父子进程
1.父子进程之间数据(.data\ .bss\ .stack\ .heap),都是不共享的
父子进程任意一个进程对数据的修改并不会影响另一个进程的数据
2.写时拷贝技术 —— .heap段
fork之后,父子进程共享所有的数据区域,但是内核将这些区域设置为只读,父子进程中任意一个进程试图修改数据,内核会将要修改的数据所在的页拷贝一份。
作用:提高fork的效率
fork之后,子进程往往会调用新的exec替换新的进程
3.父子进程是否共享fork之前打开的文件描述符
共享:子进程能够使用fork之前打开的文件描述符访问文件的内容
父子进程通过fork之前打开的文件描述访问文件时,是相互影响的——读写偏移量
如果子进程先结束,子进程结束时会执行close(fd),有没有关闭文件?
子:close(fd) 父:sleep(1);write();
僵尸进程
进程主体结束,但是进程的PCB依旧存在。在多进程编程中,父进程未结束,但是子进程已结束。
存在的意义:进程有四种结束方式,进程结束后,进程的退出状态需要保存到PCB结构中,为父进程获取子进程的退出状态。
进程真正结束:1.进程主体退出
2.PCB释放——父进程获取子进程的退出状态以后
父进程如何获取子进程的退出状态——已处理僵死进程,有两种方式:
1.pid_t wait(int *status); 返回处理的子进程PID,阻塞运行
2.pid_t waitpid(pid_t pid,int *status,int flag);
两个处理方式的区别为,第一种是阻塞运行,当条件未发生时,函数等待条件发生,条件发生后,函数才可以返回;第二种是非阻塞运行,无论条件是否发生,函数都会即可返回。
如果父进程创建n个子进程,wait调用n次。
父进程退出后为什么也能处理僵死进程?
如果父进程结束,则子进程会被挂在init下面。init是系统进程,其功能之一是处理僵死进程。
如果父进程不阻塞,还能及时处理僵死进程
wait调用时机:子进程已结束,父进程调用wait
那么子进程结束后通过何种机制通知父进程——信号