进程间通信常见方式-信号

进程间通信常见方式-信号

学习目标:

熟练使用信号捕捉函数signal。
熟练使用信号捕捉函数sigaction
熟练掌握使用信号完成子进程的回收


信号:

信号的特质:信号是软件层面上的“中断”,一旦信号产生,无论程序执行到什么位置,必须立即停止运行,处理信号,处理结束,再继续执行后续指令。
信号的相关概念:

  • 按键产生
  • 系统调用产生
  • 软件条件产生
  • 硬件异常产生
  • 命令产生

概念:

  • 未决:产生与递达之间的状态。
  • 递达:产生并且送达到进程,直接被内核处理。
  • 信号处理方式:执行默认处理动作、忽略、捕捉(自定义)。
  • 阻塞信号集(信号屏蔽字),本质:位图,用来记录信号的屏蔽状态。一旦被屏蔽的信号,再解除屏蔽之前,一直处于未决态。
  • 未决信号集,本质:位图,用来记录信号的处理状态。该信号集中的信号,表示已经产生,但未被处理。

信号4要素:
- 信号使用之前,应先确定四要素,而后再用
- 编号、名称、对应事件、默认处理动作。
信号的编号:信号定义在signal.h头文件中。
如下:
在这里插入图片描述


kill命令和kill函数:

kill命令:kill命令用来给某个进程发送信号。

kill [options] <pid> [...]

kill函数:给指定进程发送指定信号。

int kill(pid_t pid,int signum);

参数
pid:

  • > 0:发送信号给指定进程。
  • = 0:发送信号给调用kill函数的那个进程处于同一进程组的进程。
  • < -1:取绝对值,发送信号给该绝对值所对应的进程组的所有成员。
  • = -1:发送信号给有权限发送的所有进程。

signum:代发送的信号

返回值
成功:0
失败:-1,设置相应的errno


alarm函数:

alarm函数:在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号。设置忽略或不捕捉该信号,如果采用默认方式其动作是终止该调用该alarm函数的进程。(使用自然计时法)

unsigned int alarm(unsigned int seconds);

参数
seconds:定时秒数
返回值
成功: 上次定时剩余时间。
无错误现象

alarm(0);取消闹钟

time命令:查看程序执行时间。实际时间 = 用户时间 + 内核时间 + 等待时间


setitimer函数:

setitimer函数:实现精度较高的定时功能。

int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value);

参数
which:

  • ITIMER_REAL:采用自然计时(SIGALRM)
  • ITIMER_VIRTUAL:采用用户空间计时(SIGVTALRM)。
  • ITIMER_PROF:采用内核 + 用户空间计时(SIGPROF)。

new_value:定时秒数 。
old_value:传出参数:上次定时剩余时间。

返回值
成功:0
失败:-1,设置相应的errno

struct itimerval 类型:

struct itimerval{
  struct timeval it_interval; //周期定时秒数
  struct timeval it_value;    //第一次定时描述
}

struct timeval类型:

struct timeval{
   time_t       tv_sec; //秒
   suseconds_t  tv_usec;//微秒
}

time命令:查看程序执行时间。实际时间 = 用户时间 + 内核时间 + 等待时间


信号集操作函数:

sigset_t set;//自定义信号集
sigemptyset(sigset_t *set);//清空信号集
sigfillset(sigset_t *set);//全部置1
sigaddset(sigset_t *set,int signum);//将一个信号添加到集合中
sigdelset(sigset_t *set,int signum);//将一个信号从集合中移除
sigismember(sigset_t *set,int signum);//判断一个信号是否在集合中。(在 1, 不在 0)

sigprocmask函数:

sigprocmask函数:用于改变进程的当前阻塞信号集,也可以用来检测当前进程的信号掩码。

int sigprocmask(int how,const sigset_t *set,struct sigset_t *oldset);

参数
how:

  • SIG_BLOCK:设置阻塞
  • SIG_UNBLOCK:取消阻塞。
  • SIG_SETMASK:用自定义set替换mask。

set:自定义set。
oldset:旧的maskt。

返回值
成功:0
失败:-1,设置相应的errno


sigpending函数:

sigpending函数:返回在送往进程的时候被阻塞挂起的信号集。

int sigpending(sigset_t *set);

参数
set:传出的未决信号集。

返回值
成功:0
失败:-1,设置相应的errno


signal函数:

