zoukankan      html  css  js  c++  java
  • [转]posix

    转自  

    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是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享

    简单来说,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
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    输入流输出流打印到文件
    前缀和
    树形dp
    快速幂 ,快速幂优化,矩形快速幂(java)
    尾递归
    java中bigInteger的应用
    求树的最大直径
    买不到的数目
    ccpc 长春站 G
    大学ACM第二周心得
  • 原文地址:https://www.cnblogs.com/yi-mu-xi/p/12567161.html
Copyright © 2011-2022 走看看