zoukankan      html  css  js  c++  java
  • apue- chapter 3 文件IO

    1.函数open和函数openat

    #include<fcnl.h>
    int open(const char *path,int oflag,.../*mode_t mode */)
    int openat(int fd,const char *path,int oflag,.../*mode_t mode*/)
    //两个函数的返回值:若成功,返回文件描述符;若出错,返回-1

    oflag 参数可用来说明此函数的多个选项。用下列一个或者多个常量进行“或运算”构成oflag参数。(常量定义在头文件<fcntl.h>)

    O_RDONLY 只读打开
    O_WRONLY 只写打开
    O_RDWR 读、写打开
    O_EXEC 只执行打开
    O_SEARCH 只搜索打开(应用于目录)
    O_APPEND 每次写的时候都追加到文件的末尾
    A_CLOSEXEC 把FD_CLOSEXEC常量设置为文件描述符标志
    O_CREAT 若该文件不存在,就创建这个文件
    O_DIRECTORY 如果path引用的不是目录,则出错
    O_EXCL 如果同事指定了O_CREAT,而文件已经存在,则出错。用此可以测试一个文件是否存在,如果不存在,就创建这个文件
    O_NOCTTY 如果path引用的是终端设备,则不将该设备分配作为此进程对的控制终端
    O_NOFOLLOW 如果path引用的是一个符号链接,则出错
    O_NONBLOCK 如果path引用的是一个FIFO,一个块特殊文件或者一个字符特殊文件,则此选项为文件的本次打开操作和后续的I/O操作设置非阻塞方式
    O_SYNC 使得每次write等待物理I/O操作完成,包括由该write操作引起的文件属性更新所需的IO
    O_TRUNC 如果此文件存在,而且为只写或者读-写成功打开,则将该长度截断为0
    O_TTY_INIT 如果打开一个还未打开的终端设备,设置非标准termios参数值,使其符合Single UNIX Specification
    O_DSYNC 使得每次write都要等待物理I/O操作完成,但是如果该写操作并不影响读取刚写入的数据,则不需要等待文件属性被更新
    O_REYNC 使得每一个以文件描述符作为参数进行的read操作等待,直至所有对文件同一部分挂起的写操作都完成

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    通过fd参数把open和openat函数区分开,共有下述3种可能:

    1. path参数指定的是绝对路径的名称,在这个情况下,fd参数被忽略,openat函数相当去open函数
    2. path参数指定的是相对路径名,fd参数支出了相对路径名在文件新系统的开始位置。fd参数是通过打开相对路径名所在的目录来获得的。
    3. path参数指定了相对路径名,fd参数具有特殊值AT_FDCWD。在这种情况下,路径名在当前目录中获取,openat函数在操作上与open函数类似

     2.函数create

    #include <fcntl.h>
    int creat(const char * path,mode_t mode);//创建一个文件
    等价于以下调用:
    open(path,O_WRONLY|O_CREATE|O_TRUNC,mode)

    3.函数close

    //可以调用close函数关闭一个打开的文件
    #include <unistd.h>
    int close(int fd);

    4.函数lseek

      可以利用函数lseek为一个打开的文件设置偏移量。

    #include <unistd.h>
    off_t lseek(int fd,off_t offset,int whence)//此函数的返回值是文件的当前偏移量
    /*
    其中,whence取值为SEEK_SET,该文件的偏移量设置为距离文件开头offset个字节
    若whence为SEEK_CUR,则该文件的偏移量设置为当前值加 offset,offset可正可负
    若whence为SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负
    */

      如果文件的描述符指向一个管道,FIFO或网络套接字,则lseek返回-1,并且将errno设置为ESPIPE。程序实例如下:

    #include "apue.h"
    #include <iostream>
    using namespace std;
    int main(){
        if(lseek(STDIN_FILENO,0,SEEK_CUR)==-1)
            cout<<"can't seek"<<endl;
        else
            cout<<"seek OK!"<<endl;
    
        return 0;
    }

    输出:can't seek

      可以通过lseek跳过一段长度的空间,创建一个具有空洞的文件。

    5.函数read

    #include <unistd.h>
    ssize_t read(int fd,void *buf,size_t nbytes);
    //read成功,返回读到的字节数目。如果已经达到文件的末尾,则返回0

      优肯那个实际读到的字节数小于要求读的字节数目nbytes

    6.函数write

      调用函数write函数向打开的文件中写入数据。

    #include <unistd.h>
    ssize_t write(int fd,const void *buf,size_t nbytes)
    //若成功,返回写入的字节数目,若出错,返回-1

     7.原子操作-函数pread和函数pwrite

      函数pread和函数pwrite允许原子性地定位并执行I/O。

    #include<unistd.h>
    ssize_t pread(int fd,void *buf,size_t nbytes,off_t offset);
    //返回值:读到的字节数,若已经到达字节尾,返回0,若出错,返回-1
    ssize_t pwrite(int fd,const void *buf,size_t nbytes,off_t offset);
    //返回值,若成功,返回已经写的字节数目;若出错,返回-1

      调用pread相当于调用lseek后调用read,但是pread又与这种顺序调用有下列重要区别:

      调用pread时,无法中断其定位和读操作;

      不更新当前文件偏移量。

      调用pwrite相当于调用lseek后调用write,但是pwrite又与这种顺序的调用有下列重要区别:

      调用pwrite时,无法中断其定位和写操作;

      不更新当前文件偏移量。

    8.函数dup和dup2

      下面两个函数都可以用来复制一个现有的文件描述符。

    #include<unistd.h>
    int dup(int fd);
    int dup2(int fd,int fd2);

      利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的

      dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。dup2函数是原子操作。

    9.函数sync,fsync,fdatasync

      为了将缓存中的更改写回磁盘,保证缓冲区和文件系统的内容的一致性,需要调用这三个函数。

    #include<unistd.h>
    int fsync (int fd);
    //只对文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束才返回
    int fdatasync(int fd);
    //类似于函数fsync,只对文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束之后才返回。可以用于数据库这样的应用程序。
    void sync(void );
    //将修改过的缓冲区排入写队列,然后返回,不等待实际磁盘操作结束。

    返回值:如果成功就返回0,否则返回-1

    10.函数 fcntl

      fcntl函数可以改变已经打开的文件的属性。

    #include<fcntl.h>
    int fcntl(int fd,int cmd,.../*int arg*/)
    //返回值 :若成功,则依赖于cmd;若出错,返回-1

      fcntl函数有以下5种功能:

    (1)复制一个已有的描述符(cmd=F_DUPFD或F_DUPED_CLOSEXEC)

    (2)获取/设置文件描述符标识(cmd=F_GETFD或者F_SETFD)

    (3)获取/设置文件状态标识(cmd=F_GETFL或者F_SETFL)

    (4)获取/设置文件状态标识(cmd=F_GETOWN或者F_SETOWN)

    (5)获取/设置记录锁(cmd=F_GETLK,F_SETLK或者F_SETLKW)

      

  • 相关阅读:
    栈的使用
    学习
    JS中常用的工具类
    AOP的相关概念
    Git-用git同步代码
    权限管理3-整合Spring Security
    权限管理2-开发权限管理接口
    权限管理1-需求描述
    使用Canal作为mysql的数据同步工具
    使用存储过程在mysql中批量插入数据
  • 原文地址:https://www.cnblogs.com/zhoudayang/p/5303880.html
Copyright © 2011-2022 走看看