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是对文件进行查找和截断等操作,这里不做详细介绍,可以在具体使用到时,在详细研究。