实现代码
#include<sys/stat.h> #include<sys/types.h> #include<fcntl.h> #include<unistd.h> #include<stdio.h> //perror() #include<stdlib.h> //exit() #define BUFFER_SIZE 1024 int main(int argc,char *argv[]) { int from_fd; int to_fd; unsigned int file_len; int ret = 1; char buf[BUFFER_SIZE]; char *ptr; if(argc != 3) { printf("Usage:%s fromfile tofile\n",argv[0]); exit(1); } //打开源文件 from_fd = open(argv[1],O_RDONLY); if(from_fd == -1) { printf("open %s failed.\n",argv[1]); exit(1); } //以只写的方式打开文件,没有的则创建文件 to_fd = open(argv[2],O_WRONLY|O_CREAT|O_APPEND,0666); //使用0666 if(to_fd == -1) { printf("open %s failed.\n",argv[2]); exit(1); } //源文件的大小 file_len = lseek(from_fd,0,SEEK_SET); //必须重新定位offset printf("%s size is %d bytes.\n",argv[1],file_len); while(ret) { ret = read(from_fd,buf,BUFFER_SIZE); if(ret == -1) { perror("read Error.\n"); } write(to_fd,buf,ret); file_len -= ret; // bzero(buf,BUFFER_SIZE); } printf("There are %d bytes data left without copy in %s\n",file_len,argv[1]); close(from_fd); close(to_fd); return 0; }
1.注意权限必需使用0666,最好是宏
2.使用mmap操作更加高效
#include<sys/mman.h> #include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> int main(void) { int len; //打开文件,以读写的方式打开 int fd; fd = open("hello",O_RDWR); //hello 文件存在 if(fd == -1) { perror("open"); return -1; } len = lseek(fd,0L,SEEK_END); // lseek(fd,0,SEEK_SET); //将文件映射到进程的虚拟地址空间 void *p = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(p==MAP_FAILED) { perror("mmap"); return -1; } int *q = (int*)p; q[0] = 0x20202020; q[1] = 0x41414141; munmap(p,len); close(fd); }
使用mmap将物理内存映射到进程的虚拟地址空间
mmap(2) 系统调用,实现代码在内核,内核态
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
将文件和设备映射到进程的虚拟地址空间
Linux下一切皆文件
参数:
addr: 它指定了开始地址,在进程的虚拟地址空间里,取值为NULL,由内核决定具体的地址
length:指定了映射的区域的长度
prot:
PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.
flags:
MAP_SHARED Share this mapping. 对映射区域的更改反映到其他进程里,同步到underlying底层文件
MAP_PRIVATE Create a private copy-on-write mapping. 对于映射区域的映射不反映到其他进程里,不同步到文件,除非msync
MAP_ANONYMOUS 匿名映射,和文件无关,映射的区域全部清为0
fd: -1
offset:文件的偏移 0
返回值:
正确:隐射区域首地址
错误:MAP_FAILED (void*)-1 errno 被设置
int munmap(void *addr, size_t length);
解除映射
addr: mmap()的返回值
length:指定了解除映射区域的长度
返回值:成功为0,错误为-1,errno被设置