0%

异常控制流-homework

记录一下csapp第八章homework

8-23

题目中counter等于2,当子进程发送了一个信号sigusr2给父进程时,父进程进入异常处理程序。紧接着,子进程又发送了一个信号,而父进程此时仍在处理程序中,内核设置pending位为1。后续子进程继续发送信号,由于父进程始终处于第一个信号处理程序中,所以剩下三个信号均被丢弃。最后再接收第二个信号。

但是在我的计算机上面跑这个程序得到了不同的结果,如图:
信号计数

原因是子进程发送信号后,父进程没有立即处理,所以pending位被一直占用,所以四个信号都被丢弃了。只进行了一次处理程序。
可以通过不断增加发送信号的次数,以增加切换到父进程的概率,观察counter的变化。
还可以通过向for循环增加sleep以得到正确的次数。

8-24

修改例子后的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include"../csapp.h"
#define N 2

int main(){
int status,i;
pid_t pid;

for(int i=0; i< N; i++){
if((pid = Fork()) == 0)
{
char* ptr = (char*)&main;
*ptr = 'c';
}
}


while((pid = waitpid(-1,&status,0)) > 0){
if(WIFEXITED(status)){
printf("child %d terminated normally with exit status=%d\n", pid, WEXITSTATUS(status));
}
else if(WIFSIGNALED(status)){
char buf[128];
sprintf(buf,"child %d terminated by signal %d ",pid,WTERMSIG(status));
psignal(WTERMSIG(status),buf);
}
else
printf("child %d terminated abnormally\n",pid);
}

if(errno != ECHILD){
unix_error("waitpid error");
}

exit(0);

8-25

初看题目没什么思路,按题目的意思,要求在五秒之后中断输入,直接返回NULL
如何中断呢,还限时,那就只有alarm了。
五秒钟过后,如何在返回NULL呢,要用到非本地跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include"../csapp.h"

sigjmp_buf buf;

void handler(int sig){
siglongjmp(buf,1);
}

char* tfgets(char* s,int n, FILE* stream){
if(!sigsetjmp(buf,1))//保存信号屏蔽字
{
alarm(5);
if(Signal(SIGALRM,handler)==SIG_ERR)
{
unix_error("Failed to install SIGALRM's handler");
return NULL;
}
return fgets(s,n,stream);
}else{
return NULL;
}
}

int main(){
char buf[100] ;
char* res;
res=tfgets(buf,99,stdin);
if(res)
printf("%s",buf);
else
printf("Time out!");

return 1;
}

8-26

感觉这个比lab要难。lab直接填,而这个要自己写出job

第一个要求,之前书上实现过了,不过等待信号要用sigsuspend,

就是lab