面试题答案
一键面试设计思路
- 信号处理函数设计:信号处理函数应尽量简单,避免复杂操作,防止阻塞其他信号处理或干扰主线程及其他线程。通常信号处理函数只是设置一个标志位,告知主线程或相关线程信号已到达。
- 线程安全考虑:对于共享资源(如文件描述符、全局变量等),在多线程环境下访问时,需要使用互斥锁(
pthread_mutex_t
)或读写锁(pthread_rwlock_t
)来保证线程安全。 - 文件I/O操作:在信号处理函数可能打断文件I/O操作的情况下,可以使用
fcntl
设置文件描述符为非阻塞模式,或者使用aio
系列异步I/O函数,以避免信号处理函数打断阻塞的I/O操作导致的数据一致性问题。 - 同步机制:使用条件变量(
pthread_cond_t
)来实现线程间的同步,确保在合适的时机处理信号相关的任务。
核心代码框架
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
// 定义标志位
volatile sig_atomic_t sigusr1_received = 0;
volatile sig_atomic_t sigusr2_received = 0;
// 定义互斥锁和条件变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
// 信号处理函数
void sigusr1_handler(int signum) {
pthread_mutex_lock(&mutex);
sigusr1_received = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void sigusr2_handler(int signum) {
pthread_mutex_lock(&mutex);
sigusr2_received = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
// 线程函数示例
void* thread_function(void* arg) {
while (1) {
pthread_mutex_lock(&mutex);
while (!sigusr1_received &&!sigusr2_received) {
pthread_cond_wait(&cond, &mutex);
}
if (sigusr1_received) {
// 处理SIGUSR1相关任务
printf("Handling SIGUSR1\n");
sigusr1_received = 0;
}
if (sigusr2_received) {
// 处理SIGUSR2相关任务
printf("Handling SIGUSR2\n");
sigusr2_received = 0;
}
pthread_mutex_unlock(&mutex);
// 执行其他任务
}
return NULL;
}
int main() {
// 注册信号处理函数
struct sigaction sa;
sa.sa_handler = sigusr1_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
sa.sa_handler = sigusr2_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR2, &sa, NULL);
// 创建线程
pthread_t tid;
pthread_create(&tid, NULL, thread_function, NULL);
// 主线程执行文件I/O等其他任务
int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
if (fd == -1) {
perror("open");
return 1;
}
// 设置文件描述符为非阻塞模式
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
// 主线程继续执行其他任务
while (1) {
// 执行文件I/O操作
write(fd, "data", 4);
// 其他任务
sleep(1);
}
// 清理资源
pthread_cancel(tid);
pthread_join(tid, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
close(fd);
return 0;
}
在上述代码中:
- 定义了两个标志位
sigusr1_received
和sigusr2_received
,用于标记信号是否到达。 - 使用互斥锁
mutex
和条件变量cond
来实现线程间的同步。 - 信号处理函数
sigusr1_handler
和sigusr2_handler
在接收到信号时设置标志位并通过条件变量通知相关线程。 - 线程函数
thread_function
等待信号相关标志位被设置,并处理相应任务。 - 主线程执行文件I/O操作,并将文件描述符设置为非阻塞模式,以避免信号打断阻塞的I/O操作。最后清理相关资源。