僵死进程
一个进程执行结束,但是进程的PCB没有被系统释放。进程结束后,在PCB中还要保存进程退出码,以备其父进程获取其退出码。
父进程未结束,子进程结束,并且父进程没有获取子进程的退出码
1 |
|
如何处理僵死进程:
父进程获取子进程的退出状态:
1 | pid_t wait(int *result); 本身会阻塞,直到任意一个子进程退出 |
1 |
|
进程替换
创建子进程以后,子进程执行的还是父进程的指令。
一个进程能够去执行另一份程序,fork()之后,子进程进行进程替换,父进程继续执行其指令,子进程就可以执行另一份指令。
main.c代码
1 |
|
test.c代码
1 |
|
由结果可以看出来,执行进程替换,仅仅是替换进程所执行的指令集,并没有创建新的进程。
写时拷贝技术:fork之后,往往子进程会执行exec
fork之前打开的文件,在子进程执行了exec之后,能不能通过此文件描述符访问该文件?
1 | 1、fork后子进程将复制父进程的数据段、BSS段、代码段、堆空间、栈空间和文件描述符。 |
exec函数
fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。
1 | int execl(char *pathname,char *argv0,char *argv1,...,(char *)0); |
1 | int execve(char *pathname,char *argv[],char *envp[]);这一个是系统调用 |
信号
信号是系统预先定义好的某些特定的事件,信号可以被产生,也可以被接收,产生和接收的实体都是进程。信号的作用就是一个进程向另一个进程通知某一事件的发生。
1、当进程收到信号时,他所处理的:默认 忽略 捕获(自定义)
编写程序实现,当进程在键盘输入Ctrl+c时,当前进程输出一个hello world,第二次收到结束进程
1 |
|
2、在程序中如何给一个进程发送一个信号
1 | int kill(pid_t pid,int sigtype); |
通过kill实现kill命令
1 |
|
利用信号解决僵死进程的方法
父进程需要调用wait方法,子进程结束会给父进程发送SIGCHLD,当父进程接收到SIGCHLD信号时,再调用wait方法,父进程不会阻塞。
父进程那些代码能够保证是在接收到信号之后执行,给SIGCHLD信号绑定一个信号处理函数(次函数会在接收到SIGCHLD信号之后才会被调用)
1 |
|