首页 > 代码库 > linux下C++开发系列(六)——文件IO相关的系统调用

linux下C++开发系列(六)——文件IO相关的系统调用

  linux操作系统中,文件是最基本和最重要的抽象,linux遵循一切皆文件的理念。按照不同的属性,文件可以分为普通文件和特殊文件。特殊文件是以文件方式表示的内核对象,linux支持四种类型的特殊文件:

  1、块设备文件 (例如硬盘设备)

  2、字符设备文件(例如键盘设备)

  3、命名管道 (主要是进程间通信使用)

  4、Unix域套接字(主要是网络通信使用)

  linux系统对于文件的操作,提供了一系列的系统调用个,主要分为以下几类:

  1、创建文件(creat) 2、打开文件(open) 3、读文件(read) 4、写文件(write) 5、同步IO(fsync) 

  6、直接IO 7、关闭文件(close) 8、查找文件(lseek) 9、定位文件(pread/pwrite) 10、截短文件(truncate)

  下面具体介绍几个常用调用用法:

  1、creat 创建文件,系统调用的原型为:

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> int creat(const char *pathname, mode_t mode);

  creat使用比较少,因为所有的创建文件的功能,都可以通过open系统调用来实现,creat本身也可以通过open来实现,为何还存在这样一个系统调用,这是一个历史遗留问题,因为Unix一开始设计时,open系统调用只有两个参数,不足以完成创建文件的功能,所以就有了creat系统调用,但是后来open系统调用扩展了三个参数,就把creat的功能实现了,但是creat系统调用还是遗留了下来,creat并不是一个单词,少了字母e,这是Unix开发者写代码的时候,漏掉了一个字母导致了,看大神也有不小心的时候,大家写代码的时候,要认真。

  2、open 打开和创建文件,系统调用的原型为

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open (const char *name, int flags);int open (const char *name, int flags, mode_t mode);

  name 代表传入的文件名。

  flags的枚举:O_RDONLY(只读) O_WRONLY(只写) O_RDWR(读写)

     flags可以和下面任何一个和多个枚举进行或运算 :
     O_APPEND 追加模式,每次文件在写操作之前,文件位置指针将被置于文件末尾。
     O_ASYNC   当指定文件可读或者可写时产生一个信号(默认是SIGIO)。这个标志仅用于终端和套接字,不能用于普通文件。
     O_CREAT    当name指定的文件不存在的时,将由内核来创建。如果文件已经存在,则本标志无效,除非给出了O_EXCL标志
     O_DIRECT   打开文件用户直接IO
     O_DIRECTORY 如果name不是一个目录,open()调用会失败。这个标志用于在opendir()内部使用
     O_EXCL     和O_CREAT一起给出的时候,如果由那么给定的文件已经存在,则open()调用失败。用来防止文件重复创建。
     O_LARGEFILE  给定文件打开时,将使用64位偏移量,这样>2G的文件也能被打开,在64位架构中隐含是使用该参数来打开文件的
     O_NOCTTY 如果给出的name指向一个终端设备(也就是说 ./dev/tty),它将不会成为这个进程的控制终端,即使该进程目前没有控制终端。这个标志不太常用
     O_NOFOLLOW  如果name是一个符号链接,open()调用会失败。通常,会解析该链接并且打开目标文件。如果给出路径的其他的部分是链接,该调用仍然可用。举例来说,如果name是/etc/ship/plank.txt,如果plank.txt是一个符号链接则该调用失败。如果etc或者ship是符号链接,只要plank.txt不是,则调用成功。
     O_NONBLOCK 如果可以,文件将在非阻塞模式下打开。open()调用不会,任何其他操作都不会使该进程中阻塞(sleep)。这种情况可能只用于FIFO
     O_SYNC 打开文件用于同步IO。在数据写到磁盘之前写操作不会完成;一般的读操作时同步的,所以这个标志对读操作没有影响。POSIX额外定义了O_DSYNC和O_RSYNC,在Linux上,这些标志和O_SYNC同义。
     O_TRUNC 如果文件存在,且为普通文件,并允许写,将文件的长度截断为0,对于FIFO或者中断设备,该参数被忽略。在其他文件类型上则没有定义。因为截断文件需要写权限,所以O_TRUNC和O_RDONLY同时使用,也是没有定义的。
 
  mode的枚举:
     S_IRWXU   所有者拥有读写和执行权限
     S_IRUSR    所有者拥有读权限
     S_IWUSR   所有者拥有写权限
     S_IXUSR    所有者拥有执行权限
     S_IRWXG   组拥有读写和执行权限
     S_IRGRP    组拥有读权限
     S_IWGRP   组拥有写权限
     S_IXGRP    组拥有执行权限
     S_IRWXO  任何用户都有读写和执行权限
     S_IROTH  任何用户有读权限
     S_IWOTH  任何用户有写权限
     S_IXOTH   任何用户有执行权限
  
  如果打开或者创建成功,会返回一个fd,文件描述符,在操作系统中是唯一的一个文件描述符。
  如果打开失败,会对errno进行赋值
  3、read函数原型为
  
#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);

  fd 代表open成功返回的文件描述符,也是要读取数据的文件

  buf存储从文件中读取的数据

  count 代表从文件中读书的数量

  返回值:如果读取成功,返回读取到的数据量,如果失败,返回-1,并且设置errno

  4、write原型

#include <unistd.h>ssize_t write (int fd, const void *buf, size_t count);

  fd代表open成功返回的文件描述符,也是要写入数据的文件

  buf 存储要写入的数据

  count 代表写入的数量

  返回值:如果写入成功,返回写入的数据量,如果师表,返回-1,并设置errno

  5、同步IO(fsync)

  fsync是最简单的确认数据写入磁盘的方法,函数的原型为:

#include <unistd.h>int fsync (int fd);

  6、直接IO

  在open时,传入O_DIRECT,即为直接IO,此时I/O 操作将忽略页缓存机制,直接对用户设备进行初始化,并且是同步操作,操作完成之前不会返回。
  7、关闭文件,使用close系统调用即可
  8、9、10是对文件进行查找和截断等操作,这里不做详细介绍,可以在具体使用到时,在详细研究。

linux下C++开发系列(六)——文件IO相关的系统调用