Linux文件类型
普通文件(-)
目录(d)
字符设备(c)
块设备(b)
套接字(s)
管道(p)
符号链接(l)
在Linux中,几乎所有概念都可以抽象成一个文件
一共七种文件类型,均可以使用通用I/O进行操作。
文件描述符
用于指代一个打开的文件,是一个正整数。
标准文件描述符
文件描述符 | 用途 | POSIX名称 |
---|---|---|
0 | 标准输入 | STDIN_FILENO |
1 | 标准输出 | STDOUT_FILENO |
2 | 标准错误 | STDERR_FILENO |
标准I/O操作
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
int open(const char *pathname, int flags, .../*mode_t mode*/); //打开文件
int creat(const char *pathname, mode_t mode); //创建文件
ssize_t read(int fd, void *buffer, size_t count); //读文件
ssize_t write(int fd, void *buffer, size_t count); //写文件
int close(int fd); //关闭文件
off_t lseek(int fd, int offset, int whence); //修改偏移量
int ioctl(int fd, int request, .../*argp*/); //I/0控制
open():打开文件
int open(const char *pathname, int flags);
- int 返回值:成功返回文件描述符,失败返回-1并设置errno
- const char *pathname:文件名
- 如果文件名所指代的文件是一个符号链接,则对符号链接进行解引用
- int flags:选项
- O_RDONLY:以只读的方式打开文件
- O_WRONLY:以只写的方式打开文件
- O_RDWR:以读写的方式打开文件
注:以上3个选项为必选选项,3选1 - O_APPEND:在文件尾部追加数据
- O_ASYNC:当文件描述符可以进行I/O操作时,系统返回一个信号通知进程。这种操作被称为信号驱动I/O,仅对特定类型文件有效(终端设备、管道,套接字)。该标志对Linux无效(大多数UNIX中有与之等效的FASYNC标志),在Linux中必须通过fcntl()的F_SETFL来设置O_ASYNC标志
- O_CLOEXEC:启用close-on-flag标志,fork()后调用execve()时,会关闭用close-on-flag标志修饰的文件描述符。这样做可以防止文件描述符泄露给其他程序。(Linux 2.6.23开始支持)
- O_CREAT:如果文件不存在,则创建文件,使用该选项需要提供mode参数
- O_DIRECT:无缓冲I/O:需要定义功能测试宏_GNU_SOURCE才能使用
- O_DIRECTORY:如果pathname参数不是目录,返回错误,errno为ENOTDIR,需要定义功能测试宏_GNU_SOURCE才能使用
- O_DSYNC:每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新(Linux 2.6.33开始支持)
- O_EXCL:和O_CREAT一起使用,如果文件已存在,则返回错误,用于测试文件是否存在
- O_LARGEFILE:打开大文件(超过4G的文件),在32位系统中有效
- O_NOATIME:读文件时,不更新文件的最近访问时间,可提高性能(Linux 2.6.8开始支持)
- O_NOCTTY:防止设备称为控制终端,以防键盘输入影响到进程。
- O_NOFOLLOW:如果pathname是符号链接,则打开符号链接,不对其进行解引用,需要定义功能测试宏_GNU_SOURCE才能使用
- O_NONBLOCK:非阻塞方式打开文件
- O_SYNC:每次write都等待物理I/O操作完成,包括对文件的属性更新。
- O_TRUNC:如果文件已存在,清空文件
- …/mode_t mode/:文件的属性,O_CREAT时才会使用
权限 | 值 | 作用 |
---|---|---|
S_IRWXU | 00700 | 用户读写执行 |
S_IRUSR | 00400 | 用户读 |
S_IWUSR | 00200 | 用户写 |
S_IXUSR | 00100 | 用户执行 |
S_IRWXG | 00070 | 组读写执行 |
S_IRGRP | 00040 | 组读 |
S_IWGRP | 00020 | 组写 |
S_IXGRP | 00010 | 组执行 |
S_IRWXO | 00007 | 其他读写执行 |
S_IROTH | 00004 | 其他读 |
S_IWOTH | 00002 | 其他写 |
S_IXOTH | 00001 | 其他执行 |
* 三种特殊权限
* S_ISUID:04000:用于修饰可执行权限,让调用者拥有可执行文件的拥有者的用户权限
* S_ISGID:02000:用于修饰可执行权限,让调用者拥有可执行文件的拥有者的组权限
* S_ISVTX:01000:作用1:修饰可执行程序,可执行程序执行完成后,会在swap缓存,由于swap时连续的,读取速度比磁盘快,可用于程序快速启动。作用2:在/tmp目录下可以创建自己的文件,但不能删除别人的文件。
create():创建文件
int creat(const char *pathname, mode_t mode); //创建文件
- int 返回值:成功返回0,失败返回-1并设置errno
- const char *pathname:文件名
- mode_t mode:文件属性,同open()的第三个参数相同
read():读取文件
ssize_t read(int fd, void *buffer, size_t count); //读文件
- ssize_t返回值:成功返回实际读取字节数,失败返回-1并设置errno,针对不同的文件类型,会有不同的出错返回值以及处理方式,这里不进行详述
- int fd:文件描述符
- void *buffer:缓冲区
- size_t count:请求读取字节数(实际读取字节可能小于请求读取字节)
注:请求读取字节不能大于缓冲区大小
write():写入文件
ssize_t write(int fd, void *buffer, size_t count); //写文件
- ssize_t返回值:成功返回实际写入字节数,失败返回-1并设置errno,针对不同的文件类型,会有不同的出错返回值以及处理方式,这里不进行详述
- int fd:文件描述符
- void *buffer:缓冲区
- size_t count:请求写入的字节数(实际写入字节可能小于请求写入字节)
注:请求写入字节数不能大于缓冲区大小
close():关闭文件
int close(int fd); //关闭文件
- int返回值:成功返回0,失败返回-1并设置errno
- int fd:文件描述符
lseek():修改偏移量
每个文件都有一个文件偏移量指针,指向当前写入文件的位置,read()、write()操作会自动更改文件偏移量指针的位置。可使用lseek()手动调整指针的位置。当指针指向一块没有实际内容的文件时(指针超出文件的尾部)会形成空洞文件。
空洞文件的空洞部分几乎不占用任何空间(存储空洞信息会占用空间,但不一定会分配新的磁盘块),读取空洞文件时,空洞部分会以0填充。
off_t lseek(int fd, int offset, int whence); //修改偏移量
- off_t返回值:返回当前文件偏移量指针
- int fd:文件描述符
- int offset:偏移量,可为0,表示当前位置;可为正,表示向后;可为负,表示向前
- int whence:参考位置
位置 | 值 | 解释 |
---|---|---|
SEEK_SET | 0 | 从0开始 |
SEEK_CUR | 1 | 从当前偏移量开始 |
SEEK_END | 2 | 从文件尾部的下一个字节开始 |
ioctl():I/O控制
int ioctl(int fd, int request, .../*argp*/); //I/0控制
- int返回值:成功返回0,失败返回-1并设置errno
- int fd:文件描述符
- int request:请求类型,不同的请求类型会有不同的argp参数
- …:argp参数
注:针对不同的文件类型,会有不同的请求类型,这里不进行详述
通用I/O中的多态
强调一下,任何类型的文件,都以文件描述符为句柄,针对不同的文件类型,通用I/O会做出不同的操作(调用不同的函数),此为通用I/O的多态。
文件描述符,打开文件表,i-node之间的关系
- 每个进程都有PCB,PCB中包含文件描述符表
- 内核有打开文件表,用于存储系统中所有打开的文件
- 内核有i-node表,用于描述文件实际存储的位置