MST

星途 面试题库

面试题:C语言Linux信号集操作在多线程环境下的复杂应用

在多线程Linux C语言程序中,不同线程可能需要处理不同的信号集。例如,主线程负责处理SIGTERM信号来进行优雅的程序关闭,而某个工作线程需要处理SIGUSR1信号来执行特定的任务。请设计一个多线程程序框架,展示如何在不同线程中分别设置和处理不同的信号集,同时要考虑线程间信号传递可能出现的竞态条件以及如何避免。详细说明涉及的信号集操作函数以及线程同步机制,并给出完整且可运行的代码示例。
28.2万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

1. 信号集操作函数

  • sigemptyset:初始化一个空的信号集。
  • sigaddset:将指定信号添加到信号集中。
  • sigprocmask:设置当前进程的信号掩码,用于阻塞或解除阻塞信号。
  • sigwait:等待信号集中的信号到达。

2. 线程同步机制

使用互斥锁(pthread_mutex_t)来避免竞态条件。在访问共享资源(如信号处理相关的变量)时,先锁定互斥锁,操作完成后解锁。

3. 完整代码示例

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

// 互斥锁
pthread_mutex_t mutex;

// 用于主线程的信号集
sigset_t main_signal_set;
// 用于工作线程的信号集
sigset_t worker_signal_set;

// 工作线程函数
void* worker_thread(void* arg) {
    int signum;

    // 等待SIGUSR1信号
    while (1) {
        pthread_mutex_lock(&mutex);
        int res = sigwait(&worker_signal_set, &signum);
        pthread_mutex_unlock(&mutex);

        if (res != 0) {
            printf("sigwait failed\n");
            pthread_exit(NULL);
        }

        if (signum == SIGUSR1) {
            printf("Worker thread received SIGUSR1. Performing specific task...\n");
        }
    }
}

int main() {
    pthread_t worker_tid;

    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);

    // 初始化主线程信号集
    sigemptyset(&main_signal_set);
    sigaddset(&main_signal_set, SIGTERM);

    // 初始化工作线程信号集
    sigemptyset(&worker_signal_set);
    sigaddset(&worker_signal_set, SIGUSR1);

    // 设置主线程信号掩码,阻塞SIGTERM
    pthread_sigmask(SIG_BLOCK, &main_signal_set, NULL);

    // 设置工作线程信号掩码,阻塞SIGUSR1
    pthread_sigmask(SIG_BLOCK, &worker_signal_set, NULL);

    // 创建工作线程
    if (pthread_create(&worker_tid, NULL, worker_thread, NULL) != 0) {
        printf("\n ERROR creating thread");
        return 1;
    }

    int signum;
    // 主线程等待SIGTERM信号
    while (1) {
        pthread_mutex_lock(&mutex);
        int res = sigwait(&main_signal_set, &signum);
        pthread_mutex_unlock(&mutex);

        if (res != 0) {
            printf("sigwait failed\n");
            return 1;
        }

        if (signum == SIGTERM) {
            printf("Main thread received SIGTERM. Shutting down gracefully...\n");
            break;
        }
    }

    // 等待工作线程结束
    pthread_join(worker_tid, NULL);

    // 清理互斥锁
    pthread_mutex_destroy(&mutex);

    return 0;
}

4. 代码说明

  • 初始化信号集:分别为main_signal_setworker_signal_set初始化并添加相应信号。
  • 设置信号掩码:通过pthread_sigmask阻塞主线程的SIGTERM信号和工作线程的SIGUSR1信号,避免信号在设置处理函数前被意外处理。
  • 创建线程:创建工作线程,在工作线程中通过sigwait等待SIGUSR1信号。
  • 主线程处理:主线程通过sigwait等待SIGTERM信号,接收到信号后执行优雅关闭操作。
  • 互斥锁使用:在调用sigwait时,使用互斥锁来避免在信号等待过程中可能出现的竞态条件。