关于Linux当中的信号

引入

当你在命令行终端运行一段程序。例如,在根目录下搜索一个文件:

​
sudo find -name *abc*

执行这个命令以后,会在命令行终端打印查询到的文件。此时,如果你看到了你想要的文件,但是程序并未结束,依然在打印信息。如果你想结束它,这个时候可以按下 Ctrl + c

这个 Ctrl + c 之所以能结束程序,就是因为它向运行的这处程序发送了一个终止程序的信号,从而终止了进程。

什么是信号?

信号是事件发生时对进程的通知机制。为了与硬件上的中断进行区分,所以信号有时也称之为软件中断。信号与硬件中断的相似 之处在于打断了程序执行的正常流程。很明显,进程是无法预测信号什么时候到达的。就像前面的进程,它无法知道我什么时候会按下 Ctrl + c

一个(具有合适权限的)进程能够向另一进程发送信号。例如,终端可以向终端上的进程发送终止进程的信号。这也是为什么你关闭终端的时候,运行在终端之上的进程也会结束的原因。Linux内核也是一个进程,内核可以向所有进行发送终止进程的信号。所以你关机的时候,所有的进程都会有序结束,也是得益于这套信号机制。

进程也可以向自身发送信号,例如定时器,就是进程每隔一段时间向自己发送一个到时的信号。

这是一条每秒更新当前目录下的文件的命令

watch -n 1 ls -l

输入命令以后,当前目录下的所有文件的变化都会实时的显示到终端上。你可以尝试在另一个终端上创建或者删除一个文件,在这里就能看到变化。

这条命令的底层工作逻辑就是每隔向自己发送一个信号,然后执行一次 ls -l 命令。

信号的产生与处理

事实上,信号并不是由用户空间的进程直接产生的,不管是终端、还是运行在终端上的进程都是这样。信号是由内核产生的。也就是说信号是由内核产生,并发送给相应进程的一种软件中断机制。用户空间的进程在收到信号以后,可以选择进行默认操作。例如,你可以编写一个 while(1); 死循环的程序。当你想要结束它时,直接 Ctrl+C 就可以了。这就是一种默认操作。

除了默认操作以外,你也可以进行自定义的操作。例如,收到 Ctrl+C 以后,在屏幕上输出 Hello World! 。下面这个程序就做了这件事情:

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

void func(int arg) {
	printf("Hello World!\n");
}

int main(int argc, const char *argv[])
{
	signal(SIGINT, func);
	while(1);
	return 0;
}

此时再按下 Ctrl+C 就会发现它会输出 Hello World! 了。但是你可能不知道如何结束这个进程。最简单粗暴的办法是关掉命令行终端。当然也可以使用 kill -9 [进程号] 。进程号可以在执行 ctrl + z以后,再运行 ps 命令,可以看到以你程序名字命名的进程号了。过程如下:

$ gcc test.c -o test -Wall
$ ./test
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^CHello World!
^Z
[1]+  已停止               ./test
$ ps
    PID TTY          TIME CMD
   3165 pts/1    00:00:00 bash
   3206 pts/1    00:00:19 test
   3207 pts/1    00:00:00 ps
$ kill -9 3206
$ ps
    PID TTY          TIME CMD
   3165 pts/1    00:00:00 bash
   3220 pts/1    00:00:00 ps

值得一提的是这里使用的 kill -9 [进程号]Ctrl + Z 都是向进程发送相应的信号。从用户空间的角度,你可以认为是你通过终端向进程 3206 发送了暂停进程( Ctrl + Z )的信号和终止进程的信号( kill -9 [进程号] )。但是这些信号的管理和生产都是在内核当中进行的。例如,上面的程序当中调用了 signal() ,这个函数确切的说是Linux的一个系统调用。它的作用就是向内核注册收到这个SIGINT 信号以后的信号处理函数。如果没有这一步,我们的进程在用户按下 Ctrl + c 以后就会很自然的被结束。但是我们注册了 func() ,所以进程会执行 func 这个函数。

很明显,现在我们已经接触到了不少信号了,包括 Ctrl + Zkill -9 [进程号]Ctrl + c,除了这些信号以外还有很多常见的信号,详情可以通过 man 7 signal 了解。部分内容展示如下:

        Signal      Standard   Action   Comment
       ────────────────────────────────────────────────────────────────────────
       SIGABRT      P1990      Core    Abort signal from abort(3)
       SIGALRM      P1990      Term    Timer signal from alarm(2)
       SIGBUS       P2001      Core    Bus error (bad memory access)
       SIGCHLD      P1990      Ign     Child stopped or terminated
       SIGCLD         -        Ign     A synonym for SIGCHLD
       SIGCONT      P1990      Cont    Continue if stopped
       SIGEMT         -        Term    Emulator trap
       SIGFPE       P1990      Core    Floating-point exception
       SIGHUP       P1990      Term    Hangup detected on controlling terminal
                                       or death of controlling process

关于信号可以说的内容还有很多,例如关于信号的阻塞,实时信号等
我下个文章再继续讲解。谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值