Linux 信号是怎么让程序响应事件和控制进程

AI 概述
Linux信号是进程间异步通信的软中断机制,用于通知进程事件,不传递数据。文中介绍SIGINT、SIGKILL等常见信号及编号、默认行为,讲解内核、kill命令等发送方式,以及默认、捕获、忽略三种处理方式,并给出C语言处理示例。同时介绍sigprocmask阻塞与解除阻塞信号的用法,是开发多进程、实时响应程序的重要基础。
目录
文章目录隐藏
  1. 一、信号的基本概念
  2. 二、常见信号
  3. 三、信号发送
  4. 四、信号的处理
  5. 五、信号的阻塞与解除阻塞

Linux 信号是怎么让程序响应事件和控制进程

在 Linux 中,signal(信号)是一种用于进程间通信的机制,用于通知进程发生了某些事件。信号可以由操作系统内核、其他进程或自身发送,并且可以用于控制进程的行为。以下是对 Linux 信号的一个简要概述,包括信号的类型、用法、处理和示例。

一、信号的基本概念

signal 信号是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用 kill 发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。

二、常见信号

使用kill -l命令就可以查看所有的信号,常见信号如下表:

信号名 信号编号 产生原因 默认处理方式
SIGHUP 1 关闭终端 终止
SIGINT 2 ctrl + c 终止
SIGQUIT 3 ctrl + \ 终止+产生 1 个转储文件
SIGABRT 6 abort()函数 终止+转储
SIGPE 8 算术错误 终止
SIGKILL 9 kill -9 pid 终止,不可捕获/忽略
SIGUSR1 10 自定义 忽略
SIGSEGV 11 段错误 终止+产生 1 个转储文件
SIGUSR2 12 自定义 忽略
SIGALRM 14 alarm()函数 终止
SIGTERM 15 kill pid 终止(可以被忽略)
SIGCHLD 17 子状态变化 忽略
SIGSTOP 19 ctrl + z 暂停,不可捕获/忽略

三、信号发送

信号可以通过多种方式发送:

  • 由操作系统内核发送:如当进程发生除零错误时。
  • 由其他进程发送:使用 kill 命令或 kill() 系统调用。
  • 由自身发送:使用 raise() 函数。

示例:

kill -signal pid

signal 是要传递的信号的数字或名称,pid  是信号应该发送到的进程 ID。

例如,如果要向一个进程发送 kill 信号,可以使用以下命令

kill -9 1231

kill -9 代表的信号是 SIGKILL,表示进程被终止,需要立即退出。进程 ID 为 1231 进程将退出。

四、信号的处理

进程可以选择如何处理接收到的信号。主要的处理方式有三种:

  • 默认处理:每个信号都有一个默认的处理方式,例如 SIGKILL 会强制终止进程。
  • 捕获信号:进程可以注册一个信号处理函数,执行自定义逻辑。例如,当接收到 SIGINT 时,可以选择清理资源后退出。
  • 忽略信号:进程可以选择不处理某些信号,例如忽略 SIGPIPE。

程序中怎么使用,举个示例:

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

void signal_handler(int signum) {
    printf("Received signal %d\n", signum);
    exit(0);
}

int main() {
    // 注册 SIGINT 信号的处理函数
    signal(SIGINT, signal_handler);
    while (1) {
        printf("Running... Press Ctrl+C to stop.\n");
        sleep(1);
    }
    return 0;
}

上面的程序在终端中运行,键盘按 Ctrl+c,程序就终端,注册函数打印。

五、信号的阻塞与解除阻塞

进程可以选择屏蔽某些信号,以防止在特定代码段中被打断。可以使用 sigprocmask() 函数来实现信号的阻塞和解除阻塞。

代码示例:

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

void signal_handler(int signum) {
    printf("Received signal %d\n", signum);
}

int main() {
    // 注册信号处理函数
    signal(SIGINT, signal_handler);
    // 阻塞 SIGINT 信号
    sigset_t newset, oldset;
    sigemptyset(&newset);
    sigaddset(&newset, SIGINT);
    sigprocmask(SIG_BLOCK, &newset, &oldset);
    printf("SIGINT is blocked. Press Ctrl+C.\n");
    sleep(5); // 等待 5 秒
    // 解除阻塞
    sigprocmask(SIG_UNBLOCK, &newset, NULL);
    printf("SIGINT is unblocked. Press Ctrl+C.\n");
    while (1) {
        sleep(1);
    }
    return 0;
}

学习 Linux ,了解信号是非常重要的,从事开发的小伙伴在编写多进程或需要实时响应的应用程序时,理解和掌握信号的使用是必不可少的。

以上关于Linux 信号是怎么让程序响应事件和控制进程的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Linux 信号是怎么让程序响应事件和控制进程

发表回复