• 常见的C语言库函数介绍(主要针对IO相关操作)
  • 部分函数仅为linux系统特有
  • 后续会对相关系统调用中涉及到的IO进行讲解

常见的C语言库函数

#include <stdio.h>

int open(const char *path,int access[,unsigned mode])

  • 功能: 文件句柄 = open("文件名",打开模式|打开模式);
  • 参数:打开模式:
    • access模式:(最多使用以下模式中的一个,且必须有一个)
      • O_RDONLY 以只读方式打开
      • O_WRONLY 以只写方式打开
      • O_RDOWR  以读写方式打开
    • 其他模式:(可选模式,可以同时存在,用或连接)
      • O_APPEND:以后每次写文件时都会先将当前文件偏移量设置到文件末尾,但是读文件时时不影响的
      • O_CREAT:如果文件不存在则创建
      • O_EXCL:要打开的文件如果存在则出错,必须要和O_CREAT参数一起使用
      • O_TRUNC:打开文件的同时将文件中的内容清除
      • O_NOCTTY:如果打开的文件是终端设备,则不将此设备设置为进程的控制终端
      • O_NONBLOCK:如果打开的文件是一个管道、一个块设备文件或一个字符设备文件,则后续的I/O操作均设置为非阻塞方式
      • O_SYNC:使每次write都等到物理I/O操作完成
      • S_IRUSR: Permits the file's owner to read it.
      • S_IWUSR: Permits the file's owner to write to it.
  • 返回值:打开成功,返回文件句柄;失败返回 -1

int close(int handle)

  • 功能:关闭由文件句柄所指向的文件 关闭结果 = close(文件句柄)
  • 返回值:0(成功),-1(失败)

FILE* fopen(const char *path, const char *mode)

  • 功能:打开一个特定的文件,并把一个流和这个文件相关联
  • 参数:
    • path:文件路径对应的字符串
    • mode:打开模式,流形态
      • r:打开只读文件,该文件必须存在
      • w:打开只写文件,已存在的文件将被清空
      • r+:以读写的方式打开文件,该文件必须存在
      • w+:打开可读写文件,已存在文件将被清空
      • rb:打开一个只读二进制文件,文件必须存在
      • wb:新建一个只写的二进制文件,已存在的将被清空
      • rb+:打开一个可读写的二进制文件,该文件必须存在
      • wb+:新建一个可读可写的二进制文件,已存在的将被清空
      • a:打开或者新建一个文本文件,只允许文件末尾追加写
      • a:打开或新建一个文本文件,可以读,但只允许在文件末尾追写
      • ab:打开或新建一个二进制文件,只允许在文件末尾追写
      • ab+:打开或新建一个二进制文件,可以读,但只允许在文件末尾追写
  • 返回值:
    • 成功:返回一个指向 FILE 结构的指针,该结构代表这个新创建的流。
    • 失败:返回一个空指针,errno会存储相关错误代码。

int fclose(FILE *stream);

  • 功能:关闭文件流
  • 返回值:关闭成功,返回 0, 否则返回 EOF -1。输出流在关闭前会刷新对应的缓冲区。

int fseek(FILE *stream, long offset, int fromwhere);

  • 功能:从指定位置将文件指针移动指定偏移量长度
  • 参数:
    • stream:文件流指针
    • offset:要移动的偏移量长度
    • fromwhere:文件指针移动的起始位置
      • #define SEEK_CUR 1:当前位置
      • #define SEEK_END 2:文件尾
      • #define SEEK_SET 0:文件头
  • 返回值:成功,返回0,失败返回非0值,并设置error的值,可以用perror()函数输出错误。

long ftell(FILE *stream);

  • 功能:用于得到文件位置指针当前位置相对于文件首的偏移字节数。
  • 用法:使用fseek函数后再调用函数ftell()就能非常容易地确定文件的当前位置。利用函数 ftell() 也能方便地知道一个文件的长。如以下语句序列: fseek(fp, 0L,SEEK_END); len =ftell(fp); 首先将文件的当前位置移到文件的末尾,然后调用函数ftell()获得当前位置相对于文件首的位移,该位移值等于文件所含字节数。

size_t fread ( void *buffer, size_t size, size_t count, FILE *stream);

  • 功能:从给定的流 stream 读取数据,最多读取count个项,每个项size个字节。
  • 参数:
    • buffer:用于接受数据的内存地址
    • size:要读的每个数据项的字节数
    • count:要读取的数据项数目
    • stream:操作的输入流
  • 返回值:调用成功返回实际读取到的项个数(小于或等于count),如果不成功或读到文件末尾返回 0。

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

  • 功能:向指定的文件中写入若干数据块,如成功执行则返回实际写入的数据块数目。该函数以二进制形式对文件进行操作,不局限于文本文件。
  • 参数:
    • ptr:存放需要写入的数据的内存地址
    • size:要写入内容的单字节数
    • count::要进行写入size字节的数据项的个数
    • stream:目标文件指针
  • 返回值:如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误

