转自
linux 文件io管理-Posix https://www.cnblogs.com/Jimmy1988/p/7488709.html
posix 文件操作一 read/write/open/close/fcntl/mmap https://www.jianshu.com/p/b86298645e08
posix文件操作二 mmap https://www.jianshu.com/p/9af7058512bf
简单总结:
在移动开发中,难免要做一些跨平台的事情。iOS和Android各执一套,平台很难跨。但其底层Linux和Unix则早早做了一套不错的兼容标准。这套标准就是POSIX
完成同一功能,不同内核提供的系统调用(也就是一个函数)是不同的,例如创建进程,linux下是fork函数,windows下是creatprocess函数。好,我现在在linux下写一个程序,用到fork函数,那么这个程序该怎么往windows上移植?我需要把源代码里的fork通通改成creatprocess,然后重新编译...
posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork(随便说的),windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用posix_fork函数,程序就在源代码级别可移植了
posix文件操作--基础读写等
基础读写操作
以下示例需要头文件
1 #include <fcntl.h> 2 #include <stdio.h> 3 #include <unistd.h>
打开文件
1 #define FILE_NAME "./test.txt" 2 3 if((fd_open_create=open(FILE_NAME,O_CREAT|O_RDWR,0644))==-1) 4 { 5 perror("open"); 6 } 7 printf("the %s file descriptor is:%d ",FILE_NAME,fd_open_create);
open方法,我们输入了三个参数,分别是:
- 文件的相对路径
- 文件的打开方式
- 文件的权限
这里有一些值得注意的点。
文件路径
笔者是在xcode下开发的c++,运行程序后的可执行文件,并不在工程目录下。因此,使用
相对路径时也要注意。相对路径的基点在运行后的可执行文件处。xcode中有一种简单的找到此目录的办法,即是在右边的工程目录栏中的Products下,找到可执行文件,右键'Show in Finder'。
文件打开方式
在fcntl.h中,我们可以看到如下宏定义
1 /* open-only flags */ 2 #define O_RDONLY 0x0000 /* open for reading only */ 3 #define O_WRONLY 0x0001 /* open for writing only */ 4 #define O_RDWR 0x0002 /* open for reading and writing */ 5 #define O_ACCMODE 0x0003 /* mask for above modes */ 6 7 /* 8 * Kernel encoding of open mode; separate read and write bits that are 9 * independently testable: 1 greater than the above. 10 * 11 * XXX 12 * FREAD and FWRITE are excluded from the #ifdef KERNEL so that TIOCFLUSH, 13 * which was documented to use FREAD/FWRITE, continues to work. 14 */ 15 #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) 16 #define FREAD 0x0001 17 #define FWRITE 0x0002 18 #endif 19 #define O_NONBLOCK 0x0004 /* no delay */ 20 #define O_APPEND 0x0008 /* set append mode */ 21 22 #include <sys/_types/_o_sync.h> 23 24 #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) 25 #define O_SHLOCK 0x0010 /* open with shared file lock */ 26 #define O_EXLOCK 0x0020 /* open with exclusive file lock */ 27 #define O_ASYNC 0x0040 /* signal pgrp when data ready */ 28 #define O_FSYNC O_SYNC /* source compatibility: do not use */ 29 #define O_NOFOLLOW 0x0100 /* don't follow symlinks */ 30 #endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ 31 #define O_CREAT 0x0200 /* create if nonexistant */ 32 #define O_TRUNC 0x0400 /* truncate to zero length */ 33 #define O_EXCL 0x0800 /* error if already exists */
通过标志位运算的方式,定义了各种打开行为。在此不一一赘述,读者可以通过后面的注释大致了解这些标志位所控制的行为。
文件权限
这里对文件的权限进行了设置,0644的逻辑与chmod类似。第一位决定了是文件还是目录,后面三位则决定了,不同用户组,对此文件rwe(read,write,execute)权限。
这一段可以参考File Permissons。
文件写入
1 const char buf1[] = "1234567890abc "; // 临时需要写入的信息 2 // write chars to file at head 3 if( write(fd_open_create, buf1, 10) != 10 ) 4 { 5 perror("write"); 6 } 7 printf("the %s file write ",FILE_NAME);
这一段比较简单,就是将buf1
中的前10个字符写入文件中。值得注意的是,这样的写入是复写的方式。如果想要在已有内容后面添加,文件需要使用O_APPEND
方式打开。
光标移动
我们在写入过程中,可能会有些特殊需求,在文字中,直接改写某些地方(注意:这里只能改写,不能插入)。在这样的情景下,我们需要移动光标
1 const char buf2[] = "ABCDEFGHIJ "; 2 // move cursor in file 3 if(lseek(fd_open_create, 5, SEEK_SET) == -1) // 从5位置写 4 { 5 perror("lseek"); 6 exit(EXIT_FAILURE); 7 } 8 printf("the %s file lseek ",FILE_NAME); 9 10 // write chars to file at seek position 11 if( write(fd_open_create, buf2, 10) != 10 ) 12 { 13 perror("write"); 14 } 15 printf("the %s file write ",FILE_NAME);
在上面的例子中,我们将光标移动至第5位,然后再开始写入。
文件读取
与上面的操作类似,文件的读取,也是从光标处开始的。
1 // move cursor in file 2 if(lseek(fd_open_create, 3, SEEK_SET) == -1) // 从3位置读取 3 { 4 perror("lseek"); 5 exit(EXIT_FAILURE); 6 } 7 // read chars from file 8 if( read(fd_open_create, bufr, 15) == 0) 9 { 10 perror("read"); 11 } 12 13 printf("the %s file read content : %s ",FILE_NAME , bufr);
关闭文件
1 close(fd_open_create);
锁定/解锁文件
flock()函数和fcntl()都可以对文件进行锁定和解锁.但是前者只能锁定整个文件,而后者可以提供任意位置的文件锁定
1 fcntl(fd_open_create, F_SETLKW, file_lock(F_WRLCK, SEEK_SET)); 2 fcntl(fd_open_create, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
posix文件操作--mmap
简单来说,mmap通过一种方法将文件映射到内存中,我们修改内存即是修改文件。具体它与一般I/O操作有什么区别,可以参考:
从内核文件系统看文件读写过程
认真分析mmap:是什么 为什么 怎么用
使用范例
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <sys/mman.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <sys/stat.h> 8 9 #define FILE_NAME "./test.txt" 10 11 int main(int argc, const char * argv[]) { 12 13 int fd_open_create; 14 char* buf; 15 16 if((fd_open_create=open(FILE_NAME,O_CREAT|O_RDWR,0644))==-1) 17 { 18 perror("open"); 19 } 20 printf("the %s file descriptor is:%d ",FILE_NAME,fd_open_create); 21 22 //取得文件状态)相关函数 fstat,lstat,chmod,chown,readlink,utime 23 struct stat statbuf; 24 if(stat(FILE_NAME,&statbuf)==-1) 25 { 26 //文件不存在 27 perror("fail to get stat"); 28 exit(1); 29 } 30 // 建立内存映射,)用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。 31 // 获取mmap映射内存 32 buf=(char*)mmap(NULL,statbuf.st_size,PROT_WRITE|PROT_READ,MAP_SHARED,fd_open_create,0); 33 if(buf==MAP_FAILED) 34 { 35 perror("fail to mmap"); 36 exit(1); 37 } 38 // 直接修改mmap映射内存 39 buf[0]='6'; 40 //解除内存映射(在解除之前,文件已被修改,但系统并不保证已修改同步完成,可以自行加死循环验证) 41 if(munmap(buf,statbuf.st_size)==-1) 42 { 43 perror("fail to munmap"); 44 exit(1); 45 } 46 // 采用read方式读取,验证文件内容 47 char bufr[128]; 48 if( read(fd_open_create, bufr, statbuf.st_size) == 0) 49 { 50 perror("read"); 51 } 52 53 printf("the %s file read content : %s ",FILE_NAME , bufr); 54 close(fd_open_create); 55 return (EXIT_SUCCESS); 56 }
作者:oceanLong
链接:https://www.jianshu.com/p/9af7058512bf
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。