进程信号

1.信号简介

1.用户输入命令,在shell下启动一个进程。
2.按下ctrl+c,这是键盘输入产生一个硬件中断,被os获取,解释成信号,发送给前台进程
3.前台进程收到信号,进而引起进程退出。
ps:信号是进程之间事件异步通知的一种方式,属于软中断

使用命令 kill -l 可以查看信号
在这里插入图片描述

2.产生信号的四种方式

  1. 键盘按键产生(ctrl + c…)
  2. 硬件条件产生
    硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。
  3. 软件条件产生
  4. 系统调用产生(kill)

3.信号的处理方式

  1. 忽略
  2. 默认处理行为,终止进程
  3. 捕捉信号,

4.信号的捕捉

捕捉一下2号信号使ctrl+c失效,但是可以使用其他信号中断(ctrl+\)

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

void hehe(int sig){
  printf("signal=%d\n",sig);
}

int main()
{
  signal(2,hehe);
  
  while(1);
  return 0;
}

在这里插入图片描述
ps:我们在C/C++当中除零,内存越界等异常,在系统层面上,是被当成信号处理的

5.信号捕捉流程

在这里插入图片描述

信号处理函数是一个独立的执行流,和原来的用户代码之间没有相互调用的关系 信号处理函数执行过程中,原有的执行流就在等待

6.阻塞信号

有时候信号不会立刻被处理,而是等到何时的时机在进行处理

  • 实际执行信号的处理动作称为信号递达(Delivery);
  • 信号从产生到递达之间的状态,称为信号未决(Pending);
  • 进程可以选择阻塞 (Block )某个信号;
  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作;
  • 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作;

7.可重入函数

一个函数如果在多个执行流中被调用,就可能出现问题

  • 一个函数如果可重入,就意味着在多个执行流中调用是没问题的。

  • 一个函数如果不可重入,在多个执行流中调用就是有问题的。

  • 如果一个函数使用了全局变量/静态变量,不可重入

  • 如果一个函数调用了不可重入函数,也是不可重入的,

如下创建20次子进程应该结束20次子进程打印20次child exit,可实际没有退出完,出现了僵尸进程,是因为在同时收到多个信号,只执行了一次。

    
#include<signal.h>
#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>

void hehe(int sig)
{
  printf("child exit\n");
  wait(NULL);
}
int main()
{
  //signal(SIGCHLD, SIG_IGN);
  signal(17,hehe);
  int i = 0; 
  for(;i<20; ++i){
    pid_t ret = fork();
    if(ret == 0){
      printf("hehehepid %d\n",getpid());
      exit(0);
    }
  }
  while(1)
  {
    sleep(1);
  }
  return 0;
}

在这里插入图片描述
在这里插入图片描述
//signal(SIGCHLD, SIG_IGN); 捕获信号之后
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值