zoukankan      html  css  js  c++  java
  • Unix3-文件I/O接口

    Unix编程第3章:

    不带缓冲的I/O:区别于标准I/O,文件I/O的write和read都调用内核中的一个系统调用。不带缓冲是指不需要在用户空间开辟空间用于与内核之间的复制操作。

    文件描述符:当读写一个文件时,使用open或create返回的文件描述符标识该文件,将其作为参数传送给read或write。

    符合POSIX.1,幻数0、1、2被标准化,通常替换为符号常量STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。定义在<unistd.h>中。

    文件描述符的变化范围是0~OPEN_MAX-1。

    该部分接口失败都返回-1。

    open和openat:

    #include<fcntl.h>

    int open(const char*path, int oflags, .../* mode_t mode */);

    int openat(int fd, const char*path, int oflags, .../* mode_t mode */);

    成功返回文件描述符。

    path是要打开或创建的文件的名字,oflags是用来说明此函数的多个选项: 

      O_RDONLY  只读打开;

      O_WRONLY  只写打开;

      O_RDWR  读、写打开;

      O_EXEC  只执行打开;

      O_SEARCH  只搜索打开(应用于目录);

    以上5个必选且只能选一个。

      O_APPEND  每次写时都追加到文件的尾端;

      O_CLOEXEC  把FD_CLOEXEC常量设置为文件描述符标志;

      O_CREAT  若此文件不存在则创建它。使用此选项时,须指定mode为文件的访问权限位;

      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操作引起的文件属性更新所需的I/O;

      O_TRUNC  如果此文件存在,而且为只写或读-写成功打开,则将其长度截断为0;

      O_TTY_INIT  如果打开一个还未打开的终端设备,设置非标准termios参数值,使其符合single Unix specification.

      O_DSYNC  使每次write要等待物理I/O操作完成,但是如果该写操作并不影响读取刚写入的数据,则不需要等待文件属性更新;

      O_RSYNC  使每一个以文件描述符作为参数进行的read操作等待,直至所有对文件同一部分挂起的写操作都完成。

    由open和openat函数返回的文件描述符一定是最小的未用描述符数值。

    openat的fd参数用于指定一个目录,然后path取相对该目录的文件;如果openat的path是绝对路径则fd忽略。

    create函数:

    #include<fcntl.h>

    int create(const char*path, mode_t mode);

    成功时返回为只写打开的文件描述符。

    等效于open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

    create只能以只写方式打开所创建的文件,如需要读取文件,则要先关闭。

    函数close:

    #include<unistd.h>

    int close(int fd);

    成功返回0;

    关闭一个文件时还会释放进程加在该文件上的所有记录锁。当一个进程终止时,内核自动关闭她所有的打开文件。

    函数lseek:

    #include<unistd.h>

    off_t lseek(int fd, off_t offset, int whence);

    成功时返回新的文件偏移量。

    每个打开的文件都有一个与其关联的“当前文件偏移量”,通常非负。按系统默认的情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0.

    lseek显式设置一个打开文件的偏移量。

    参数offset的解释与whence有关:

    -若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节。

    -若whence是SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,offset可正或负。

    -若whence是SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负。

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

    因为某些设备允许偏移量是负值,所以在比较lseek的返回值时,不要测试它是否小于0,而是测试是否等于-1.

    文件偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将加长该文件并在文件中构成一个空洞。位于文件中但没有写过的字节都被读为0.

    文件中的空洞不要求在磁盘上占用存储区。

    函数read:

    #include<unistd.h>

    ssize_t read(int fd, void*buf, size_t nbytes);

    成功时返回读到的字节数,如已到达文件的尾端则返回0。

    有多种情况可使实际读到的字节数少于要求读到的字节数:

    -读普通文件时,在读到要求字节数之前就已到达文件尾端。

    -当从终端设备读时,通常一次最多读一行。(可改变)

    -当从网络读时,网络中的缓冲机制可能造成返回值小于所要求读的字节数。

    -当从管道或FIFO读时,如若管道包含的字节数少于所需的数量,那么read将只返回实际可用的字节数。

    -当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录。

    -当一个信号造成中断,而已经读了部分数据量时。

    函数write:

    #include<unistd.h>

    ssize_t write(int fd, const void*buf, size_t nbytes);

    成功时返回以写的字节数。

    其返回值通常与参数nbytes的值相同,否则表示出错。write出错的一个常见原因是磁盘以写满,或者超过了一个给定进程的文件长度限制。

    ps:大多数文件系统为改善性能都采用某种预读技术(read ahead)。当检测到正在进行顺序读取时,系统就试图读入比应用所要求的更多数据,并假想应用很快就会读这些数据。

    原子操作:不中断的操作

    lseek和read、write之间不是整体的原子操作,提供了pread和pwrite保证lseek与read、write的原子性。

    #include<unistd.h>

    ssize_t pread(int fd, void*buf, size_t nbytes, off_t offset);

    成功时返回读到的字节数,若已经到达文件结尾则返回0.

    ssize_t pwrite(int fd, const void*buf, size_t nbytes, off_t offset);

    成功时返回以写的字节数。

    pread相当于先调用lseek再调用read;pwrite相当于先调用lseek再调用write。

    函数dup和dup2:

    #include<unistd.h>

    int dup(int fd);

    int dup2(int fd, int fd2);

    成功时返回新的文件描述符。

    dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。

    对于dup2,可用fd2参数指定新描述符的值。如果fd2已经打开,则先将其关闭。如若fd等于fd2,则dup2返回fd2,而不关闭它。否则,fd2的FD_CLOEXEC文件描述符标志就被清除,这样fd2在进程调用exec时是打开状态。

    返回的新文件描述符与fd共享同一个文件表项。

    每个文件描述符都有它自己的一套文件描述符标志,新描述符的执行时关闭(close-on-exec)标志总是由dup函数清除。

    复制一个描述符的另一种方式是fcntl函数。

    dup(fd);相当于fcntl(fd,F_DUPFD,0);

    dup2(fd,fd2);相当于close(fd2);dup2(fd,F_DUPFD,fd2);

    但dup2是一个原子操作,close加上fcntl包含两个系统调用不是原子操作。

    dup2和fcntl有一些不同的errno。

    函数sync、fsync和fdatasync:

    延迟写:传统的UNIX系统实现在内核中设有缓冲区高速缓存和页高速缓存,大多数磁盘I/O都通过缓冲区进行。当我们向文件写入数据时,内核通常首先将数据复制到缓冲区中,然后排入队列,晚些写入磁盘。

    内核需要重用缓冲区来存放其它磁盘块数据时,它会把所有延迟写数据块写入磁盘。为了保证磁盘上实际文件与缓冲区中内容一致,UNIX提供了sync、fsync和fdatasync三个函数:

    #include<unistd.h>

    int fsync(int fd);

    int fdatasync(int fd);

    成功返回0.

    void sync(void);

    sync只是将所有修改过的块缓冲区排入写队列,然后就返回,他并不等待实际写磁盘操作结束。

    update守护进程周期性地调用sync函数,保证了定期冲洗内核的快缓冲区。

    fsync函数只对由文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束才返回。fsync可用于数据库这样的应用程序,确保修改过的块立即写到磁盘上。

    fdatasync函数类似于fsync,但它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的属性。

    函数fcntl:

    改变已打开文件的属性。

    #include<fcntl.h>

    int fcntl(int fd, int cmd,... /* int arg */);

    成功时,返回值依赖于cmd;

    fcntl函数有以下5种功能:

    -复制一个已有的文件描述符(cmd=F_DUPFD或F_DUPFD_CLOEXEC)

    -获取/设置文件描述符标志(cmd=F_GETFD或F_SETFD);

    -获取/设置文件状态标志(cmd=F_GETFL或F_SETFL)

    -获取/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN);

    -获取/设置记录锁(cmd=F_GETLK、F_SETLK或F_SETLKW)。

    F_DUPFD:复制文件描述符fd,新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第三个参数值(取为整数值)种各值的最小值。新描述符与fd共享同一文件表项。但是,新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除(这表示该描述符在exec时仍保持有效)。

    F_DUPFD_CLOEXEC:复制文件描述符,设置与新描述符关联的FD_CLOEXEC文件描述符标志的值,返回新的文件描述符。

    F_GETFD:对应于fd的文件描述符标志作为函数值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。

    F_SETFD:对于fd设置文件描述符标志。新标志值按第三个参数(取为整型值)设置。

    F_GETFL:对应于fd的文件状态标志作为函数值返回。(与open函数中使用的文件状态标志相同)访问方式位是五个互斥值中的一个(只读、只写、读写、可执行、搜索),首先用O_ACCMODE获得访问方式位再与这五个值分别作比较。

    F_SETFL:将文件状态标志设置为第3个参数的值(取为整型值)。可以设置的标志是:O_APPEND、O_NONBLOCK、O_SYNC、O_DSYNC、O_FSYNC、O_ASYNC。

    F_GETOWN:获取当前接收SIGIO和SIGURG信号的进程ID或进程组ID。

    F_SETOWN:设置接收SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进程ID,负的arg等于arg绝对值的一个进程组ID。

    函数ioctl:

    主要是设备驱动程序使用。

    /dev/fd:

    较新的系统都提供名为/dev/fd的目录,其目录项是名为0、1、2等的文件。打开文件/dev/fd/n等效于复制描述符n(假设描述符n是打开的)。

  • 相关阅读:
    Oracle数据库event事件与dump文件介绍
    (原)dbms_rowid.rowid_create来创建一个rowid
    Oracle读取事件的命名理由(哈哈)
    关于删除temporary tablespace的一点小建议
    oracle的rowid到底是什么
    电脑高手最常用的五个组合键
    win2008里如何取消IE游览器弹出增强的安全配置?
    经典SQL语句大全
    Win7中安装Rational Rose,启动提示计算机丢失suite objects.dll
    Asp.net页面跳转
  • 原文地址:https://www.cnblogs.com/cjj-ggboy/p/12261439.html
Copyright © 2011-2022 走看看