csapp_ECF习题/例题笔记

关于csapp第八章ECF中习题运行和结果分析
这部分的代码使用的一些常量或封装函数(WNOHANG,Pid_t,Fork()等)在某些头文件定义,为简化代码示例,这里使用了csapp.h头文件(已包含所有这些需要的头文件)。
这里附上在ubuntu中使用csapp.h和csapp.c的方法链接:

https://www.cnblogs.com/acm1314/p/5623562.html


习题8.3
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
由进程图知,该程序可能的输出序列为acbc, abcc, bacc。(满足拓扑排序
而程序执行结果却输出为bacc。
这说明程序是并发执行的。父进程和子进程是并发运行的独立进程,内核能以任何方式交替执行他们的逻辑控制流语句中的指令,父进程与子进程执行的先后顺序并不能确定。
补:fflush(stdout):对标准输出流的清理,及时地打印数据到屏幕上。标准输出是以行为单位进行的,也即碰到\n才打印数据到屏幕,这就可能造成延时。(即清空输出缓冲区,并把缓冲区内容输出)。另一篇博客将讲解未及时清除缓冲区而影响输出结果的实例。


习题8.4
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
该程序的可能的输出序列会满足拓扑排序这里不再赘述。
关于fork函数
他被调用一次,返回两次。一次在父进程中,一次在新创建的子进程中。父进程中fork返回子进程的PID,子进程中fork返回0。故父进程的!pid为0,子进程的!pid为1。
关于waitpid函数

pid_t waitpid(pid_t pid, int *statusp, int options);
  • 默认情况下(options=0)时,waitpid挂起调用进程的执行,直到它的等待集合中的一个子进程终止。可将options设置成常量WNOHANG等来修改默认行为
  • pid>0,那么等待集合是单独的子进程,它的进程ID等于pid。如果pid=-1,那么等待集合是由父进程所有的子进程组成的
  • 若statusp参数非空,waitpid会在status中放上关于导致返回子进程的状态信息,status是statusp指向的值。宏WIFEXITED(status):如果子进程通过调用exit或者返回(return)正常终止,就返回真。WEXITSTATUS(status):返回一个正常终止的子进程的退出状态。只有在WIFEXITED()返回为真时,才会定义这个状态。
  • 错误条件:调用进程没有子进程,waitpid返回-1,并设置errno为ECHILD。如果waitpid函数被一个信号中断,返回-1,并设置errno为EINTR。

而exit函数以status退出状态来终止进程。由于子进程exit(2),故这里的父进程中会输出2。


示例8-18,8-19(书中代码过长未贴出)
这里对重点在对waitpid函数做了更改,图8-18中是waitpid(-1,&status,0),图8-19中是waitpid(pid[i++],&status,0),这样在while循环中等待集合是一个单独的子进程,父进程可以逐个按创建顺序(i值的大小顺序)回收子进程。

代码结尾处有判断语句if(errno != ECHILD),这里用到了waitpid的错误条件,检查waitpid函数是否是正常终止的。


示例8-29
在这里插入图片描述
在这里插入图片描述
能够看到这里并没有任何输出。
关于pause函数
能让调用函数休眠,直到该进程收到一个信号。
关于kill函数

int kill(pid_t pid, int sig);

如果pid>0,那么kill函数发送信号号码给进程pid。如果pid=0,那么kill发送信号sig给调用进程所在进程组中的每个进程,包括调用进程自己。如果pid<0,kill发送信号sig给进程组|pid|中的每个进程。
关于进程组
每个进程都只属于一个进程组,进程组是由一个正整数进程组ID来标识的。一个子进程和他的父进程同属于一个进程组。子进程pgid为父进程pid。

这里的子进程本是调用pause进入休眠,直到收到信号继续执行,但父进程给子进程发送的信号SIGKILL杀死了子进程,所以子进程不会执行printf语句。


示例8-30
在这里插入图片描述
在这里插入图片描述
关于signal函数

sighanlder_t signal(int signum, sighanlder_t hanlder);
  • 如果hanlder是SIG_IGN,忽略类型为signum的信号。如果hanlder是SIG_DFL,类型为signum的信号行为恢复为默认行为。否则hanlder就是用户定义的函数的地址,这个函数被称为信号处理函数,只要用户接收到一个类型为signum的信号,就会调用这个程序。
  • 每个信号类型都有一个默认行为,把处理程序的地址传递到signal函数能改变默认行为,唯一不能修改默认行为的是SIGSTOP和SIGKILL。
  • 返回:若成功则为指向前次处理函数的指针,若出错则为SIG_ERR。

这里pause使它休眠直到接收信号(注释pause则会直接结束程序),SIGINT的对应事件为键盘的中断即ctrl+c。在命令行输入ctrl+c,signal函数使它执行函数中的输出语句表示接收信号。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值