面试题答案
一键面试竞争情况分析
在C语言的Linux信号处理异步通知场景中,可能出现以下竞争情况:
- 数据访问冲突:信号处理函数和主程序同时访问并修改共享变量,导致数据不一致。例如,主程序正在读取一个共享的计数器变量,在读取过程中信号处理函数对该计数器进行了修改,使得主程序读取到的数据不准确。
- 资源操作冲突:共享资源如文件描述符、内存区域等,主程序和信号处理函数可能同时尝试对其进行操作,比如同时进行写操作,导致数据混乱。
避免竞争条件的方法
- 互斥锁(Mutex):使用互斥锁可以保证在同一时间只有一个线程(在信号处理场景下可看作信号处理函数和主程序两个“线程”)能够访问共享资源。在访问共享资源前加锁,访问结束后解锁。
- 信号掩码(Signal Masking):通过设置信号掩码,在主程序访问共享资源期间阻塞相应信号,防止信号处理函数打断主程序对共享资源的操作。信号处理函数执行时也可以阻塞其他可能干扰的信号。
代码示例 - 使用互斥锁
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
// 共享资源
int shared_variable = 0;
pthread_mutex_t mutex;
// 信号处理函数
void signal_handler(int signum) {
pthread_mutex_lock(&mutex);
shared_variable++;
printf("Signal handler: shared_variable incremented to %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
}
int main() {
// 初始化互斥锁
if (pthread_mutex_init(&mutex, NULL) != 0) {
printf("\n mutex init has failed\n");
return 1;
}
// 设置信号处理函数
struct sigaction sa;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// 主程序
for (int i = 0; i < 5; i++) {
pthread_mutex_lock(&mutex);
shared_variable++;
printf("Main program: shared_variable incremented to %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
sleep(1);
}
// 销毁互斥锁
pthread_mutex_destroy(&mutex);
return 0;
}
代码示例 - 使用信号掩码
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
// 共享资源
int shared_variable = 0;
// 信号处理函数
void signal_handler(int signum) {
shared_variable++;
printf("Signal handler: shared_variable incremented to %d\n", shared_variable);
}
int main() {
// 设置信号处理函数
struct sigaction sa;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
sigset_t block_mask;
sigemptyset(&block_mask);
sigaddset(&block_mask, SIGUSR1);
// 主程序
for (int i = 0; i < 5; i++) {
sigprocmask(SIG_BLOCK, &block_mask, NULL);
shared_variable++;
printf("Main program: shared_variable incremented to %d\n", shared_variable);
sigprocmask(SIG_UNBLOCK, &block_mask, NULL);
sleep(1);
}
return 0;
}