面试题答案
一键面试1. 资源清理顺序
在清理系统资源时,通常遵循以下顺序:
- 套接字:关闭套接字以释放网络资源,防止数据泄露或未完成的连接。
- 文件描述符:关闭打开的文件描述符,确保文件系统状态正常,避免数据丢失。
- 共享内存段:解除映射并释放共享内存,防止内存泄漏。
2. 可能出现的竞态条件及解决方案
- 竞态条件:在多进程或多线程环境下,多个进程或线程可能同时尝试访问和修改共享资源,导致数据不一致或程序崩溃。例如,一个线程正在清理共享内存,而另一个线程同时尝试访问该共享内存。
- 解决方案:
- 信号掩码:在进入信号处理函数前,屏蔽SIGINT信号,防止在处理信号过程中再次接收到该信号,导致重入问题。
- 互斥锁:对于共享资源的访问,使用互斥锁(pthread_mutex_t)来保证同一时间只有一个线程可以访问和修改共享资源。
3. 代码示例
以下是一个简单的C语言示例,展示如何实现上述要求:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SHM_SIZE 1024
// 共享内存结构体
typedef struct {
int data;
} SharedData;
// 全局变量
SharedData *shared_memory;
int socket_fd;
int shmid;
pthread_mutex_t mutex;
// 信号处理函数
void sigint_handler(int signum) {
// 屏蔽SIGINT信号
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_BLOCK, &set, NULL);
// 清理套接字
close(socket_fd);
// 清理共享内存
pthread_mutex_lock(&mutex);
shmdt(shared_memory);
shmctl(shmid, IPC_RMID, NULL);
pthread_mutex_unlock(&mutex);
// 解除信号屏蔽
sigprocmask(SIG_UNBLOCK, &set, NULL);
// 退出程序
exit(0);
}
// 模拟工作线程
void* worker_thread(void* arg) {
while (1) {
// 模拟工作
pthread_mutex_lock(&mutex);
shared_memory->data++;
pthread_mutex_unlock(&mutex);
sleep(1);
}
return NULL;
}
int main() {
// 初始化互斥锁
pthread_mutex_init(&mutex, NULL);
// 创建共享内存
key_t key = ftok(".", 'a');
shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
shared_memory = (SharedData*)shmat(shmid, NULL, 0);
shared_memory->data = 0;
// 创建套接字
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8080);
servaddr.sin_addr.s_addr = INADDR_ANY;
bind(socket_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(socket_fd, 5);
// 设置信号处理函数
struct sigaction sa;
sa.sa_handler = sigint_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
// 创建工作线程
pthread_t tid;
pthread_create(&tid, NULL, worker_thread, NULL);
// 主线程等待
while (1) {
sleep(1);
}
// 清理资源(理论上不会执行到这里)
pthread_mutex_destroy(&mutex);
close(socket_fd);
shmdt(shared_memory);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
4. 信号处理函数与其他模块协同工作
- 信号处理函数:负责捕获SIGINT信号,并按照预定顺序清理系统资源。在清理共享资源时,通过互斥锁确保资源的安全访问。
- 其他模块:如工作线程,在访问共享资源时,先获取互斥锁,完成操作后释放互斥锁,与信号处理函数协同工作,保证系统资源的深度优化和程序的优雅退出。