Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1743431
  • 博文数量: 297
  • 博客积分: 285
  • 博客等级: 二等列兵
  • 技术积分: 3006
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-06 22:04
个人简介

Linuxer, ex IBMer. GNU https://hmchzb19.github.io/

文章分类

全部博文(297)

文章存档

2020年(11)

2019年(15)

2018年(43)

2017年(79)

2016年(79)

2015年(58)

2014年(1)

2013年(8)

2012年(3)

分类: LINUX

2015-10-26 10:09:04

第一个版本,使用的系统调用,没有使用C库的函数。

点击(此处)折叠或打开

  1. #include <apue.h>
  2. #include <fcntl.h>
  3. #define BUFFERSIZE 4096
  4. #define COFYMODE 0644

  5. void die(char* string1, char* string2); //print error and quit


  6. void die(char* string1,char* string2){
  7.     fprintf(stderr,"Error: %s ",string1);
  8.     perror(string2);
  9.     exit(1);
  10.     }


  11. int main(int argc, char *argv[])
  12. {
  13.     int source_fd,target_fd,n_chars;
  14.     char buf[BUFFERSIZE];

  15.     if(argc!=3){
  16.         fprintf(stderr,"usage: %s source destination\n",*argv);
  17.         exit(1);
  18.         }

  19.     //try to open files
  20.     if((source_fd=open(argv[1],O_RDONLY))==-1)
  21.         die("cannot open ",argv[1]);
  22.     if((target_fd=creat(argv[2],COFYMODE))==-1)
  23.         die("can not create ",argv[2]);
  24.     
  25.     //copy from source to target
  26.     while((n_chars=read(source_fd,buf,BUFFERSIZE))>0){
  27.         if(n_chars!=write(target_fd,buf,n_chars))
  28.             die("Write error to ",argv[2]);
  29.             }
  30.     if(-1==n_chars)
  31.         die("read error from ",argv[1]);


  32.     //close both files
  33.     if(close(source_fd)==-1 || close(target_fd)==-1)
  34.         die("Error closing files","");

  35.     return 0;
  36.     }
第二个版本:使用了mmap函数把文件映射入内存,应该是对文件频繁读写最适合的一种解决方式。
1


点击(此处)折叠或打开

  1. #include <apue.h>
  2. #include <sys/mman.h>
  3. #include <fcntl.h>
  4. /* cp3.c --a copy program using memory-mapped I/0 */

  5. #define COFYMODE 0666

  6. void die(char* string1,char* string2){
  7.     fprintf(stderr,"Error: %s ",string1);
  8.     perror(string2);
  9.     exit(1);
  10. }


  11. int main(int argc, char *argv[])
  12. {
  13.     int in_fd,out_fd;
  14.     size_t filesize;
  15.     char nullbyte;
  16.     void *source_addr;
  17.     void *dest_addr;

  18.     /* check args */
  19.     if(argc!=3){
  20.         fprintf(stderr,"usage: %s source destination \n", *argv);
  21.         exit(1);
  22.     }

  23.     /* open files */
  24.     if((in_fd=open(argv[1],O_RDONLY))==-1)
  25.         die("Cannot open ",argv[1]);

  26.     
  27.     #if defined(i386) || defined(__x86_64) || defined(__x86_64__) || defined(i686)
  28.         if((out_fd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,COFYMODE))==-1)
  29.             die("Can not create ",argv[2]);
  30.     
  31.     #else
  32.         if((out_fd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,COFYMODE))==-1)
  33.             die("can not create ",argv[2]);

  34.     #endif
  35.     /* get the size of the source file by seeking to the end of it :
  36.     lseek ( ) returns the offset location of the file pointer after
  37.     the seek relative to the beginning of the file , so this is a
  38.     good way to get an opened file 
  39.     ×/
  40.     if((filesize=lseek(in_fd,0,SEEK_END))==-1)
            die("Could not seek to end of file",argv[1]);


        /* by seeking to filesize in the new file can be grown to that size,
        * its size does not change until a write occurs
        */
        lseek(out_fd,filesize-1,SEEK_SET);




        /* so we write the NULL byte and file size is now set to filesize */
        write(out_fd,&nullbyte,1);


        /* time to setup the memory maps */
        if((source_addr=mmap(NULL,filesize,PROT_READ,MAP_SHARED,in_fd,0))==(void *)-1)
            die("Error mapping file ",argv[1]);


        if((dest_addr=mmap(NULL,filesize,PROT_WRITE,MAP_SHARED,out_fd,0))==(void *)-1)
            die("Error mapping file, ",argv[2]);


        /* copy the input to output by doing a memcpy */
        memcpy(dest_addr,source_addr,filesize);


        /*unmap the fiels */
        munmap(source_addr,filesize);
        munmap(dest_addr,filesize);


        /* close the files */
        close(in_fd);
        close(out_fd);


        return 0;
        }
我还顺便用strace 来看了下:

点击(此处)折叠或打开

  1. [root@c653f1u25 system_program]# strace ./cp3 1.txt 4.txt
  2. execve("./cp3", ["./cp3", "1.txt", "4.txt"], [/* 38 vars */]) = 0
  3. brk(0) = 0x11f4000
  4. mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb194b72000
  5. access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
  6. open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
  7. fstat(3, {st_mode=S_IFREG|0644, st_size=150792, ...}) = 0
  8. mmap(NULL, 150792, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb194b4d000
  9. close(3) = 0
  10. open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
  11. read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\34\2\0\0\0\0\0"..., 832) = 832
  12. fstat(3, {st_mode=S_IFREG|0755, st_size=2107760, ...}) = 0
  13. mmap(NULL, 3932736, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb194591000
  14. mprotect(0x7fb194747000, 2097152, PROT_NONE) = 0
  15. mmap(0x7fb194947000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7fb194947000
  16. mmap(0x7fb19494d000, 16960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb19494d000
  17. close(3) = 0
  18. mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb194b4c000
  19. mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb194b4a000
  20. arch_prctl(ARCH_SET_FS, 0x7fb194b4a740) = 0
  21. mprotect(0x7fb194947000, 16384, PROT_READ) = 0
  22. mprotect(0x600000, 4096, PROT_READ) = 0
  23. mprotect(0x7fb194b73000, 4096, PROT_READ) = 0
  24. munmap(0x7fb194b4d000, 150792) = 0
  25. open("1.txt", O_RDONLY) = 3
  26. open("4.txt", O_RDWR|O_CREAT|O_TRUNC, 0666) = 4
  27. lseek(3, 0, SEEK_END) = 16
  28. lseek(4, 15, SEEK_SET) = 15
  29. write(4, "\0", 1) = 1
  30. mmap(NULL, 16, PROT_READ, MAP_SHARED, 3, 0) = 0x7fb194b71000
  31. mmap(NULL, 16, PROT_WRITE, MAP_SHARED, 4, 0) = 0x7fb194b70000
  32. munmap(0x7fb194b71000, 16) = 0
  33. munmap(0x7fb194b70000, 16) = 0
  34. close(3) = 0
  35. close(4) = 0
  36. exit_group(0) = ?
  37. +++ exited with 0 +++
看到了很多熟悉的system call.
execve,brk lseek,哈哈。


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