分类:
2008-11-26 18:06:26
chapter 8 exercises
|
In , we said that replacing the call to _exit with a call to exit might
cause the standard output to be closed and printf to return -1. Modify the
program to check whether your implementation behaves this way. If it does
not, how can you simulate this behavior? |
答案:这个问题其实就是讲了如下原则:
Vfork出来的进程和服进程共享了地址空间,所以也就共享了对standard i/o library的使用。在child里,如果调用_exit(),他不会对stanadard i/o library进行clearup工作,既不会进行flush操作,更不会执行对流对象的关闭,即FILE object的清除。但是他会关闭自己的STDOUT_FILENO和 STDIN_FILENO这两个打开的descriptor,由于chilld和parent都有各自的一份descriptor,共同指向相同的file table entries,因此理应不会真正关闭file table entry. 所以parent应该还可以使用标准库输出。
如果在child里,调用eixt()这个库函数,它肯定会对标准库进行cleanup工作,即flush stadout,然后呢,可能会关闭标准输出/输入流。如果的确要关闭的话,等关闭之后,father的标准输出流当然也就不能用了,所以father就不能再输出了。有的时候,关闭标准输出流会使得底层的descriptor也被关闭。从而导致father 也不能使用STDOUT_FILENO这个descriptor来进行write操作了。但是有的实现在关闭标准流的时候并不关闭底层的descriptor。那么parent 就还可以使用STDOUT_FILENO来进行write操作。
我们看到的一般情况是:
1. 单进程里,如果STDOUT_FILENO没有被dup,关闭标准流就会关闭STDOUT_FILENO
2. vfork多进程后,关闭标准流后,descriptor不会被关闭。仅仅是不能使用标准流了。
|
Recall the typical arrangement of memory in . Because the stack frames corresponding to each function call are
usually stored in the stack, and because after a vfork, the child runs in the
address space of the parent, what happens if the call to vfork is from a
function other than main and the child does a return from this function after
the vfork? Write a test program to verify this, and draw a picture of what's
happening. |
答案:vfork出来的子进程和parent共享stack,当子进程从一个函数返回时,一个stack frame被出栈。然后parent在执行时,如果不执行return,就不会出错,一旦执行到return,他也要出栈那个同样的stack frame的时候就出了segment fault了。结论:vfork可不是让你用来建立进程后随便执行的,要exec的阿。
|
When we execute the program in one time, as in $ ./a.out the output is correct. But if we execute the program multiple times, one
right after the other, as in $ ./a.out ;
./a.out ; ./a.out output from
parent ooutput from
parent ouotuptut from
child put from
parent output from
child utput from
child the output is not correct. What's happening? How can we correct this?
Can this problem happen if we let the child write its output first? |
答案:8.13是一个使用伪码来进行进程间同步的程序,力图让父子进程能够按顺序输出。
#include "apue.h"
static void charatatime(char *);
int
main(void)
{
pid_t pid;
TELL_WAIT();
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid == 0) {
WAIT_PARENT(); /* parent goes first */
charatatime("output from child\n");
} else {
charatatime("output from parent\n");
TELL_CHILD(pid);
}
exit(0);
}
static void
charatatime(char *str)
{
char *ptr;
int c;
setbuf(stdout, NULL); /* set unbuffered */
for (ptr = str; (c = *ptr++) != 0; )
putc(c, stdout);
}
输出:
output from child
output from parent
结果混乱的原因:
1.在一个a.out启动的两个进程之间可以肯定是不会发生混乱的
2.一定是在多个a.out之间造成的混乱,也就是说一个a.out还没有完全结束,另一个就开始了
3.Shell连续执行a.out的原则是:第一个a.out的父进程退出后,才会执行第2个a.out。由第2条可知,当一个a.out的父进程结束时,一定还有子进程没有结束,这个子进程和新启动的a.out发生了混乱输出。
解决办法:保证让一个child结束之后,parent再结束。这样就等于说一个 a.out完全结束后,才启动另一个a.out。
修改后的代码:
else if (pid == 0) {
WAIT_PARENT(); /* parent goes first */
charatatime("output from child\n");
TELL_PARENT(getppid()); /* tell parent we're done */
} else {
charatatime("output from parent\n");
TELL_CHILD(pid); /* tell child we're done */
WAIT_CHILD(); /* wait for child to finish */
}