zoukankan      html  css  js  c++  java
  • 第三章:文件 I/O

    文件描述符

      文件描述符的早期上限为20 , 现在增到 63; 其变化范围为 0 ~ OPEN_MAX

    open函数

      int  open(const char* filename , int oflag , ... /*mode_t  mode*/);

      filename  :  要打开文件的名字

      oflag     :  打开方式

              O_RDONLY 、 O_WRONLY 、O_RDWR 三个常量必须指定一个

              O_APPEND  、 O_CREAT  、O_EXCL 、O_TRUNC等是可选择的

              O_CREAT | O_EXCL 组和可用于判断文件是否存在,存在则打出错,否则创建新文件

    /***********************************************
    *function       : check if a file exist
    *params         : @filename: pointer to the buffer
    *return         : return -1 if exist or -1 if not
    ************************************************/
    int             is_file_exist(const char* filename);

    int             is_file_exist(const char* filename)
    {
            int             fd;

            if(filename == NULL)
                    return  0;
            fd = open(filename,O_RDONLY|O_EXCL|O_CREAT);
            if(fd != -1){

          close(fd);
                    remove(filename);
                    return  0;
            }
            return  1;
    }


    O_DSYNC  :等待每次write操作的完成 , 但是不等待文件属性的更新 , 除非影响到写操作的完成

    O_RSYNC  :等待读操作的完成

    O_SYNC   :等待每次写操作的完成并且同步更新文件属性

     

    open() 返回的文件描述符值一定是最小未用描述符值。这一特点常被用来重定向标准文件描述符:具体做法是先调用close关闭标准描述符

    (如 STDIN_FILENO),然后调用open函数,就可以在标准输入上打开新文件。

              creat(const char* filename , mode_t mode);  这个函数相当于 open(filename , O_RDWR|O_EXCL|O_CREAT, mode);

    文件名和路径的截短

      当文件名超过 NAME_MAX 或路径长度超过 PATH_MAX的时候,根据系统不同,结果也不相同。

      可以测试 _POSIX_NO_TRUNC 宏

            #ifdef  _POSIX_NO_TRUNC

            if( (fd = open(filename,O_RDWR|O_EXCL|O_CREAT) == -1 && errno == ENAMETOOLONG){

              perror(filename);

            #endif

    close 函数 

       关闭打开的文件

    lseek函数

      设置打开文件的文件偏移量,默认情况下,打开一个文件时,除非O_APPEND标志被设置,否则文件偏移 为0

      该函数不能用于操作 管道、套接字、FIFO  ,  函数的返回值是先前的文件偏移量

      有些设备允许偏移量为 负 ,所以测试函数是否执行成功的时候  应该和 -1 比较 , 如果 ==-1 则失败  否则为成功

      lseek 仅仅调整内核中保存的文件结构的偏移量,不会引起任何I/O操作

      当文件偏移量大于文件长度的时候, lseek会在文件中形成文件空洞, 这些文件空洞不占用磁盘空间, 当 I/O 函数读写文件的时候,

      读到的空洞部分的字节的值为 0

    read函数

      读到的字节数少于要求读取的字节数的原因

        读普通文件  :到达文件尾端

        读终端设备  :一次最多读取一行

        网络       :缓冲机构可能造成返回值小于要读取的字节数

        管道或FIFO  :管道中所包含的字节数少于要读取的字节数,则返回管道中实际的字节数

        由于信号造成中断

    write函数

      返回实际写入的字节数

    I/O效率

      在发生I/O操作的时候,一般缓冲区大小为 4096 的时候,I/O效率最高

      大多数的文件系统为改善I/O效率  , 一般采用某种  预读(read ahead)技术。 当检测到正在进行顺序读取的时候,系统会试图读取比

      要求的更多的数据,并假象应用程序很快会读取这些数据

    文件共享

      不同进程中的文件描述符表中的描述符只想相同的文件节点,就实现了所谓的文件共享

    原子操作

      原子操作要么不执行,要么一次执行完。

      不能被系统中断的操作。 当多进程对同一个文件进行写操作的时候,写操作应该 保证为原子 操作。可以用 pread  和 pwrite这两个原子操作函数

      来替代 read 和 write  , 这俩函数执行的时候无法被中断。而且  pread 不更新文件指针

      

    三种复制现有文件描述符的方法

        1、int  dup(int fd) 函数

        2、int  dup2(int fd, int fd2);

              将 fd 复制为 指定的fd2 的描述符,如果fd2已经打开,则先关闭fd2

        3、int  fcntl(fd, F_DUPFD , fd2 )

    冲洗缓冲区的三个函数

        void  sync(void)  :    将所有修改过的块排入写入队列 , 然后就返回, 不等待写入操作的结束

        int   fsync(int fd) :  仅仅对单一文件的缓冲区冲洗,但是会等待写入操作的完成,并且同步更新文件属性

        int   fdatasync(int fd) :  同 fsync()  , 但是不会更性文件属性,除非影响到写入操作

    /dev/fd/

       当描述符 n 是打开的时候, 此时打开   “/dev/fd/n”  相当于复制  描述符 n 。

       但是打开后的权限不可更改  , 只能 是 描述度 n 的一个子集 。  

  • 相关阅读:
    mysql 慢查询分析工具
    php+redis实现消息队列
    Mysql数据库千万级数据查询优化方案.....
    windows下安装docker详细步骤
    Git基础使用教程
    redis实现消息队列&发布/订阅模式使用
    macos上改变输入法顺序
    ssh动态转发小记
    ubuntu上runsv/runit小记
    使用libcurl下载https地址的文件
  • 原文地址:https://www.cnblogs.com/wowk/p/3107092.html
Copyright © 2011-2022 走看看