signal函数:组测一个信号捕捉函数。

typedef void(*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);

参数
signum:待发送的信号。
handler:处理的方式。
返回值
成功:该函数返回信号处理程序之前的值。
失败:SIG_ERR


sigaction函数:

sigaction函数:查询或设置信号处理方式。

int sigaction(int signum,const struct sigaction *act,struct *oldact);

参数
signum:待发送的信号。
act:传入参数,新的处理方式。
oldact:传出参数,旧的处理方式。
返回值
成功:0
失败:-1,设置相应的errno

struct sigaction 类型:

struct sigaction{
  void (*sa_handler)(int); //新的信号处理函数
  void (*sa_sigaction)(int,siginfo_t*,void *); 
  sigset_t sa_mask;//用来设置处理该信号时暂时将sa_mask指定的信号集搁置
  int sa_flags;//用来设置信号处理的其他相关操作,下列的数值可用。  
 /***********************************************
   SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
   SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
   SA_NODEFER:一般情况,当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了SA_NODEFER标记,那么在该信号处理函数运行时,内核将不会处理阻塞该信号。
***********************************************/
  void (*sa_restorer)(void);//此参数没有使用  
}

信号捕捉特性:

  • 捕捉函数执行期间,信号屏蔽字,有mask–>sa_mask,捕捉函数执行结束,恢复回mask
  • 捕捉函数执行期间,本信号自动被屏蔽(sa_flags = 0)
  • 捕捉函数执行期间,被屏蔽信号多次发送,接触屏蔽后只处理一次!

中断系统调用:

系统调用可分为两类,慢速系统调用和其他系统调用

  • 慢速系统调用,可能会使进程永远阻塞的一类,如果在阻塞期间收到一个信号,该系统调用就被中断,不再继续执行(早期),也可以设定系统调用是否重启。如:read、write、pause、wait…
  • 其他系统调用:getpid、getppid、fork…

慢速系统调用被中断的相关行为,实际上就是pause行为。如:read

  • 想中断pause,信号不能被屏蔽
  • 信号处理方式必须是捕捉(默认、忽略都不行)
  • 中断后返回-1,设置errno为EINTR(表示被信号中断)可修改sa_flags参数来设置被信号中断后系统调用是否重启。SA_INTERRURT不重启,SA_RESTART重启。
  • sa_flags还有很多可选参数,适用于不同情况。如:捕捉信号后,在执行函数期间,不希望自动阻塞该信号,可将sa_flags设置为SA_NODEFER,除非sa_mask中包含该信号。

补充:

信号捕捉

sighandler_t signal(int signum,sighandler_t handler);

参数
set:传出的未决信号集。

返回值
成功:0
失败:-1,设置相应的errno

发信号函数

int raise(int sig);
void abort(void);

内核实现信号捕捉过程:
在这里插入图片描述

SIGCHLD信号产生条件:

  • 子进程终止时
  • 子进程接收到SIGSTOP信号停止时
  • 子进程处于停止态,接收到SIGCONT后唤醒时

信号表:

取值名称解释默认动作
1SIGHUP挂起
2SIGINT中断
3SIGQUIT退出
4SIGILL非法指令
5SIGTARP断点或陷阱指令
6SIGABRTabort发出的信号
7SIGBUS非法内存访问
8SIGFPE浮点异常
9SIGKILLkill信号不能被忽略、处理和阻塞
10SIGUSR1用户信号1
11SIGSEGV无效内存访问
12SIGUSR2用户信号2
13SIGPIPE管道破损,没有读端的管道写数据
14SIGALRMalarm发出的信号
15SIGTERM终止信号
16SIGSTKFLT栈溢出
17SIGCHLD子进程退出默认忽略
18SIGCONT进程继续
19SIGSTOP进程停止不能被忽略、处理和阻塞
20SIGSTP进程停止
21SIGTTIN进程停止,后台进程从终端读数据时
22SIGTTOU进程停止,后台进程想从终端写数据时
23SIGURGI/O有紧急数据到达当前进程默认忽略
24SIGXCPU进程的CPU时间片到期
25SIGXFSZ文件大小的超出上限
26SIGVTALRM虚拟时钟超时
27SIGPROFprofile时钟超时
28SIGWINCH窗口大小改变默认忽略
29SIGIOI/O相关
30SIGPWR关机默认忽略
31SIGSYS系统调用异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值