系统调用fork()允许一个进程创建一个新的进程,子进程获得父进程的栈、数据段、堆、执行文本段的副本.单击(此处)折叠或打开includepid_tfork(void);/*inparent:returnsprocessIDofchildonsuccess,or-1onerror;insuccessfullycreatedchild:alwaysreturns0*/大多数现代UNIX实现使用两个计数避免内存浪费:1.将每个进程的代码段标记为只读,这样父子进程就可以共享同一个代码段2.对于进程的数据段、堆段、栈段中的每个页父进程,内核使用copy-on-write)count来处理专门为子进程设计的vfork()来立即执行exec()程序click(here)tocollapseoropenincludepid_tvfork(void);,or-1onerror;insuccessfullycreatedchild:alwaysreturns0*/vfork()之所以效率更高,是因为以下两个特点:1.子进程不需要复制虚拟内存页或页表。相反,子进程共享父进程的内存,直到成功执行exec()或调用_exit()退出。2、子进程调用exec()或_exit()前,父进程的终止会被挂起:系统调用:点击(此处)折叠或打开includevoid_exit(intstatus);includevoidexit(intstatus);其中exit()会执行以下操作:1.调用exithandler(通过atexit()和on_exit()注册的函数),其执行顺序与注册顺序相反2.刷新stdio流Buffer3.使用status提供的值,用于执行_exit()系统调用。进程终止的详细信息不管进程是否正常终止,都会发生以下行为:1.关闭所有打开的文件描述符、目录流信息、目录描述符和(字符集)转换描述符2.作为文件描述符被关闭的结果,释放进程持有的任何文件锁3.任何附加的SystemV共享内存段被分离并对应于每个段的shm_nattch计数器值将减1。4.进程为每个SystemV信号量设置的semadj值将被添加到信号量值。5.如果进程是管理终端的管理进程,系统会向终端的前台进程组中的每个进程发送一个SIGHUP信号,终端会脱离会话(session)6.会关闭任何POSIX著名的进程开启的信号量,类似于调用sem_close()7.将关闭进程开启的信号量任意POSIX消息队列,类似于调用mq_close()8.作为进程退出的后果之一,如果一个进程组被调用孤儿,并且组中有任何停止的进程,组中的所有进程将收到SIGHUP信号,然后是SIGCONT信号9.通过mlock()或mlockall()删除进程创建的任何内存锁10.取消调用mmap()的进程创建的任何内存映射退出处理程序:如果程序直接调用_exit()或由于信号而异常终止,则不会调用退出处理程序单击(此处)折叠或打开包含intatexit(void(*func)(void));/*returns0onsuccess,ornonzeroonerror*/一旦任何退出处理程序返回失败,其余处理程序将不会被调用