Linux — 进程信号

信号更多的是通知事件的发生,信号产生之后第一时间也不是直接处理,而是先存储下来,处理信号
时会打断当前进程正在执行的工作,然后去准备处理事件,事件处理完毕之后进程会回到原先运行的位置继续运行。

Linux下有62种信号,可以使用 kill -l 查看
在这里插入图片描述
分类

  • 1-31不可靠信号(非实时信号)
  • 34-64可靠信号(实时信号)

注:在书写程序时,建议书写信号宏名,便于跨平台

信号的生命周期: 信号的产生->信号注册(修改信号集)->(信号阻塞)->信号注销->信号处理

信号的产生

1、 通过硬件中断产生
例如: CTRL + C

2、程序异常
SIGFPE(数据运算错误)
SIGSEGV(内存错误)

3、软件函数

kill函数

int kill(int pid,int sig);    //向指定进程发送指定信号
	pid    //进程id
	sig    //信号    
  
//命令
kill pid    // 默认向一个进程发送SIGTERM(15)--终止信号
kill -15  pid    //向进程发送15信号

raise函数

int raise(int sig);    //给当前进程发送指定的信号(向自身发送信号)

abort函数

void abort(void);    //向自身发送SIGABRT信号

alarm函数 ——定时器

unsigned int alarm(unsigned int seconds);    //设置一个定时器,在n秒后给当前进程发送SIGALRM信号(该信号的默认处理动作是终止当前进程)。同时取消上一次的定时器,并且返回上一个定时器的剩余时间
	seconds    //n秒
    
alarm(0)    //取消上一次定时器,并且返回上一个定时器剩余时间

sigqueue函数

int sigqueue(pid_t pid, int sig, union sigval)
	pid    //进程ID
	sig    //信号编号
	sigvl    //参数
//这个函数不仅可以发送信号,还可以顺便携带一个参数

信号注册

信号注册:给一个进程发送信号,就是修改这个进程pcb中关于信号的pending位图,将其相应的信号位置1。
在这里插入图片描述

信号阻塞

暂时不处理信号(阻止信号的递达),并不是不接收信号,即阻止信号的递达。
信号的递达: 信号的处理
要阻塞一个信号,就是将pcb中关于信号的block位图,将相应的信号位置1。
在这里插入图片描述
注: 阻塞信号集(block)与未决信号集(pending)分别具有一个集合,这两个集合都是位图,当某个信号阻塞 / 未决 时,将位图相应的位置置1。
信号未决: 这是一种状态,指的是信号从注册成功到信号递达的之间的一种状态。

对信号集操作的一些函数

int sigprocmask(int how, const sigest_t *set, sigset_t *old-set);     //阻塞信号/解除阻塞
	how
	   	SIG_BLOCK    //阻塞
   		SIG_UNBLOCK    //解除阻塞
   		SIG_SETMASK    //设置阻塞集合当中的信号
	set    //阻塞或解除阻塞的集合    从block中加入/剔除
	oldset    //保存原先阻塞集合中的信号

int sigpending(sigset_t *set);	//获取未决(未被处理)信号

int sigemptyset(sigset_t *set);    //清空一个信号集合

int sigfillset(sigset_t *set);    //将所有的信号都添加到set中(置1)

int sigaddset(sigset_t *set, int signum);    //添加指定的单个信号到set集合中

int sigdelset(sigset_t *set, int signum);    //从集合移除一个指定的信号

int sigismember(const sigset_t *set, int signum);     //判断一个信号是否在set集合中

信号处理

从pending集合中将即将要处理的信号相应位置0(从pcb的pending集合中移除)。

  • 非可靠信号注册(1-31)就是将相应pending位图置1,然后添加一个sigqueue结构到链表,之后如果有相同信号到来时,位图已经置1,就不做操作了,意味着后来的信号在前一个信号处理之前不会重复注册,代表丢了。
  • 可靠信号注册(34-64)不管有没有注册都要置1,并且添加结点到链表中,所以不会丢信号。
  • 非可靠注销就是删除链表结点,相应位图置1。
  • 可靠信号注销就是删除结点,判断链表中是否有相同信号结点,如果没有位图置0,如果有就不置0。

在这里插入图片描述

信号的处理

处理方式

1、默认操作 按照操作系统中对信号事件的既定处理方式
2、忽略操作 直接将信号丢掉(不注册)
3、自定义处理 用户自己定义事件处理的方式
自定义型号处理方式接口函数
01、signal函数

typedef void (*sighandler_t)(int);    //int    signo
sighandler_t signal(int signum, sighandler_t handler);    //指定改变某一个信号的处理方式
	signum    //信号编号
	handler    //函数指针,处理方式
   	 	//SIG_IGN    //忽略信号(宏)
    	//SIG_DFL    //默认

02、sigaction

int sigaction(int signum,const struct sigaction *act,struct sigaction *odlact)      
	signum    //信号编号
	act    //新的处理方式
	odlact    //保存原有的处理方式
	struct sigaction  
	{
	    //回调函数指针
  	  void (*sa_handler)(int);    //函数指针    处理函数
  	  void (*sa_sigactionr)(int, siginfo_t *, void*);    //函数指针    处理函数
   	  sigset_t sa_mask;    //位图  信号集合    在处理信号时可以通过这个mask暂时阻塞一些信号,处理完毕后会还原回去
   	  int sa_flags;    //决定了我们使用那个回调接口,并且还有一些其他选项信息
                    //SA_SIGINFO    //使用sa_sigaction
                    //否则使用sa_handler
      void (*sa_restorer)(void);
	};

信号的捕捉流程——主要是针对信号的自定义处理方式

信号并不是立即处理的,而是选择一个合适的时机,合适的时机就是当前进程从内核态切换到用户态的时候。
信号的捕捉是当我们发起系统调用/程序异常/程序中断时,当前程序从用户态运行切换到内核态,去处理这些事情,处理完毕之后,要从内核态返回用户态,但是在返回之前会看一下是否有信号需要处理,如果有,就处理信号(切换用户态执行信号的自定义处理方式),处理完毕之后,再次返回内核态,如果没有信号要处理就调用sys_sugreturn返回用户态(我们程序之前运行的位置)。
在这里插入图片描述

可重入函数/不可重入函数

可重入函数: 不管怎么调用,都不会对函数内部功能/程序逻辑造成影响,称为可重入函数。
不可重入函数: 如果函数在不同的地方/时序进行调用,会对函数的功能逻辑造成影响,称为不可重入函数(两个进程在不同时间对同一个函数中的变量修改,可能造成程序紊乱)。

不可重入函数的一些要点(什么函数是不可重入函数)

  • 内部包含对全局性变量的修改操作
  • 函数传参的参数和其余位置共同使用同一变量
    因为这些对全局变量的操作不是原子性的,因此这些修改操作有可能同时在不同地方进行修改(被打断)。

一个函数是否可以重入

  • 是否对全局性数据进行修改操作
  • 操作是否是原子性

SIGCHLD信号

僵尸进程的避免
操作系统如何通知父进程子进程退出——SIGCHLD信号

以前为了避免产生僵尸进程,只能让父进程一直等待子进程退出(不知道子进程什么时候退出),浪费了父进程的资源,现在,自定义信号SIGCHLD的处理方式,相当于提前告诉进程,当接收到这个信号的时候使用waitpid,这样就不用一直等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值