#include <sys/uio.h>

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

  • 功能:在指定偏移量的位置开始读取指定长度的个字节
  • 参数:
    • fd:文件描述符
    • *buf:数据缓冲区指针,存放读取出来的数据
    • count:读取数据的字节数
    • offset:读的起始地址的偏移量, 读取地址=文件开始+偏移量。执行后文件偏移指针不变。
  • 返回值:读取到缓冲区的字节数

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

  • 功能:在指定偏移量的位置上,写入对应的数据
  • 参数:
    • fd:要写入数据的文件描述符
    • *buf:数据缓存区指针,存放要写入的数据
    • count:写入文件中的数据字节数
    • offset:偏移地址。写入地址=文件开始+offset。注意,执行后,文件偏移指针不变
  • 返回值:写入到文件中的字节数

ssize_t readv(int fd, const struct iovec *iov, int iovcnt);

  • 功能:数据散布读到缓冲区中(散点输入)
  • 参数:
    • fd:文件描述符
    • *iov:指向 iovec结构数组的一个指针。buffer
      • iov_base:存放数据的缓冲区
      • iov_len:缓冲区的数据长度
    • iovcnt:数组元素的个数。缓冲区的个数
  • 返回值:读取的字节数

ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

  • 功能:将散步在缓冲区的数据(可能不连续)一起写入到文件描述符对应的文件中去。
  • 参数:
    • fd:文件描述符
    • *iov:指向iovec结构数组的一个指针。(要写入的数据)
    • iovcntiovec数组的长度,缓冲区的个数
  • 返回值:写入的字节数

ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);

  • 功能:在指定偏移量的位置上,将数据散布读到缓冲区中(散点输入)
  • 参数:
    • fd:文件描述符
    • *iov:指向 iovec结构数组的一个指针。buffer
      • iov_base:存放数据的缓冲区
      • iov_len:缓冲区的数据长度
    • iovcnt:数组元素的个数。缓冲区的个数
    • offset:偏移量
  • 返回值:读取的字节数

ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);

  • 功能:在指定偏移量的位置上,将散步在缓冲区的数据(可能不连续)一起写入到文件描述符对应的文件中去。
  • 参数:
    • fd:文件描述符
    • *iov:指向 iovec结构数组的一个指针。buffer
      • iov_base:存放数据的缓冲区
      • iov_len:缓冲区的数据长度
    • iovcnt:数组元素的个数。缓冲区的个数
    • offset:偏移量
  • 返回值:写入的字节数。

#include<unistd.h>

int fsync(int fd)

  • 功能:确保文件 fd 所有已修改的内容已经正确同步到硬盘上,该调用会阻塞等待直到设备报告IO完成。(由于 write() 函数本质更新的是内存中的页缓存,而已经更新但还没刷入磁盘的页面,也叫脏页面,不会立即更新到硬盘中,而是由操作系统统一调度,如由专门的flusher内核线程在满足一定条件时,如一定时间间隔、内存中的脏页达到一定比例等条件,才将脏页面同步到硬盘上,通过将页面放入磁盘设备的IO请求队列来进行同步。所以 write 函数不会等到硬盘IO完成之后才返回,提供了一种‘松散的异步语义’,但是无法保证事务的持久化和一致性,此时则需要操作系统提供的同步IO原语来进行保证)
  • 参数:文件描述符
  • 返回值:成功 返回 0;失败 返回 -1

int fdatasync(int fd);

  • 功能:fdatasync的功能与fsync类似,但是仅仅在必要的情况下才会同步metadata(元数据主要包括文件大小、最后访问时间和修改时间等),因此可以减少一次IO写操作。其中必要的情况主要包括文件的尺寸(st_size)发生变化以及部分应用程序对于文件最后访问时间和修改时间的有严苛要求等。

#incude <sys/mman.h>

int msync(void *addr, size_t length, int flags)

  • 功能:针对采用内存映射文件方式进行文件IO的操作,譬如mmap将文件的页缓存直接映射到进程的地址空间,通过写内存的方式来修改对应的文件,也提供了相应的同步系统调用来确保数据的持久化和一致性,往往在调用munmap()后才执行该操作。
  • 参数:
    • addr:文件映射到进程空间的地址;
    • lenth:映射空间的大小;
    • flags:刷新的参数设置
      • MS_ASYNC:异步,调用后立即返回,不等待更新完成
      • MS_SYNC:同步,调用后会等到更新完成返回
      • MS_INVALIDATE:通知使用该共享区域的进程,数据已经改变时,在共享内容更改之后,使得文件的其他映射失效,从而使得共享该文件的其他进程去重新获取最新值;
  • 返回值:成功 返回 0;失败 返回 -1

参考链接: