子进程由父进程fork而来,拷贝父进程的全部代码,但执行时是选择执行的:从fork后开始执行。比如父进程第一次fork产生的子进程,在第二次fork后变成了父进程,也产生了一个子进程,而不会去执行第一次fork。
子进程继承了父进程的一切。也就是说,子进程虽然没有执行父进程fork之前的代码,但结果是和执行了fork之前的代码一样。
在fork前后打开文件,子进程和父进程的文件描述符一样,file结构体里的引用加1。fork前打开文件,子进程和父进程用同一文件指针,fork后打开文件,子进程和父进程使用不同的文件指针。
使用追加的方式打开文件,文件没有数据写入时,文件指针的位置在文件头,有数据写入,文件指针移到文件尾。
fork后打开文件
#include<unistd.h>
#include<stdio.h>
#include<string.h>
//#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<dirent.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//
//
int main()
{
int i1=0;
// while(1)
// {
pid_t pid=-1;
int fd=-1;
pid=fork();
printf("&i1=%p\n",&i1);
printf("fd=%d\n",fd);
printf("songshiqi\n");
fd=open("tea.info",O_RDWR|O_CREAT|O_APPEND);
if(fd==-1)
{
printf("打开失败\n");
return -1;
}
int ret1=lseek(fd,0,SEEK_CUR);
printf("ret1=%d\n",ret1);
int iNum=0;
int i=0;
char caData[32]={'\0'};
if(pid>0)//父进程
{
printf("&i1=%p\n",&i1);
printf("fd=%d\n",fd);
while(1)
{
i1++;
printf("i1=%d\n",i1);
if(i1==10)
{
return 0;
}
sleep(1);
int ret1=lseek(fd,0,SEEK_CUR);
printf("fujincheng ret1=%d\n",ret1);
int ret=-1;
ret=write(fd,"333",3);
if(ret==-1)
{
printf("写入失败\n");
return -1;
}
printf("成功写入%d\n",ret);
// close(fd);
}
close(fd);
}
else if(pid==0)//子进程
{
printf("fd=%d\n",fd);
printf("进入子进程\n");
printf("&i1=%p\n",&i1);
while(1)
{
i1++;
printf("i1=%d\n",i1);
if(i1>=10)
{
return 0;
}
// printf("进入循环\n");
sleep(2);
/* int fd=-1;
fd=open("tea.info",O_RDWR|O_CREAT);
if(fd==-1)
{
printf("打开失败\n");
return -1;
}*/
int ret=-1;
ret=lseek(fd,0,SEEK_CUR);
if(ret==-1)
{
printf("失败\n");
return -1;
}
printf("该文件有%d字节大小\n",ret);
// close(fd);
}
close(fd);
}
else if(pid==-1)//创建进程失败 子进程 父进程完整拷贝
{
printf("fork\n");
return -1;
}
/* for(;i<iNum;i++)
{
printf("%s",caData);
}
printf("hello wolrd1\n");
while(1)
{
sleep(2);
}*/
close(fd);
return 0;
}
fork前打开文件
#include<unistd.h>
#include<stdio.h>
#include<string.h>
//#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<dirent.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
int i1=0;
// while(1)
// {
pid_t pid=-1;
int fd=-1;
fd=open("tea.info",O_RDWR|O_CREAT);
if(fd==-1)
{
printf("打开失败\n");
return -1;
}
pid=fork();
printf("&i1=%p\n",&i1);
printf("fd=%d\n",fd);
printf("songshiqi\n");
int iNum=0;
int i=0;
char caData[32]={'\0'};
if(pid>0)//父进程
{
printf("&i1=%p\n",&i1);
printf("fd=%d\n",fd);
while(1)
{
i1++;
printf("i1=%d\n",i1);
if(i1==10)
{
return 0;
}
sleep(1);
int ret2=lseek(fd,0,SEEK_CUR);
printf("fu ret2=%d\n",ret2);
int ret=-1;
ret=write(fd,"333",3);
if(ret==-1)
{
printf("写入失败\n");
return -1;
}
printf("成功写入\n");
ret2=lseek(fd,0,SEEK_CUR);
printf("fu ret2=%d\n",ret2);
// close(fd);
}
close(fd);
}
else if(pid==0)//子进程
{
printf("fd=%d\n",fd);
printf("进入子进程\n");
printf("&i1=%p\n",&i1);
while(1)
{
i1++;
printf("i1=%d\n",i1);
if(i1>=10)
{
return 0;
}
// printf("进入循环\n");
sleep(2);
/* int fd=-1;
fd=open("tea.info",O_RDWR|O_CREAT);
if(fd==-1)
{
printf("打开失败\n");
return -1;
}*/
int ret2=lseek(fd,0,SEEK_CUR);
printf("zi ret2=%d\n",ret2);
int ret=-1;
ret=lseek(fd,0,SEEK_CUR);
if(ret==-1)
{
printf("失败\n");
return -1;
}
printf("该文件有%d字节大小\n",ret);
// close(fd);
}
close(fd);
}
else if(pid==-1)//创建进程失败 子进程 父进程完整拷贝
{
printf("fork\n");
return -1;
}
/* for(;i<iNum;i++)
{
printf("%s",caData);
}
printf("hello wolrd1\n");
while(1)
{
sleep(2);
}*/
close(fd);
return 0;
}
文件一次循环使用3次fork,第一次fork产生1个父进程和1个子进程,第二次fork产生2个父进程和2个子进程,第3次fork产生4个父进程和4个子进程,和上面的理论相符。
一次fork3次循环产生的效果一样。
一次循环3次fork:
#include<unistd.h>
#include<stdio.h>
#include<string.h>
int main()
{
// while(1)
// {
pid_t pid=-1;
pid=fork();
int iNum=0;
int i=0;
char caData[32]={'\0'};
if(pid>0)//父进程
{
printf("this is parent process\n");
strcpy(caData,"this is parent process\n");
printf("the parent:%d\n",pid);
iNum=3;
}
else if(pid==0)//子进程
{
printf("this is child process\n");
strcpy(caData,"this is child process\n");
printf("the child:%d\n",pid);
iNum=6;
}
else if(pid==-1)//创建进程失败 子进程 父进程完整拷贝
{
printf("fork\n");
return -1;
}
// for(;i<iNum;i++)
// {
// printf("%s",caData);
// }
printf("hello wolrd1\n");
sleep(6);
pid_t pid1=-1;
pid1=fork();
int iNum1=0;
int i1=0;
char caData1[32]={'\0'};
if(pid1>0)//父进程
{
printf("this is parent process\n");
strcpy(caData1,"this is parent process\n");
printf("the parent:%d\n",pid1);
iNum1=3;
}
else if(pid1==0)//子进程
{
printf("this is child process\n");
strcpy(caData1,"this is child process\n");
printf("the child:%d\n",pid1);
iNum1=6;
}
else if(pid1==-1)//创建进程失败 子进程 父进程完整拷贝
{
printf("fork\n");
return -1;
}
printf("hello wolrd2\n");
pid_t pid12=-1;
pid12=fork();
int iNum12=0;
int i12=0;
char caData12[32]={'\0'};
if(pid12>0)//父进程
{
printf("this is parent process\n");
strcpy(caData12,"this is parent process\n");
printf("the parent:%d\n",pid12);
iNum12=3;
}
else if(pid12==0)//子进程
{
printf("this is child process\n");
strcpy(caData12,"this is child process\n");
printf("the child:%d\n",pid12);
iNum12=6;
}
else if(pid12==-1)//创建进程失败 子进程 父进程完整拷贝
{
printf("fork\n");
return -1;
}
printf("hello wolrd3\n");
// sleep(6);
while(1)
{
sleep(2);
}
// printf("hello wolrd\n");
// sleep(4);
// printf("songshiqi\n");
// }
return 0;
}
僵尸进程的解决办法一是父进程使用wait函数,执行阻塞直到子进程结束获得子进程的退出状态,并对子进程做清理工作;二是父进程尽快执行完,由祖宗进程来完成善后。
网友评论