自学内容网 自学内容网

Linux进程通讯—信号处理

进程通讯—信号处理

signal 系统调用是 UNIX 和类 UNIX 系统(如 Linux)中用于处理信号的一个基础机制。信号是软件中断,它们可以被系统或者进程发送给另一个进程或线程,以通知它们发生了某个事件。这些事件可以是硬件中断(如外部设备请求服务)、软件异常(如除零错误)、用户请求(如用户请求停止进程)等。

1.基本用法

signal 函数的原型定义在 <signal.h> 头文件中,我们可以通过 signal 系统调用注册信号处理函数:

#include <signal.h>
// 信号处理函数声明
typedef void (*sighandler_t)(int);
/**
* signal 系统调用会注册某一信号对应的处理函数。如果注册成功,当进程收到这一
信号时,将不会调用默认的处理函数,而是调用这里的自定义函数
* 
* int signum: 要处理的信号
* sighandler_t handler: 当收到对应的 signum 信号时,要调用的函数
* return: sighandler_t 返回之前的信号处理函数,如果错误会返回 SEG_ERR
*/
sighandler_t signal(int signum, sighandler_t handler);

2.性质

2.1注意事项

  1. 信号处理函数的行为:信号处理函数必须是简单的,并且必须是异步信号安全的。这意味着它只能调用异步信号安全的函数,不能执行那些可能导致死锁或数据竞争的操作,如修改全局变量(除非这些操作是原子的)。
  2. 不可重入性:如果信号处理函数在执行时被中断(例如,通过另一个信号),则原始的处理函数可能会再次被调用,这可能导致不可预测的行为。
  3. 信号掩码:在信号处理函数执行期间,会阻塞(或忽略)与当前信号相同的信号,以避免嵌套调用。但是,这不会影响其他信号。
  4. 可移植性问题:由于不同系统间对信号处理的实现细节可能存在差异,因此使用 signal 函数可能会导致可移植性问题。

2.2替代方案

由于 signal 函数存在上述的缺点,许多现代系统提供了更可靠的替代方案,如 sigaction 函数。sigaction 提供了更详细的控制,包括指定信号屏蔽集、获取信号处理函数以及设置信号处理选项等。

3.测试

//
// Created by root on 2024/9/16.
//
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sigint_handler(int signum){
    printf("捕获到信号%d\n",signum);
    exit(signum);
}

int main(int argc,char *argv[]){
    if (signal(SIGINT,sigint_handler)==SIG_ERR){
        perror("signal error");
        exit(EXIT_FAILURE);
    }
    while(1){
        sleep(1);
        printf("你好\n");
    }
    return 0;
}

在这个示例中,当接收到 SIGINT 信号(通常由用户按下 Ctrl+C 产生)时,sigint_handler 函数会被调用,程序会打印一条消息并退出。


原文地址:https://blog.csdn.net/weixin_45706195/article/details/142292081

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!