一、简介
本节讨论Unix系统中大多数文件用到的5个函数:open,read,write,lseek,close。本节描述的函数经常被称为不带缓冲的IO。不带缓冲指的是每个read和write都调用内核中的一个系统调用。这些不带缓冲的IO函数不是ISO C的组成部分,但是,它们是POSIX.1和Singer UNIX Specification的组成部分。具体详见以下博客。UNIX 标准之ISO C、IEEE POSIX和Single UNIX Specificatiohttps://blog.csdn.net/lemonpi/article/details/78965060?ops_request_misc=&request_id=&biz_id=102&utm_term=Singer%20UNIX%20Specification%E7%AE%80%E4%BB%8B&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-78965060.142%5Ev59%5Epc_rank_34_queryrelevant25,201%5Ev3%5Econtrol_2&spm=1018.2226.3001.4187
二、文件描述符
对于内核而言,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数。当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,使用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。
按照惯例,UNIX系统shell把文件描述符0与进程的标准输入关联,文件描述符1与标准输出关联,文件描述符2与标准错误关联。这是各种shell以及很多应用程序使用的惯例,与UNIX内核无关。尽管如此,如果不遵循这种惯例,很多UNIX系统应用程序就不能正常工作。
在符合POSIX.1的应用程序中,幻数0、1、2虽然已被标准化,但应当把它们替换成符号常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO以提高可读性。这些常量都在头文件<unistd.h>中定义。
文件描述符的变化范围是0~OPEN_MAX-1。早期的UNIX系统实现采用的上限值是19(允许每个进程最多打开20个文件),但现在很多系统将其上限值增加至63。
三、文件来源
在 Linux 系统中,一切都是“文件”:普通文件、驱动程序、网络通信等等。 所有的操作,都是通过“文件 IO”来操作的。所以,很有必要掌握文件操作的常用接口。如图 1 所示,Linux 的文件既可以是真实保存到存储介质的文件也可以 是自身内核提供的虚拟文件,还可以是设备节点。
四、访问文件
1.通用的 IO 模型:open/read/write/lseek/close
参考以下博客:
2.不是通用的函数:ioctl/mmap
参考以下博客:
五、函数手册
Linux下有三大帮助方法:help、man、info。想查看某个命令的用法时,比如查看ls命令的用法,可以执行:
ls --help
help 只能用于查看某个命令的用法,而 man 手册既可以查看命令的用法,还可 以查看函数的详细介绍等等。它含有 9 大分类,如下:
1 Executable programs or shell commands // 命令
2 System calls (functions provided by the kernel) // 系统调用,比如 man 2 open
3 Library calls (functions within program libraries) // 函数库调用
4 Special files (usually found in /dev) // 特殊文件, 比如 man 4 tty
5 File formats and conventions eg /etc/passwd // 文件格式和约定, 比如 man 5
//passwd
6 Games // 游戏
7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
8 System administration commands (usually only for root) // 系统管理命令
9 Kernel routines [Non standard] // 内核例程
比如想查看 open 函数的用法时,可以直接执行“man open”,发现这不是 想要内容时再执行“man 2 open”。 在 man 命令中可以及时按“h”查看帮助信息了解快捷键。常用的快捷键是:
f 往前翻一页
b 往后翻一页
/patten 往前搜
?patten 往后搜
六、系统调用函数进入内核
如下图2所示,以open/read为例,从用户态调用API触发异常进入内核:
如图3所示,进入内核后,sys_read/open 会首先根据参数判断文 件的类型,然后根据不同的文件类型去找不同的设备驱动,继而进行读写或者输 入输出控制。