接前一篇文章:Linux内核进程管理子系统有什么第十七回 —— 进程主结构详解(13)
本文内容参考:
Linux内核进程管理专题报告_linux rseq-CSDN博客
《趣谈Linux操作系统 核心原理篇:第三部分 进程管理》—— 刘超
《图解Linux内核 基于6.x》 —— 姜亚华 机械工业出版社
特此致谢!
进程管理核心结构 —— task_struct
3. 信号处理相关成员
上一回开始讲解task_struct结构中信号处理相关的成员,包括:
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct __rcu *sighand;
sigset_t blocked;
sigset_t real_blocked;
/* Restored if set_restore_sigmask() was used: */
sigset_t saved_sigmask;
struct sigpending pending;
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;
为了更好地理解这些字段,上一回开始对于信号相关知识进行知识补强。本回继续上一回的内容,结合信号应用例程讲解信号处理的(常见)流程。
信号处理流程
信号处理的流程主要分为两步:
1)注册信号处理函数;
2)发送信号。
下边结合两个信号处理的应用例程,对此进行深入理解。
- 例程1 —— 简单应用例程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void signal_handler(int signo)
{
if (signo == SIGINT)
{
printf("Received SIGINT signal, exiting...\n");
exit(0);
}
}
int main(int argc, char *argv[])
{
signal(SIGINT, signal_handler);
while(1)
{
printf("Main process running ...\n");
sleep(1);
}
return 0;
}
在终端下编译并运行此代码生成的程序,如下所示:
ph@ph-virtual-machine:~/shiyan$ gcc signal_simple_example.c -o signal_simple_example
ph@ph-virtual-machine:~/shiyan$ ./signal_simple_example
Main process running ...
Main process running ...
按Ctrl+C,结果如下所示:
$ ./signal_simple_example
Main process running ...
Main process running ...
Main process running ...
Main process running ...
^CReceived SIGINT signal, exiting...
程序员甚至是懂点Linux的人一般都知道,要结束某一个进程,通常按Ctrl+C即可结束。实际上Ctrl+C是向进程发送SIGINT信号,终止进程。
由上一回所讲的Linux对每种信号都规定了默认的处理动作可知,SIGINT对应的Action是Term,即终止进程。
如果不想让某个信号执行系统默认操作(动作),一种方法就是对该信号注册相应的信号处理函数,设置信号处理方式的是signal函数。上边例程代码中就是通过signal函数注册了(将默认处理函数修改为)signal_handler函数。通过上边例程的执行结果就可以看到,按下Ctrl+C发送SIGINT信号后,打印出了"Received SIGINT signal, exiting...",说明确实进入了signal_handler函数。如果没有通过signal设置,则按住Ctrl+C发送SIGINT信号虽然也能够结束进程,但是是没有这一打印的。
这里也讲一下signal函数,该函数原型如下:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
合并起来就是:
void (*signal(int signum, void (*handler)(int)))(int);
笔者对这个signal函数是有情结的。话说那是15年前(2010年)参加华清远见培训的时候,讲到信号这一块时(当年印象中signal函数还没有上边那种typedef的形式、就是下边一行的形式),这一部分的主讲人曾宏安老师提出了一个问题:signal函数这样的形式说明了什么?那个时候还是刚刚由单片机转行Linux,想了很久也没想明白,后来曾老师说:这个形式说明signal是一个指针函数,它的返回值是一个函数指针。就是这一句话,瞬间感觉醍醐灌顶、认识和水平上升了一个层次,因此这个signal函数至今依旧记忆犹新,一辈子也不会忘记。
好了,信号相关的简单应用例程就讲完了。下一回讲复杂的信号应用例程。