APUE第九章

来源:互联网 发布:淘宝下载苹果版下载 编辑:程序博客网 时间:2024/06/07 18:27

谈不上懂  先把一些东西写下来吧。 随笔记记  很多原理是需要记载脑海中的,回头去看的几率不高


可以分析出,这个shell终端进程号是2862,会话组ID也是2862,所以当我们打开一个shell的时候,就建立了一个新会话,启动shell的进程是新会话的第一个进程,按书上的话来说他是一个后台进程组,也是会话首进程,也是控制进程。

之后vim temp.foo & 这个命令在后台启动了一个进程,父进程ID是2862,所以可以分析出是shell里面先fork一个子进程,子进程中调用fork返回的进程号是2890,然后调用setpgid为子进程设置一个进程组ID,并且子进程ID设置为组长进程,所以新的进程组ID也为2890

第三个是我们调用ps命令时候shell启动了一个前台程序,建立过程跟vim差不多,不过ps进程是前台进程。

对于其中TPGID列,可以查阅man手册

在命令行里 输入 man ps

然后 继续输入 /TPGID  

就可以查阅到了。


TPGID:与进程关联(连接)的终端的前台进程组ID  

所以比如对第一幅图第二行分析TPGID,vim这个后台进程关联的终端(虽然此时终端的输入输出并不是对于他,不过如果后台进程想输入输出的时候终端还是会给发信号的)是shell的会话终端,ps这个前台进程关联的终端也是shell会话终端,所以vim关联的终端即是ps关联的终端,该终端前台进程为ps,ps的进程组ID为2892,所以vim的TPGID为2892.


apue第三版245页的程序。其中其实仔细思考还是有很多小知识的。

 

以下是我阅读完第九章对这个程序运行流程的理解。(以下是运行代码前对其中的过程的分析,之后我会把代码运行结果贴出来,有一些还是不太一样的)

 

父进程先运行pr_ids打印调用进程(父进程)的信息,然后fork一个子进程。之后父进程和子进程共同运行剩下的代码。父进程fork返回值为子进程的进程号,所以pid大于0,所以父进程进入sleep(5),可以说这5秒足以让子进程运行所有代码了,我们看看子进程执行什么代码,首先子进程先执行pr_ids函数来打印调用进程(子进程)的信息,此时父进程并没有退出(在sleep),所以其打印的信息中ppid为父进程的进程号,然后signal来设置处理SIGHUP信号的函数为sig_hup。然后执行kill(getpid(),SIGTSTP)。此时这段代码终止了子进程,使得子进程不再执行以下代码,但此时仍是前台进程!

父进程从sleep中醒来后,直接就执行了exit(0)。此时父进程终止,按照书上来推理的话,父进程终止后,子进程所在的进程组中任何一个子进程(其实本例中就只有一个子进程)的父进程并不在同一会话组的其他进程组中,所以无法使得子进程从终止状态继续下去,所以此时子进程组变成孤儿进程组,并且!此时子进程变成后台进程。

变成孤儿进程组后,POSIX.1会要求向新的孤儿进程组先发送一个SIGHUP信号,此时子进程接收到SIGHUP信号后执行SIGHUP信号处理程序。

然后POSIX.1还会向新的孤儿进程组发送一个SIGCONT信号,让子进程继续执行代码。子进程收到SIGCONT信号后于是执行后面的代码。先是执行pr_ids("……").打印出父进程终止后子进程的信息。然后子进程(注意是后台进程)想read一个标准输入,在一般的情况下,后台进程想读取标准输入都会被发送一个SIGTTIN信号以终止,但是有两种情况后台进程读取标准输入的时候是不发送SIGTTIN信号的。(对于SIGTTIN信号相关信息可查阅第三版APUE255页)

第一种情况:读进程忽略或者阻塞此信号(调用read的进程忽略了或阻塞此信号)

第二种情况:读进程所属进程组是孤儿进程组,此时终端驱动程序并不发送SIGTTIN信号,而是读操作出错返回,errno设置为EIO。

我们这里是属于第二种情况的。所以read函数出错,errno设置为EIO,所以如果设置SIGTTIN信号处理程序不能看见什么效果(也就是不会运行SIGTTIN信号处理程序),因为终端驱动程序会发现调用read来读标准输入的进程所属进程组是个孤儿进程,所以并不发送SIGTTIN信号,而是让读操作出错。

然后子进程read函数出错后继续执行后面代码,后面代码是exit,退出。

程序分析完毕。


以下是我按书上的程序执行结果,我是在shell上写并且运行的。




 

0 0
原创粉丝点击