1.任务1
比较trace06执行不同结果,编程实现sigint handlet捕获INT响应、waitfg0等待、sigchld_ handler回 收僵死
查看trace06.txt的内容以及make rtest06与make test06的输出比较:
发现make test06没有相应输入命令中的INT
发现在我们的main函数里面已经修改了信号SIGINT的默认行为,因此完善sigint_handler:
sigint_handler:
- 键盘输入ctrl+c时该函数处理SIGINT信号,终止前台进程pid以及其所有的子进程
- 调用函数fgpid返回前台进程pid
- 利用kill函数kill(-pid,sig)表示向进程组pid的所有进程发送sig信号,如果返回值为-1表示进程不存在。
waitfg(pid_t pid):
- fpgid函数:如果不存在前台进程返回0,否则返回指向前台进程的pid
- 当前台进程的pid与要等待的前台进程pid相等的时候,执行sleep(0)
- 前台进程pid终止后返回
sigchld_handler:
- 该函数处理SIGCHLD信号,此时子进程被终止或停止,并回收所有僵死进程,但是不等待其他目前正在运行的子进程结束
- SIGCHLD信号:
①子进程通过EXIT或return正常终止
②子进程接收到其他信号而终止③子进程接收到SIGSTP/SIGSTOP信号后停止
- 调用函数pid2jid(pid_t pid)得到进程组的jid
- 调用函数waitpid(-1,&status,WNOHANG|WUNTRACED)等待父进程所有的子进程集合,立即返回
①如果没有终止的进程返回0
②否则为终止进程的pid,并回收,status记录了终止状态
- 利用WIFSTOPPED(status)判断子进程是否停止,WSTOPSIG(status)返回导致其停止的信号
- 利用WIFEXITED(status)判断子进程是否正常退出
- 利用WIFSIGNALED(status)判断子进程是否因为一个未捕获的信号终止,WTERMSIG(status)返回未捕获的信号
2.任务2:
验证trace06 07,了解接收信号、信号处理、信号阻塞概念。
trace06中首先运行程序myspin,然后休眠2s之后输入INT命令终止程序
输出被终止程序的进程组jid和进程pid,以及终止信号2(SIGINT),正确
trace07:
- trace07.txt中①在后台运行程序myspin 4 ②然后在前台运行程序myspin 5 ③接着休眠2s后输入INT信号终止前台进程 ④最后输入jobs查看进程列表
- 输出:①在捕获SIGINT信号后输出Job [2] (13055) terminated by signal 2的提示 ②收到内置命令后,输出进程组信息,还剩下一个后台的myspin 4 &进程,正确
接收信号:当内核从一个异常处理程序返回,准备将控制传递给进程p时,它会检查进程p的未被阻塞的待处理信号集合,如果非空,则内核强制接收信号,调用信号处理程序。
信号处理:执行信号处理程序即为处理信号,对信号做出相应的响应。
信号阻塞:当进程捕获了一个类型为k的信号并在处理时,那么k信号就被阻塞i,下一个k信号会变成待处理的信号,如果在此期间还有k信号,则被丢弃。
3.任务3
比较trace08执行不同结果,编程实现sigtstp_ handler捕 获TSTP响应
没有相应SIGSTP信号
- trace08.txt中①在后台运行程序myspin 4 ②然后在前台运行程序myspin 5 ③接着休眠2s后输入STSP信号停止前台进程 ④最后输入jobs查看进程列表
4.任务4
验证trace08
输出:①在捕获SIGINT信号后输出Job [2] (15969) STOPPED by signal 20 的提示 ②收到内置命令后,输出进程组信息,后台的myspin 4 &进程是running,./myspin 5 是stopped,正确
对于之前参考了我博客的同学感到十分抱歉,非常抱歉,也是因为在做实验的过程中不断发现了问题,然后回过头改正,这里将改正后的eval贴一下:如果大家有什么问题的话欢迎大家留言评论(*^_^*)
① int setpgid(pid_t pid,pid_t pgid)
- 将参数pid指定的进程所属的组识别码,设为参数pgid指定的组识别码。
- 如果参数pid 为0,则会用来设置进程的组识别码
- 如果参数pgid为0,则由pid指定的进程ID将用作进程组ID。
- 一个进程只能为它自己或它的子进程设置进程组ID。
②无须判断运行程序是否为./开头,否则会产生如下错误:/bin/echo程序运行命令先输入但是后运行