Linux内核进程管理子系统有什么第十八回 —— 进程主结构详解(14)

接前一篇文章: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函数至今依旧记忆犹新,一辈子也不会忘记。

好了,信号相关的简单应用例程就讲完了。下一回讲复杂的信号应用例程。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝天居士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值