Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验

  上一节介绍进程间通信方式之一信号通信中的信号产生和捕捉函数,这一节介绍信号处理函数signal()函数和信号集函数组,接上一节http://blog.csdn.net/mybelief321/article/details/9078193

强烈建议做最后一个实验!

信号处理方法

   信号处理的方法主要有以下两种:

   ①  使用 signal() 函数;

   ②  使用信号集函数组。

使用signal()函数

函数说明

    使用signal()函数处理时,只需指出要处理的信号和处理函数即可。它主要用于前32种非实时信号的处理,不支持信号传递信息。Linux还支持一个更健壮更新的信号处理函数呢,它就是 sigaction(),推荐使用这个函数。

函数格式

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第1张图片

    这里 signal() 这个函数的原型我当时看了头有点大,还是先说明一下:首先该函数原型整体指向一个无返回值并且带一个整形参数的函数指针,也就是信号的原始配置函数;接着该原型又带有两个参数,其中第2个参数可以是用户自定义的信号处理函数的函数指针。不明白也没事,后边做实验就明白了,会用就行了。

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第2张图片

  这里要说明的是 sigaction()函数中第2个和第3个参数用到的 sigaction 结构,下表为 siaction的定义:

  Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第3张图片

   sa_handler 是一个函数指针,指定信号处理函数,这里除可以是咱们自定义的处理函数外,还可以为SIG_DFL(采用默认的处理方式)或SIG_IGN(忽略信号)。它的处理函数只有一个参数,即信号值。

   sa_mask 是一个信号集,它可以指定在信号处理程序执行过程中哪些信号应当被屏蔽,在调用信号捕获函数前,该信号集要加入到信号的信号屏蔽字中。

   sa_flags 中包含了很多标志位,是对信号进行处理的各个选择项。它的常见可选值如下表所示:

  Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第4张图片

基础实验1

   本实验是表明如何使用 signal()函数捕捉相应信号,并做出给定的处理。这里,my_func就是信号处理的函数指针,咱们也可以将其改为SIG_IGN或SIG_DFL查看运行结果。实验代码如下:

   signal.c文件点此下载

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第5张图片

  编译运行后出现如下的结果:

  Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第6张图片

  此时程序被挂起,一直等待信号。

  如果在键盘上按下  Ctrl+c  组合键,结果如下

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第7张图片

  如果在键盘上按下  Ctrl+\  组合键,结果如下

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第8张图片

  可见进程收到相应的信号后,转去执行咱们自定义函数了。你可以将my_func换为SIG_IGN或者SIG_DFL,看看有什么不同。

基础实验2

   本实验实现的功能同实验1一样,只不过是换成了sigaction()函数,程序如下

    sigaction.c文件点此下载

  Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第9张图片

    编译运行后结果如下

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第10张图片

    第一次按组合键“Ctrl+c”,结果如下

    Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第11张图片       

    第二次按组合键“Ctrl+c”,结果如下

    Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第12张图片

   我建议你把25行的换成SA_RESTARTHAND等试一试,会加深理解的

信号集函数组

函数说明

  使用信号集函数组处理信号时设计一系列的函数,这些函数按照先后的调用次序可分为以下几大模块:创建信号集、注册信号处理函数及检测信号。

  其中,创建信号集主要用于处理用户感兴趣的一些信号,其函数包括以下几个:

  ●  sigemptyset(): 将信号集初始化为空

  ●  sigfillset(): 将信号集初始化为包含所有已定义的信号集

  ●  sigaddset(): 将指定信号加入到信号集中

  ●  sigdelset(): 将指定信号从信号集中删除

  ●  sigismember(): 查询指定信号是否在信号集中

   注册信号处理函数主要用于决定进程如何处理信号。这里要注意的是,信号集里的信号并不是真正可以处理的信号,只有当信号的状态处于非阻塞状态时才会真正起作用。因此,首先使用 sigprocmask() 函数检测并更改信号屏蔽字(信号屏蔽字是用来指定当前被阻塞的一组信号,它们不会被进程接收),然后使用 sigaction()函数来定义进程接收到特定信号后的行为。

   检测信号是信号处理的后续步骤,因为被阻塞的信号不会传递给进程,所以这些信号就处于“未处理”状态(也就是进程不清除它的存在)。sigaction()函数允许进程检测“未处理”信号,并进一步决定对它们做何处理。

函数格式

    Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第13张图片

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第14张图片

    在sigprocmask()中,若set 是一个非空指针,则参数 how 表示函数的操作方式;若how为空,则表示忽略此操作。

    Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第15张图片

    总之,在处理信号时,一般遵循下图所示的操作流程

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第16张图片

基础实验3(强烈建议做这个实验啊)

   该实验首先把 SIGQUIT、SIGINT两个信号加入信号集,然后将该信号集设为阻塞状态,并进入用户输入状态。咱们只需要按任意键,就可以将信号集设置为非阻塞状态,再对这两个信号分别操作,其中SIGQUIT执行默认操作,而SIGINT执行用户自定义函数的操作。

   sigset.c文件点此下载  

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第17张图片

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第18张图片

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第19张图片

   编译运行结果如下

   

   按任意键

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第20张图片

  接着按组合键:Ctrl+c

  Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第21张图片

  接着按组合键:Ctrl+\

   Linux进程间通信(五)---信号通信之signal()、信号集函数组及其基础实验_第22张图片

  如果在运行时,先直接按组合键:Ctrl+\,结果如下

  

 对比结果可以看到,在新号处于阻塞状态时,所发出的信号对进程不起作用,并且该信号进入待处理状态。按下任意键,信号脱离了阻塞状态时,咱们发出的信号才能正常运行。这里SIGINT已经按照咱们自定义的函数运行。

  

转自请注明出处:http://blog.csdn.net/mybelief321/article/details/9079145

你可能感兴趣的:(信号通信,信号集)