-
#include <stdio.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <unistd.h>
-
-
#define N 100
-
-
//拷贝src文件中指定长度为len的文件到dest文件中
-
int do_copy(int src,int dest,long int len )
-
{
-
int n = 0;
-
int sum = 0;
-
char buf[N] = {0};
-
-
while(sum < len)
-
{
-
//n为实际读到的字符个数,比如sizof(buf) = 100,但是若文件中没有
-
//100个字符时,比如是abcdef,则read返回的是能够读到的有效的字符个数6
-
n = read(src,buf,sizeof(buf));
-
-
if (n == 0)
-
{
-
break;
-
}
-
-
write(dest,buf,n);
-
-
sum += n;
-
}
-
-
return 0;
-
}
-
-
int main(int argc, const char *argv[])
-
{
-
int rfd = 0,
-
wfd = 0;
-
pid_t pid = 0;
-
long len = 0;
-
-
if(argc < 3)
-
{
-
fprintf(stderr,"Usage %s filename src dest\n",argv[0]);
-
exit(EXIT_FAILURE);
-
}
-
-
//源文件为只读方式打开
-
if((rfd = open(argv[1],O_RDONLY)) < 0)
-
{
-
fprintf(stderr,"Fail to open %s : %s\n",argv[1],strerror(errno));
-
exit(EXIT_FAILURE);
-
}
-
-
//目标文件为“w+”方式打开,文件可以不存在
-
if((wfd = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC,0666)) < 0)
-
{
-
fprintf(stderr,"Fail to open %s : %s\n",argv[2],strerror(errno));
-
exit(EXIT_FAILURE);
-
}
-
-
//求出源文件的长度
-
len = lseek(rfd,0,SEEK_END);
-
-
//填充目标文件,产生“空洞文件”,使其大小和源文件大小相同
-
lseek(wfd,len - 1,SEEK_SET);
-
write(wfd,"x",1);
-
-
if((pid = fork()) < 0)
-
{
-
perror("Fail to fork");
-
exit(EXIT_FAILURE);
-
}
-
-
//父进程拷贝文件的前一半
-
if(pid > 0)//parent
-
{
-
lseek(rfd,0,SEEK_SET);
-
lseek(wfd,0,SEEK_SET);
-
-
do_copy(rfd,wfd,len/2);
-
}
-
-
//需要注意的几个问题:
-
//1.对于源文件只能以只读的方式打开
-
//
-
//2.对于目标文件,在父进程中必须以类似"w+"的方式打开,文件不存在则
-
// 创建。
-
//
-
//3.在子进程中必须先关闭源文件和目标文件,重新打开。
-
// 否则,会出现以下问题:
-
//
-
// (1).若子进程中不先关闭文件然后在打开文件的话,如果子进程先运行时,
-
// 程序运行结果会不正确,原因是,此时子进程拷贝后一半完成后,父
-
// 进程再次执行时会把dest文件的内容清0,所以只会拷贝一半的数据。
-
//
-
// (2).若子进程中目标文件是以"w+"方式打开,如果父进程先运行,子进
-
// 程会把父进程拷贝的前一半数据清0,故错误。
-
//
-
// (3).子进程中以"w"的方式打开,不管是父进程先运行还是子进程先运行
-
// 程序的执行都不会出现错误。
-
-
//子进程拷贝文件的后一半
-
if(pid == 0)//child
-
{
-
close(rfd);
-
close(wfd);
-
-
if((rfd = open(argv[1],O_RDONLY)) < 0)
-
{
-
fprintf(stderr,"Fail to open %s : %s\n",argv[1],strerror(errno));
-
exit(EXIT_FAILURE);
-
}
-
-
if((wfd = open(argv[2],O_WRONLY)) < 0)
-
{
-
fprintf(stderr,"Fail to open %s : %s\n",argv[2],strerror(errno));
-
exit(EXIT_FAILURE);
-
}
-
-
//把源文件和目标文件的offset定位到文件的中间位置
-
lseek(rfd,len/2,SEEK_SET);
-
lseek(wfd,len/2,SEEK_SET);
-
-
do_copy(rfd,wfd,len - len / 2);
-
}
-
-
close(rfd);
-
close(wfd);
-
-
-
return 0;
-
}
运行结果如下:
-
litong@ltubuntu:~/exericse$ gcc par_chi_half_copy.c
-
litong@ltubuntu:~/exericse$ ./a.out src.txt dest.txt
-
litong@ltubuntu:~/exericse$ diff src.txt dest.txt
-
litong@ltubuntu:~/exericse$ cat dest.txt
-
pwdlsabcdesquiquitlitong@ltubuntu:~/exericse$
阅读(2052) | 评论(0) | 转发(0) |