日期:2014-05-16  浏览次数:20811 次

高手指点:Linux的exit调用的_IO_cleanup()为什么没起作用呢?
#include "apue.h" 

int glob = 6; /* external variable in initialized data */ 

int 
main(void) 

  int var; /* automatic variable on the stack */ 
  pid_t pid; 

  var = 88; 
  printf("before vfork\n"); /* we don 't flush stdio */ 
  if ((pid = vfork()) < 0) { 
  err_sys("vfork error"); 
  } else if (pid == 0) { /* child */ 
  glob++; /* modify parent 's variables */ 
  var++; 
  exit(0); /* child terminates */按照书上说的,这句应该关闭所有的I/O流啊 
  } 
  /* 
  * Parent continues here. 
  */ 
  printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var); 
  exit(0); 

可是结果仍然是: 
before vfork 
pid = 598, glob = 7, var = 89 
为什么exit(0)调用的cleanup 没起作用阿?

------解决方案--------------------
会有这两种结果

before vfork
pid = 598, glob = 6, var = 88

before vfork
pid = 598, glob = 7, var = 89


=============================
vfork(建立一个新的进程)
相关函数
wait,execve
表头文件
#include<unistd.h>
定义函数
pid_t vfork(void);
函数说明
vfork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量、已打开的文件代码、工作目录和资源限制等。Linux 使用copy-on-write(COW)技术,只有当其中一进程试图修改欲复制的空间时才会做真正的复制动作,由于这些继承的信息是复制而来,并非指相同的内存空间,因此子进程对这些变量的修改和父进程并不会同步。此外,子进程不会继承父进程的文件锁定和未处理的信号。注意,Linux不保证子进程会比父进程先执行或晚执行,因此编写程序时要留意
死锁或竞争条件的发生。

返回值
如果vfork()成功则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回0。如果vfork 失败则直接返回-1,失败原因存于errno中。
错误代码
EAGAIN 内存不足。ENOMEM 内存不足,无法配置核心所需的数据结构空间。
------解决方案--------------------


我看过Linux核了。vfork以后用户空间的内存是和父进程共享的,但文件描述表却是
和fork一样重新复制一份给子进程的。所以子进程调用close不会影响父亲进程。但
在用户空间的一些操作比如fflush(stdout), fclose(stdout)却会影响父进程。

vfork比起fork来就是多了两个标志:CLONE_VFORK 和 CLONE_VM,它们都没
有CLONE_FILES、CLONE_FS、CLONE_SIGHAND标志,所以fork与vfork在文件表项、信号
处理等方面是一致的,但由于vfork有CLONE_VM标志,所以它与父进程共享进程空间。
子进程通过内核文件表项的数据结构close(1)来关闭stdou并不影响父进程,但是通过
用户空间的库代码fflush就不一样了,此时父子是共享的。
------解决方案--------------------
manual都说了vfork以后子进程和父进程共享一切内存,包括堆栈,除非子进程调用execve。

你的变量都在堆栈里,按照manual,则子进程也共享这些变量,且你没有调用execve就修改了
变量,当然应该影响到父进程的堆栈变量。

exit 清理的是子进程单独持有的资源,对父进程的堆栈当然无法清理。