MST
星途 面试题库

面试题:C语言动态调整信号屏蔽集对多线程程序的影响

在一个多线程的C语言程序中,主线程和子线程都可能会接收到信号。现在需要动态调整信号屏蔽集,在主线程中临时屏蔽SIGTERM信号,同时保证子线程在特定任务执行时也不受该信号干扰,但在任务完成后恢复对SIGTERM信号的响应。请描述实现思路,并给出关键代码片段,同时分析可能会遇到的同步问题及解决方案。
40.3万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 初始化信号屏蔽集:在程序开始时,创建一个信号屏蔽集并添加SIGTERM信号。
  2. 主线程临时屏蔽信号:主线程在需要时调用sigprocmask函数来临时屏蔽SIGTERM信号。
  3. 子线程特定任务屏蔽信号:子线程在执行特定任务前,调用pthread_sigmask函数屏蔽SIGTERM信号,任务完成后再调用pthread_sigmask恢复对信号的响应。

关键代码片段

#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>

sigset_t sigSet;

void* threadFunction(void* arg) {
    // 子线程屏蔽SIGTERM信号
    pthread_sigmask(SIG_BLOCK, &sigSet, NULL);

    // 特定任务
    printf("子线程执行特定任务\n");
    sleep(2);

    // 子线程恢复对SIGTERM信号的响应
    pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);

    return NULL;
}

int main() {
    pthread_t thread;

    // 初始化信号屏蔽集,添加SIGTERM信号
    sigemptyset(&sigSet);
    sigaddset(&sigSet, SIGTERM);

    // 主线程临时屏蔽SIGTERM信号
    sigprocmask(SIG_BLOCK, &sigSet, NULL);

    // 创建子线程
    if (pthread_create(&thread, NULL, threadFunction, NULL) != 0) {
        perror("pthread_create");
        return 1;
    }

    // 主线程特定操作
    printf("主线程执行操作\n");
    sleep(2);

    // 主线程恢复对SIGTERM信号的响应
    sigprocmask(SIG_UNBLOCK, &sigSet, NULL);

    // 等待子线程结束
    if (pthread_join(thread, NULL) != 0) {
        perror("pthread_join");
        return 1;
    }

    return 0;
}

可能遇到的同步问题及解决方案

  1. 同步问题:主线程和子线程可能在信号屏蔽和恢复的时机上出现竞争条件,导致信号在不期望的时刻被处理。
  2. 解决方案
    • 使用互斥锁(pthread_mutex_t)来保护对信号屏蔽集的操作,确保在同一时间只有一个线程可以修改信号屏蔽集。
    • 使用条件变量(pthread_cond_t)来同步主线程和子线程的操作,例如在主线程等待子线程完成特定任务后再恢复对信号的响应。
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>

sigset_t sigSet;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int taskCompleted = 0;

void* threadFunction(void* arg) {
    // 子线程屏蔽SIGTERM信号
    pthread_mutex_lock(&mutex);
    pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
    pthread_mutex_unlock(&mutex);

    // 特定任务
    printf("子线程执行特定任务\n");
    sleep(2);

    // 任务完成
    pthread_mutex_lock(&mutex);
    taskCompleted = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

    // 子线程恢复对SIGTERM信号的响应
    pthread_mutex_lock(&mutex);
    pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);
    pthread_mutex_unlock(&mutex);

    return NULL;
}

int main() {
    pthread_t thread;

    // 初始化信号屏蔽集,添加SIGTERM信号
    sigemptyset(&sigSet);
    sigaddset(&sigSet, SIGTERM);

    // 主线程临时屏蔽SIGTERM信号
    pthread_mutex_lock(&mutex);
    sigprocmask(SIG_BLOCK, &sigSet, NULL);
    pthread_mutex_unlock(&mutex);

    // 创建子线程
    if (pthread_create(&thread, NULL, threadFunction, NULL) != 0) {
        perror("pthread_create");
        return 1;
    }

    // 主线程等待子线程任务完成
    pthread_mutex_lock(&mutex);
    while (!taskCompleted) {
        pthread_cond_wait(&cond, &mutex);
    }
    pthread_mutex_unlock(&mutex);

    // 主线程恢复对SIGTERM信号的响应
    pthread_mutex_lock(&mutex);
    sigprocmask(SIG_UNBLOCK, &sigSet, NULL);
    pthread_mutex_unlock(&mutex);

    // 等待子线程结束
    if (pthread_join(thread, NULL) != 0) {
        perror("pthread_join");
        return 1;
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}