linux信号在多线程中的使用1

sigaction

        sigaction 函数主要用于在一个进程内部对信号进行处理和管理。它允许进程注册自定义的信号处理函数,来应对接收到的信号。在多线程编程中,sigaction 函数也可以用于线程中对信号的处理。虽然信号是进程级别的通信机制,但在某些情况下,线程也可以捕获和处理信号。

        sigaction原型:

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

        signum:要操作的信号编号;

        act:新的信号处理方式,包括信号处理函数、信号掩码、标志等;

        oldact:旧的信号处理方式。

        注册信号处理函数:每个线程可以通过sigaction 函数注册自己的信号处理函数,以捕获特定信号。以下是注册信号处理函数的一般步骤:

#include <signal.h>

void sig_handler(int signum) {
    // 处理信号的代码
}

struct sigaction sa;
sa.sa_handler = sig_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;

// 注册信号处理函数
if (sigaction(SIGINT, &sa, NULL) == -1) {
    perror("Error registering signal handler");
    exit(1);
}

        在上述例子中,我们定义了一个名为sig_handler的信号处理函数。通过sigaction 函数,我们将SIGINT信号的处理函数设置为sig_handler。

        注意:各线程独立处理信号:在多线程环境中,每个线程可以独立注册和处理信号。这意味着当某个线程捕获到信号时,其他线程不会被此信号打断。

pthread_sigmask 

        该函数与sigprocmask()不同的是,一般采用pthread_mask来屏蔽或者解除某个线程对某个信号的处理。具体用法是将自定义信号集设置给阻塞信号集(blocked位向量)。

int pthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask);

        1.how:表示对信号屏蔽字的修改方式,有以下几种取值:

        SIG_BLOCK:将set中指定的信号添加到线程的信号屏蔽字中,即屏蔽这些信号,即追加屏蔽字。
        SIG_UNBLOCK:将set中指定的信号从线程的信号屏蔽字中移除,即允许接收这些信号。
        SIG_SETMASK:将set中指定的信号设置为线程的新信号屏蔽字,即覆盖原屏蔽字。
        2.set:指向一个sigset_t类型的信号集,用于指定需要修改/设置的信号。

        3.oldset:指向一个sigset_t类型的信号集,用于存储修改前的旧信号屏蔽字。如果不需要保存旧的信号屏蔽字,可以传入NULL。

pthread_kill

        该函数用于向指定的线程发送信号。

int pthread_kill(pthread_t thread, int sig);

        函数参数的含义如下:

  • thread: 要发送信号的目标线程的标识符。pthread_t类型是一个线程标识符的数据类型,通常是一个无符号整数。可以通过pthread_create创建线程时返回的线程标识符或使用pthread_self函数获取当前线程的标识符。
  • sig: 要发送的信号的编号。可以是标准的POSIX信号编号,如SIGUSR1SIGUSR2等,也可以是其他自定义的信号编号。

函数返回值:

如果成功发送信号,则返回0。如果发生错误,则返回相应的错误代码。

在使用pthread_kill函数发送信号时需要注意以下几点:

  1. 信号只能发送给同一进程中的其他线程,不能发送给不同进程的线程。
  2. 接收到信号的线程需要先设置相应的信号处理函数,以便在接收到信号时执行相应的操作。
  3. 如果线程在设置了信号处理函数之前收到了信号,信号会被默认处理。

        示例:

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

void signal_handler(int signal) {
    printf("Received signal: %d\n", signal);
    printf("Terminating the current thread...\n");
    pthread_exit(NULL);
}

void* thread_func(void* arg) {
    // 设置信号屏蔽字
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    pthread_sigmask(SIG_BLOCK, &mask, NULL);

    // 注册信号处理函数
    signal(SIGINT, signal_handler);

    // 等待信号
    int received_signal;
    sigwait(&mask, &received_signal);
    printf("Signal received: %d\n", received_signal);

    // 解除信号屏蔽
    pthread_sigmask(SIG_UNBLOCK, &mask, NULL);

    return NULL;
}

int main() {
    // 创建线程
    pthread_t thread;
    if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
        fprintf(stderr, "Failed to create thread\n");
        return 1;
    }

    // 在一段时间后向子线程发送SIGINT信号
    sleep(5);
    pthread_kill(thread, SIGINT);

    // 等待线程结束
    pthread_join(thread, NULL);

    return 0;
}

        子线程首先使用pthread_sigmaskSIGINT信号添加到信号屏蔽字中,阻塞SIGINT信号的传递。然后,子线程注册了信号处理函数signal_handler用来处理SIGINT信号。子线程通过调用sigwait函数来等待信号的到达。当SIGINT信号到达时,sigwait函数会返回,并将信号值存储在received_signal变量中。接着,子线程使用pthread_sigmask解除信号屏蔽,允许后续SIGINT信号的传递。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值