进程信号

Posted 李憨憨_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程信号相关的知识,希望对你有一定的参考价值。

进程信号


  概念:信号就是软件中断,信号就是用于向进程通知某个事件的产生,打断进程当前操作,去处理这个事件。

1.操作系统中信号的种类

在这里插入图片描述

2.代码演示

Linux中信号的种类: 62种
 1~31: 非可靠信号(有可能造成事件丢失)
 34~64: 可靠信号(不会丢失事件) 信号的生命周期:产生信号->在进程pcb中注册信号->注销账号->处理信号 信号的产生:  硬盘产生:ctrl + c, ctrl + |, ctrl + z;  软件产生:kill命令发送信号给指定进程 kill -signum pid     kill命令杀死一个进程的原理:默认给进程发送了终止信号;
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 int main()
  5 {
  6     while(1){
  7         sleep(1);
  8         printf("---------\\n");
  9     }
 10     return 0;
 11 }

在这里插入图片描述

ctrl + z: 发送一个停止信号, 让程序停止运行
进程并没有退出只是停止运行了
在这里插入图片描述

程序依然运行在后台;
kill: 给进程发送一个终止信号
在这里插入图片描述
进程退出
在这里插入图片描述
在这里插入图片描述
当使用Ctrl + z, 进程终止之后, 进程就不会再去处理信号了, 所以此时使用kill就不会杀死这个进程.
此时可以使用kill -9, 来杀死这个进程, kill -9 , 就是给进程发送9号命令.

int kill(pid_t pid, int sig);

在这里插入图片描述

给pid进程发送sig信号

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<signal.h>
  5 int main()
  6 {   
  7     //kill(进程ID, 信号值)
  8     kill(getpid(), SIGINT);
  9     while(1){
 10         printf("-------\\n");
 11         sleep(1);
 12     }
 13     return 0;
 14 }

在这里插入图片描述

程序直接退出;
int raise(int sig);–给进程自身发送一个指定的信号
unsigned int alarm(unsidned int second);–sec秒之后给进程自身发送一个时钟信号–SIGALRM
void abort(void);–给进程自身发送一个SIGABRT信号

3.库函数接口

int sigqueue(pid_t pid, int sig, const union sigval value)

给一个进程发送信号的同时携带一个数据过去

4.信号注册, 注销, 处理

注册: 在进程中注册一个信号让进程知道自己收到了某个信号
修改Pending位图,添加一个信号信息节点

在这里插入图片描述


注销:将信号信息进程pcb中移除(修改位图,删除节点)
 非可靠:删除节点,修改位图为0
 可靠:删除信号节点,检查链表中是否还有相同节点,没有则修改位图
处理:信号的处理也叫信号的递达,实际上就是打断进程当前的操作,去执行进程的对应信号处理函数
 信号的处理方式:
   1.默认处理方式
   2.忽略处理方式
   3.自定义处理方式–用户自己定义信号的处理回调函数

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signum:信号值-表示要修改那个信号的处理方式
handler:新的信号处理方式
SIG_DFL-默认; SIG_IGN-忽略; 自定义函数名称
返回值:成功则返回当前信号原来的处理方式,失败则返回SIG_ERR;

5.自定义信号方式的基本使用


演示:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<signal.h>
  5 int main()
  6 {
  7     //signal(信号, 处理方式)
  8     signal(SIGINT, SIG_IGN);
  9     //kill(进程ID, 信号值)
 10     //kill(getpid(), SIGINT);
 11     raise(SIGINT);
 12     while(1){
 13         printf("-------\\n");
 14         sleep(1);
 15     }
 16     return 0;
 17 }

在这里插入图片描述
此时虽然调用raise但程序并未终止
在这里插入图片描述
因为调用signal将SIGINT信号忽略了;
只能使用Ctrl+\\退出信号将进程退出
在这里插入图片描述

  5 void sigcb(int signo)
  6 {
  7     printf("recv signal:%d\\n", signo);
  8 }
 12     signal(SIGINT, sigcb);

Ctrl+c向进程发送一个2号信号
在这里插入图片描述

6.自定义处理方式的信号捕捉流程

在这里插入图片描述

7.阻塞

阻塞:信号的阻塞--阻止信号被递达--一个信号被阻塞后,依然收到这个信号会注册,但是暂时不被处理
pcb中有pending位图-未决信号结合; 还有阻塞信号集合, 如果要阻塞一个信号,就是在进程的阻塞信号集合中标记这个信号
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

在这里插入图片描述


how:操作类型
 SIG_BLOCK–阻塞set集合中的信号 block=block | set
 SIG_UNBLOCK–将set集合中的信号解除阻塞block&=~set
 SIG_SETMASK–将set集合中的信号设置为阻塞集合的信号block = set
返回值:成功返回0;失败返回-1;

以上是关于进程信号的主要内容,如果未能解决你的问题,请参考以下文章

代码片段:Shell脚本实现重复执行和多进程

进程相互作用之信号量PV操作及其代码实现

信号量机制实现进程互斥同步前驱关系

linux进程间通信之Posix 信号量用法详解代码举例

信号处理程序代码会阻塞主进程吗?

请教一个Linux下C语言的进程间的信号问题