思维导图:
创建出三个进程完成两个文件之间拷贝工作,子进程1拷贝前一半内容,子进程2拷贝后一半内容,父进程回收子进程的资源。
代码:
#include<myhead.h>
int main(int argc, const char *argv[])
{
if(argc!=3)
{
printf("内容错误\n");
return -1;
}
//定义字符搬运工
char buf[100]="";
//以只读的形式打开源文件
FILE *rfp=NULL;
if((rfp=fopen(argv[1],"r"))==NULL)
{
perror("rfp error");
return -1;
}
//使用fseek和ftell函数定位到文件的数量
//fseek(文件指针,偏移量,开始的位置)
//ftell(文件中指针),直接返回文件的位置,既把指针最后的位置,返回文件数量
int num=0; //计数
fseek(rfp,0,SEEK_END); //光标偏移到文件最后的位置
num=ftell(rfp); //返回值就是文件的数量
fseek(rfp,0,SEEK_SET); //光标偏移到文件开头的位置
//定义追加写的形式打开文件
FILE *wfp=NULL;
if((wfp=fopen(argv[2],"a"))==NULL)
{
perror("wfp error");
return -1;
}
pid_t pid1=-1;
//创建一个子进程
pid1=fork();
if(pid1==0)
{
printf("我是老大\n");
printf("拷贝文档后部分内容\n");
//定义追加写的形式打开文件
FILE *wfp=NULL;
if((wfp=fopen(argv[2],"a"))==NULL)
{
perror("wfp error");
return -1;
}
//bzero(清零的地址,空间字节数)
//防止buf中有内容影响操作
bzero(buf,sizeof(buf)); //清零buf
//由于读文件已经打开,故需要把光标定位到开头
fseek(rfp,num/2,SEEK_SET); //光标定位从开头偏移到num/2后面
//由于需要限制位置,所以使用fread函数来进行读取
int count=fread(buf,sizeof(buf[0]),num-num/2,rfp);
//写入使用fwrite函数
fwrite(buf,sizeof(buf[0]),count,wfp);
//执行成功后关闭源文件以及被写入文件
fclose(rfp);
fclose(wfp);
sleep(2);
printf("拷贝文档后部分内容\n");
//退出老大进程
exit(EXIT_SUCCESS);
}
else if(pid1>0)
{
//创建一个子进程
pid_t pid2=fork();
if(pid2==0)
{
printf("我是老二\n");
printf("拷贝文档前一部分内容\n");
//定义追加写的形式打开文件
FILE *wfp=NULL;
if((wfp=fopen(argv[2],"a"))==NULL)
{
perror("wfp error");
return -1;
}
//bzero(清零的地址,空间字节数)
//防止buf中有内容影响操作
bzero(buf,sizeof(buf)); //清零buf
//由于读文件已经打开,故需要把光标定位到开头
fseek(rfp,0,SEEK_SET); //光标定位开头
//由于需要限制位置,所以使用fread函数来进行读取
int count=fread(buf,sizeof(buf[0]),num/2,rfp);
//写入使用fwrite函数
fwrite(buf,sizeof(buf[0]),count,wfp);
//关闭被写入文件
fclose(wfp);
sleep(5);
printf("拷贝前一部分内容完成\n");
//退出进程老二
exit(EXIT_SUCCESS);
}
else if(pid2>0)
{
printf("我是父进程,我来收回资源\n");
printf("我是父进程,我的第一个子进程pid:%d,第二个为:\
%d\n", pid1, pid2);
wait(NULL);
wait(NULL);
printf("孩子都死了,不活了\n");
}
else
{
perror("fork error");
return -1;
}
}
else
{
perror("fork error");
return -1;
}
return 0;
}
运行效果:
进程五种状态转换图