Chinaunix首页 | 论坛 | 博客
  • 博客访问: 986240
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

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,由于chilldparent都有各自的一份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是一个使用伪码来进行进程间同步的程序,力图让父子进程能够按顺序输出。

Figure 8.13. Modification of to avoid race condition
   #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还没有完全结束,另一个就开始了

3Shell连续执行a.out的原则是:第一个a.out的父进程退出后,才会执行第2a.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 */
     }

 

阅读(1061) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~