关于linux下fork函数的调用
父进程会产生子进程,子进程会获得父进程的数据空间,堆和栈的副本。(注意:不是共享)
fork函数调用一次会返回两次
主要注意两点处理:1.子进程先退出,内核向父进程发送SIGCHLD信号,如果父进程不处理这个信号的话,子进程会变成僵尸进程
2.父进程先退出,子进程会变成孤儿进程,将会被1号进程收养,由于1号进程对它完成状态收集工作。(孤儿进程没什么危害)
问题1造成后果:父进程没处理子进程退出的信息,内核就不会释放这个数据结构,子进程的进程编号会被一直占用,大量僵尸进程会导致没有可用的进程号从而系统无法产生新的进程。(系统的进程号是有限的,释放掉一个进程号会有一段等待时间才会再次调用那个进程号)
僵尸进程产生:(让子进程先结束)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main()
{
int pid=fork();
if(pid==0)
{
printf("这是子进程%d\n",getpid());
sleep(5);
}
if(pid>0)
{
printf("这是父进程%d\n",getpid());
slep(10);
}
}
僵尸进程在父进程退出后也会消失。父进程不退出的话会一直存在
三种解决方法:1.在父进程中忽略SIGCHLD信号
运行观测:没有产生僵尸进程
2.在父进程中增加等待子进程退出的代码(使用wait函数)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
// signal(SIGCHLD,SIG_IGN);
int pid=fork();
if(pid==0)
{
printf("这是子进程%d\n",getpid());
sleep(5);
}
if(pid>0)
{
printf("这是父进程%d\n",getpid());
int sts;
wait(&sts);
sleep(10);
}
}
运行效果和上面一样;
但是有个问题是会阻塞在wait处等待,此时父进程做不了其他事情。
3.设置SIGCHLD的信号处理函数。在信号处理函数中调用wait,只要信号到达了,不需要等待
void func(int sig)
{
int sts;
wait(&sts);
}
int main()
{
signal(SIGCHLD,func);
int pid=fork();
if(pid==0)
{
printf("这是子进程%d\n",getpid());
sleep(5);
}
if(pid>0)
{
printf("这是父进程%d\n",getpid());
sleep(10);//子进程5秒后退出,信号是软信号会中断此信号的调用
sleep(10);
}
}