1.文件描述符:是一个非负整数,用来描述打开的文件
2.函数open和函数openat:
1 #include <fcntl.h> 2 int open(const char * path, int oflag,...); 3 int openat(int fd, const char * path, int oflag,...);
打开或者创建一个文件描述符,失败的话返回-1
path是要打开或创建的文件名
oflag参数可用来说明此函数的多个选项
fd参数指出了相对路径名在文件系统的开始地址
这两个函数返回的都是未用的最小的文件描述符
3.函数create
1 #include <fcntl.h> 2 int create(const char * path, mode_t mode);
创建一个新的文件,返回文件描述符,错误的话返回-1
等效于:
1 open(path,O_WRONLY|O_CREAT|O_TRUNC, mode);
4.函数close
1 #inlude <unistd.h> 2 int close (int fd);
成功的话返回0,失败的话返回-1
关闭一个打开的文件,还会释放该进程加在该文件上的所有记录锁
大多数时候进程终止时,内核会自动管理她所有的打开文件
5.函数lseek
1 #include <unsitd.h> 2 off_t lseek(int fd, off_t offset, int whence);
这个函数可以显式地为一个打开文件设置偏移量
成功的话返回新的文件偏移量,失败的话,返回-1
whence是解释偏移量的
SEEK_SET 设置为距离文件开始处offset个字节
SEEK_CUR 设置为当前的的值加offset
SEEK_END 设置为文件长度加offset
6.函数read
1 #include <unistd.h> 2 ssize_t read(int fd, void * buf, size_t nbytes);
从打开的文件中读数据
成功返回读到的字节数,到达尾部的话,返回0,出错的话返回-1
7.函数write
1 #include <unistd.h> 2 ssize_t write(int fd, const void *buf, size_t nbytes);
向打开的文件写数据
成功的话,返回已写的字节,失败的话,返回-1
8.文件共享
内核使用三种数据结构表示打开的文件
1) 每个进程在进程表里面有一个记录项,包含一张打开文件描述符表,每个描述符占一项,包含两个部分,文件描述符标志,指向文件表项的指针
2) 内核为所有的打开文件维持一张文件表,每个文件表包含三部分,文件状态标志,当前文件偏移量,指向该文件v节点表项的指针
3) 每个打开的文件都有一个v-node结构,包含文件类型和对文件进行各种操作函数的指针
9.原子操作
1) 追加到一个文件
在打开文件时设置O_APPEND标志,这样使内核在每次写操作之前,都将进程的当前偏移量设置到该文件的末尾处,于是每次写之前就不再需要调用lseek
2) 函数pread和pwrite
1 #include <unistd.h> 2 ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
返回读到的字节数,到达文件尾部的话返回0,出错的话,返回-1.
1 ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
成功返回写的字节数,失败,返回-1.
pread相当于调用lseek后调用read
pwrite相当于调用lseek后调用write
区别在于连贯的函数无法中断操作
3) 创建一个文件
atomic operation是指多步组成的一个操作,如果该操作原子地执行,要么执行完所有的步骤,要么一步也不执行,不可能执行一个子集。
10.函数dup和dup2
1 #include <unistd.h> 2 int dup(int fd); 3 int dup2(int fd, int fd2);
函数用来复制一个现有的文件描述符
成功的话返回新的文件描述符,失败的话返回-1
dup返回的文件描述符是当前可用的最小的
dup2可以指定fd2为新的描述符,要是fd2已经打开,则先关闭,要是fd=fd2就直接返回,不关闭。
11.函数sync,fsync和fdatasync
当我们向文件写入数据时,内核通常先将数据复制到缓冲区,然后排入队列,晚些时候写入磁盘。当内核需要重用缓冲区存放其他磁盘块数据时,会把所有延迟写数据块写入磁盘。为保证磁盘上实际文件系统和缓冲区中的内容一致,使用下面的三个函数。
1 #include <unistd.h> 2 int fsync(int fd); 3 int fdatasync(int fd); 4 //成功返回0失败返回-1 5 void sync(void);
sync只是将所有修改过的块缓冲区排入写队列,然后返回,不等待实际写磁盘的操作结束。
守护进程updata周期性调用sync函数,保证定期冲洗内核的块缓冲区。
fsync针对指定的文件描述符,并且等待磁盘操作结束
fdatasync可用于数据库这样的程序,确保修改过的块立即写到磁盘上。
12.函数fcntl
1 #include <fcntl.h> 2 int fcntl(int fd, int cmd,...);
改变已经打开的文件的属性
13.函数ioctl
1 #include <unistd.h> 2 #include <sys/ioctl.h> 3 int ioctl(int fd, int request,...);
出错返回-1成功返回其他值
不能用其他函数表示的I/O通常可以用这个函数实现。
14./dev/fd
打开文件/dev/fd/n等效于复制描述符n(假定描述符n是打开的)
1 fd=open(“/dev/fd/0”,mode); 2 fd=dup(0);//描述符0和fd共享同一文件表项 3 fd=open(“/dev/fd/0”,O_RDWR);//要是0被打开为只读,即使这个调用成功,也不能对fd进行写操作。