面试题答案
一键面试设计思路
- 信号处理函数选择:
- 使用
sigaction
函数来设置信号处理函数。sigaction
比传统的signal
函数更强大,它能提供更细粒度的控制,并且可设置信号处理的一些标志,比如SA_RESTART
(使某些被信号中断的系统调用自动重启)。 - 对于多线程应用,需要注意信号处理函数应该是可重入的。这意味着信号处理函数不能调用不可重入的函数(如
malloc
、printf
等),因为在信号处理期间可能会打断其他线程正在执行的代码,如果调用了不可重入函数可能会导致数据不一致等问题。
- 使用
- 原子性和线程安全性:
- 原子性:通过设置信号掩码来确保信号处理期间不会被其他信号打断,从而保证原子性。在进入信号处理函数前,使用
sigprocmask
函数阻塞所有可能干扰的信号,处理完后再解除阻塞。 - 线程安全性:使用互斥锁来保护共享资源。当信号处理函数需要访问共享资源时,先获取互斥锁,处理完后释放互斥锁。对于需要等待某些条件的情况,可以使用条件变量。
- 原子性:通过设置信号掩码来确保信号处理期间不会被其他信号打断,从而保证原子性。在进入信号处理函数前,使用
- 与线程机制配合:
- 主线程负责初始化信号处理,使用
pthread_sigmask
函数在其他线程中阻塞信号,确保信号由主线程处理。 - 当主线程接收到信号时,通过条件变量通知其他线程进行相应的处理,其他线程在条件变量上等待,收到通知后获取互斥锁,处理共享资源,然后释放互斥锁。
- 主线程负责初始化信号处理,使用
关键代码片段
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
// 共享资源
int shared_variable = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
// 信号处理函数
void signal_handler(int signum) {
// 阻塞其他信号
sigset_t blocked_signals;
sigfillset(&blocked_signals);
sigprocmask(SIG_SETMASK, &blocked_signals, NULL);
// 处理信号相关逻辑,这里以修改共享变量为例
pthread_mutex_lock(&mutex);
shared_variable++;
pthread_mutex_unlock(&mutex);
// 通知其他线程
pthread_cond_broadcast(&cond);
// 解除信号阻塞
sigemptyset(&blocked_signals);
sigprocmask(SIG_SETMASK, &blocked_signals, NULL);
}
// 线程函数
void* thread_function(void* arg) {
// 阻塞信号
sigset_t blocked_signals;
sigfillset(&blocked_signals);
pthread_sigmask(SIG_BLOCK, &blocked_signals, NULL);
while (1) {
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
// 处理共享资源
printf("Thread received signal, shared variable: %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
// 设置信号处理函数
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
// 创建线程
pthread_t thread;
pthread_create(&thread, NULL, thread_function, NULL);
// 主线程逻辑,这里简单地等待信号
while (1) {
sleep(1);
}
// 清理资源
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_join(thread, NULL);
return 0;
}
这段代码实现了一个多线程应用中健壮的信号处理系统。主线程设置信号处理函数,其他线程阻塞信号并在条件变量上等待信号处理函数的通知,通过互斥锁保护共享资源。