目录
一,僵尸进程
1,僵尸进程
来一个创建维持30秒的僵死进程例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t id = fork();
if (id < 0) {
perror("fork");
return 1;
}
else if (id > 0) { //parent
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}
else {
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}
当fork()函数返回值,父进程和子进程同时启动,当子进程运行结束退出进程时,父进程还在等待,此时子进程一直在等待父进程读取其退出状态代码,于是产生了僵尸状态;
僵尸状体会造成内存泄漏,我们要尽可能避免;
2,僵尸进程的危害
进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
内存泄漏?是的!
二,孤儿进程
1,孤儿进程
我们写一个进程来感受一下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t id = fork();
if (id < 0) {
perror("fork");
return 1;
}
else if (id == 0) {//child
printf("I am child, pid : %d\n", getpid());
sleep(10);
}
else {//parent
printf("I am parent, pid: %d\n", getpid());
sleep(3);
exit(0);
}
return 0;
}
fork()函数返回后,子进程和父进程同时运行,当父进程执行结束并且退出后,子进程还在运行,此时子进程沦为孤儿!
一般孤儿进程最后会被1号init进程领养,不会造成内存泄漏;
三,进程等待
1,进程等待的必要性
2,wait 方法
#include <stdio. h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys / wait.h>
int main()
{
pid_t id = fork();
if (id < 0) {
perror("fork");
return 1;
}
else if (id == 0) {
//parent
printf("child[%d] is sleeping...\n", getpid());
sleep(5);
exit(3);
}
int status = 0;
pid_t rid = wait(&status);
if (rid > 0)
{
printf("parent[%d] is begin Z...\n", rid);
sleep(10);
}
else
{
printf("进程失败:rid:%d\n", rid);
}
return 0;
}
这样子 wait 会自动及时回收子进程,不会形成僵尸,不会造成内存泄漏;
3,waitpid 方法
#include <stdio. h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys / wait.h>
int main()
{
pid_t id = fork();
if (id < 0) {
perror("fork");
return 1;
}
else if (id == 0) {
//parent
printf("child[%d] is sleeping...\n", getpid());
sleep(5);
exit(3);
}
int status = 0;
pid_ t rid = waitpid(-1,&status,0);
if (rid > 0)
{
printf("parent[%d] is begin Z...\n", rid);
sleep(10);
}
else
{
printf("进程失败:rid:%d\n", rid);
}
return 0;
}