第三章文件I/O学习笔记

 

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) 函数preadpwrite

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.函数dupdup2

 

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,fsyncfdatasync

 

当我们向文件写入数据时,内核通常先将数据复制到缓冲区,然后排入队列,晚些时候写入磁盘。当内核需要重用缓冲区存放其他磁盘块数据时,会把所有延迟写数据块写入磁盘。为保证磁盘上实际文件系统和缓冲区中的内容一致,使用下面的三个函数。

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进行写操作。
原文地址:https://www.cnblogs.com/kongchung/p/4599208.html