Chinaunix首页 | 论坛 | 博客
  • 博客访问: 552783
  • 博文数量: 181
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1498
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-22 15:17
个人简介

用发呆的时间来理清自己的思绪

文章存档

2015年(7)

2014年(134)

2013年(40)

分类: 嵌入式

2014-06-22 19:51:54


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>

  9. #define N 100

  10. //拷贝src文件中指定长度为len的文件到dest文件中
  11. int do_copy(int src,int dest,long int len )
  12. {
  13.     int n = 0;
  14.     int sum = 0;
  15.     char buf[N] = {0};

  16.     while(sum < len)
  17.     {
  18.         //n为实际读到的字符个数,比如sizof(buf) = 100,但是若文件中没有
  19.         //100个字符时,比如是abcdef,则read返回的是能够读到的有效的字符个数6
  20.         n = read(src,buf,sizeof(buf));
  21.         
  22.         if (n == 0)
  23.         {
  24.             break;
  25.         }

  26.         write(dest,buf,n);

  27.         sum += n;
  28.     }

  29.     return 0;
  30. }

  31. int main(int argc, const char *argv[])
  32. {
  33.     int rfd = 0,
  34.         wfd = 0;
  35.     pid_t pid = 0;
  36.     long len = 0;

  37.     if(argc < 3)
  38.     {
  39.         fprintf(stderr,"Usage %s filename src dest\n",argv[0]);
  40.         exit(EXIT_FAILURE);
  41.     }

  42.     //源文件为只读方式打开
  43.     if((rfd = open(argv[1],O_RDONLY)) < 0)
  44.     {
  45.         fprintf(stderr,"Fail to open %s : %s\n",argv[1],strerror(errno));
  46.         exit(EXIT_FAILURE);
  47.     }

  48.     //目标文件为“w+”方式打开,文件可以不存在
  49.     if((wfd = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC,0666)) < 0)
  50.     {
  51.         fprintf(stderr,"Fail to open %s : %s\n",argv[2],strerror(errno));
  52.         exit(EXIT_FAILURE);
  53.     }

  54.     //求出源文件的长度
  55.     len = lseek(rfd,0,SEEK_END);

  56.     //填充目标文件,产生“空洞文件”,使其大小和源文件大小相同
  57.     lseek(wfd,len - 1,SEEK_SET);
  58.     write(wfd,"x",1);

  59.     if((pid = fork()) < 0)
  60.     {
  61.         perror("Fail to fork");
  62.         exit(EXIT_FAILURE);
  63.     }

  64.     //父进程拷贝文件的前一半
  65.     if(pid > 0)//parent
  66.     {
  67.         lseek(rfd,0,SEEK_SET);
  68.         lseek(wfd,0,SEEK_SET);

  69.         do_copy(rfd,wfd,len/2);
  70.     }
  71.     
  72.     //需要注意的几个问题:
  73.     //1.对于源文件只能以只读的方式打开
  74.     //
  75.     //2.对于目标文件,在父进程中必须以类似"w+"的方式打开,文件不存在则
  76.     // 创建。
  77.     //
  78.     //3.在子进程中必须先关闭源文件和目标文件,重新打开。
  79.     // 否则,会出现以下问题:
  80.     //
  81.     // (1).若子进程中不先关闭文件然后在打开文件的话,如果子进程先运行时,
  82.     //      程序运行结果会不正确,原因是,此时子进程拷贝后一半完成后,父
  83.     //      进程再次执行时会把dest文件的内容清0,所以只会拷贝一半的数据。
  84.     //
  85.     // (2).若子进程中目标文件是以"w+"方式打开,如果父进程先运行,子进
  86.     // 程会把父进程拷贝的前一半数据清0,故错误。
  87.     //
  88.     // (3).子进程中以"w"的方式打开,不管是父进程先运行还是子进程先运行
  89.     // 程序的执行都不会出现错误。

  90.     //子进程拷贝文件的后一半
  91.     if(pid == 0)//child
  92.     {
  93.         close(rfd);
  94.         close(wfd);

  95.         if((rfd = open(argv[1],O_RDONLY)) < 0)
  96.         {
  97.             fprintf(stderr,"Fail to open %s : %s\n",argv[1],strerror(errno));
  98.             exit(EXIT_FAILURE);
  99.         }

  100.         if((wfd = open(argv[2],O_WRONLY)) < 0)
  101.         {
  102.             fprintf(stderr,"Fail to open %s : %s\n",argv[2],strerror(errno));
  103.             exit(EXIT_FAILURE);
  104.         }

  105.         //把源文件和目标文件的offset定位到文件的中间位置
  106.         lseek(rfd,len/2,SEEK_SET);
  107.         lseek(wfd,len/2,SEEK_SET);

  108.         do_copy(rfd,wfd,len - len / 2);
  109.     }

  110.     close(rfd);
  111.     close(wfd);

  112.     
  113.     return 0;
  114. }
运行结果如下:

点击(此处)折叠或打开

  1. litong@ltubuntu:~/exericse$ gcc par_chi_half_copy.c
  2. litong@ltubuntu:~/exericse$ ./a.out src.txt dest.txt
  3. litong@ltubuntu:~/exericse$ diff src.txt dest.txt
  4. litong@ltubuntu:~/exericse$ cat dest.txt
  5. pwdlsabcdesquiquitlitong@ltubuntu:~/exericse$


阅读(2052) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~