Unix中的文件IO函数主要包括如下几个:open()、read()、write()、lseek()、close()等。这类I/O函数也被称为不带缓冲的I/O,标准I/O是带缓冲的I/O(固然,标准I/O也能够设置为不带缓冲)。函数
对于内核而言,全部打开的文件都经过文件描述符引用,好比read、write等操做都是经过文件描述符来实现的。文件描述符其实就是一个非负整数。当打开或者建立一个文件时,内核会向进程传递一个非负整数做为文件描述符,该文件描述符就能够做为参数传递给read、write等函数,进行文件操做。学习
UNIX系统中,一般是把0做为标准输入的描述符、1做为标准输出的描述符、2做为标准错误的描述符。code
// <unistd.h> #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2
#include <fcntl.h> int open(const char *path, int oflag, ...); int openat(int fd, const cahr *path, int oflag, ...);
使用open() 或者 openat() 函数打开或者建立文件。在函数open()中,path参数是文件的绝对路径或相对于当前文件的相对路径,oflag表示打开的方式。而在函数openat()中,path表示绝对路径(此时fd被忽略)或者是相对于fd的相对路径(fd 表示某已打开目录的文件描述符),openat()函数能够实现以相对路径来打开某些不便直接用相对路径表示的文件。进程
open和openat函数返回的文件描述符必定是最小的未使用描述符,好比一个应用程序能够先关闭标准输出(文件描述符是1),而后打开另外一文件,这样该文件会返回1做为其文件描述符。it
int fd1 = open("test/test.c", O_RDONLY); //只读方式打开文件test.c,此处为相对路径。 int fd2 = open("test", O_RDONLY | O_DIRECTORY); //打开当前目录下的文件夹test int fd3 = openat(fd2, "test.c", O_RDONLY); //打开相对于test文件夹下的test.c
文件打开标志有五个必选标志(必须指定一个且只能指定一个),与其余可选标志。io
// 如下五个必须选一个且只能选一个 O_RDONLY // 只读打开 O_WRONLY // 只写打开 O_RDWR // 读写打开 O_EXEC // 只执行打开 O_SEARCH // 只搜索打开(应用于目录) // 如下为可选标志, O_APPEND // 每次写都追加到文件的结尾,文件以该标志打开时,若是使用lseek对文件重定位,如果读操做,重定位能够生效,如果写操做,重定位不生效,依然写在文件结尾。 O_CREAT // 如果文件爱你不存在则建立它,使用该标志时须要同时说明open第三个参数mode,即建立文件的权限。 O_TRUNC // 若是此文件存在且以只读或读写打开,则将文件长度截为0. O_DIRECTORY // 打开目录,若path不是目录则出错。
该函数只能以只写方式打开,咱们能够直接使用open来实现建立新的文件,因此该函数就不用了。test
#include <fcntl.h> int close(int fd);
关闭一个文件时,还会释放加在该文件上的全部记录锁。搜索
当一个进程结束时,内核会自动关闭它全部的打开文件,不少程序都用了这一点而不显示的调用close关闭打开文件。权限
每一个打开的文件都有一个与其相关的文件偏移量,表示从文件开始处到当前的字节数,一般是一个非负值。学习笔记
#include <unistd.h> off_t lseek(int fd, off_t offset, int whence); // whence 可能取值以下 // SEEK_SET, 将文件的偏移量设置为距文件开始处offset个字节 // SEEK_CUR, 将文件的偏移量设置为距当前位置offset个字节(offset可正可负) // SEEK_END, 将文件的偏移量设置为距结尾处offset个字节(offset可正可负)
一般,读写操做都是从当前文件偏移量处开始,并使偏移量增长所读写的字节数。根据系统默认状况,除非设置了O_APPEND,不然打开文件时,其偏移量被设置为0。
lseek若成功,则返回新的文件偏移量。文件的偏移量能够大于文件的长度,在这种状况下,对文件的下一次写操做将会增加改文件,并在文件中构成一个空洞。
文件空洞并不在磁盘占用存储区,读出的数据为0.