MST
星途 面试题库

面试题:C语言Linux信号处理异步通知的竞争条件处理

在C语言的Linux信号处理异步通知场景中,可能会出现竞争条件,比如信号处理函数和主程序同时访问共享资源。请分析可能出现的竞争情况,并阐述如何使用互斥锁或其他机制来避免这些竞争条件,给出代码示例。
18.3万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

竞争情况分析

在C语言的Linux信号处理异步通知场景中,可能出现以下竞争情况:

  1. 数据访问冲突:信号处理函数和主程序同时访问并修改共享变量,导致数据不一致。例如,主程序正在读取一个共享的计数器变量,在读取过程中信号处理函数对该计数器进行了修改,使得主程序读取到的数据不准确。
  2. 资源操作冲突:共享资源如文件描述符、内存区域等,主程序和信号处理函数可能同时尝试对其进行操作,比如同时进行写操作,导致数据混乱。

避免竞争条件的方法

  1. 互斥锁(Mutex):使用互斥锁可以保证在同一时间只有一个线程(在信号处理场景下可看作信号处理函数和主程序两个“线程”)能够访问共享资源。在访问共享资源前加锁,访问结束后解锁。
  2. 信号掩码(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;
}