《深入理解计算机系统》Exceptional Control Flow-Signals and Nonlocal Jumps

shell:

shell有一些内建命令,收到命令行字符串之后,首先检查是否时内置命令,如果是,则直接执行;如果不是,则认为命令行是需要执行的可执行文件,直接fork-exec执行。通过这样的方式达到可扩展的优势。

信号是一小条消息,通知进程系统中发生了一个某种类型的事件。是完全由软件基于异常机制实现的。

以下摘自man 7 signal

Signal     Value     Action   Comment

       ──────────────────────────────────────────────────────────────

       SIGHUP        1       Term    Hangup detected on controlling terminal

                                     or death of controlling process

       SIGINT        2       Term    Interrupt from keyboard(ctrl-c

       SIGQUIT       3       Core    Quit from keyboard

       SIGILL        4       Core    Illegal Instruction

       SIGABRT       6       Core    Abort signal from abort(3)

       SIGFPE        8       Core    Floating-point exception

       SIGKILL       9       Term    Kill signal-ctrl-c

       SIGSEGV      11       Core    Invalid memory reference-段错误

       SIGPIPE      13       Term    Broken pipe: write to pipe with no

                                     readers; see pipe(7)

       SIGALRM      14       Term    Timer signal from alarm(2)(用户自己使用

       SIGTERM      15       Term    Termination signal

       SIGUSR1   30,10,16    Term    User-defined signal 1

       SIGUSR2   31,12,17    Term    User-defined signal 2

       SIGCHLD   20,17,18    Ign     Child stopped or terminated

       SIGCONT   19,18,25    Cont    Continue if stopped

       SIGSTOP   17,19,23    Stop    Stop process(ctrl-z

       SIGTSTP   18,20,24    Stop    Stop typed at terminal

       SIGTTIN   21,21,26    Stop    Terminal input for background process

       SIGTTOU   22,22,27    Stop    Terminal output for background process

       The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

信号的默认处理动作有以下几种:

1. 进程终止;

2. 进程终止并转储内存;

3. 进程停止(挂起);

4. 忽略

信号发送的2种触发方式:

1. 内核捕获到了某种事件的发生:如除零或子进程退出;

2. 进程使用kill系统调用主动发信号。

使用int signal(int signum,  isghandler_t handler);可以设置每个信号的关联行为。

SIG_IGN 为忽略

SIG_DFT为恢复默认行为

还可以指定用户自定义的信号处理程序。

同一时刻,只能有一个相同类型的等待处理的信号。如果同时又来了一个相同类型的信号,则后来的信号会被丢弃掉(原因是在一个进程中,一个信号的有效只用一个bit来表示 32bit int)。

进程可以阻塞信号的接收(没办法阻止信号的传递),即阻止进程在接收到信号之后的反应,使用系统调用sigpromask(相当于对进程的不同信号屏蔽位置位32bit int)。

进程组:每个进程都只属于一个进程组,默认情况下,子进程和父进程同属于一个进程组。

但可以哦通过setpgid系统调用修改。

kill -9 12345 //杀死pid为12345的进程

kill -9 -12345 //杀死pgid为12345的每一个进程

发送信号的几种方式:

1. 给一整个进程组发送信号 kill -9 -12345

2. 通过键盘发送信号:ctrl-c对应SIGINT,ctrl-z对应SIGSTOP,fg对应将所有被挂起的命令恢复到前台执行。

3. 使用kill系统调用给指定pid发送信号;

4. 使用alarm系统调用给自己发送SIGALRM信号

pause系统调用:阻塞直到一个信号到来,执行完信号处理动作后返回。

包含系统调用的进程调度例子:

进程A正在执行时,来了一个信号SIGA,只是信号标志位置位,还没来得及执行,这时执行了一次上下文切换,系统调度进程B。过了一段时间,系统又进行上下文切换,调度进程A,这是由于信号标志位置位,所以开始执行信号处理函数(用户态),执行完成之后,切换回进程A的主进程,这两步之间还有依次用户态-内核态-用户态的切换。

信号处理函数还可以发生嵌套。编号越小,优先级越高?

https://blog.csdn.net/zhangchaoq/article/details/51201979

如何编写你的信号处理函数:

1. 让信号处理函数尽可能简单;

2. 只能使用异步信号安全的函数(printf,sprinf,malloc,exit都不是异步信号安全的);

3. 保存和恢复errno

4. 对一些全局变量的操作加锁;

5. 主函数和信号处理函数公用的变量声明为volatile类型,避免编译器把它存储在寄存器中;

6. 使用sig_atomic_t(多数系统上是int)声明主函数和信号处理函数之间的标志,对这种类型的操作是原子的(不会被打断的过程中)。

write系统调用是唯一一个异步信号安全的输出函数。

父进程回收子进程信号处理函数:

信号处理函数在不同unix版本的不同表现:

1. 执行一次信号处理函数后,会自动恢复默认操作,所以需要每次执行完信号处理函数后,重新挂载一次;

2. 有些unix上,如果执行read这种慢系统调用,还没有返回时,系统自动结束系统调用,并把errno置为EINTR,需要用户检查errno并重新执行系统调用。

父子进程分配回收资源框架:

P542

大概原理:addjob和deljob在一个进程中,都在父进程中。只能按次序执行。父进程在执行fork之前已经把SIGCHLD屏蔽了,直到addjob之后,才会解除屏蔽。因此addjob只可能在deljob之前调用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值