记录一下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