Linux 基础 IO(二):系统文件 IO
一、IO 操作的层级调用关系
简单来说:
C/C++程序(标准库)→ 调用 →系统调用→ 调用 →操作系统→ 调用 →硬件驱动→ 操作 →硬件。
应用程序 (App) ↓ C/C++ 标准库 (Libc) ↓ 系统调用接口 (Syscall) ↓ 操作系统内核 (Kernel) ↓ 硬件驱动程序 (Driver) ↓ 硬件 (Hardware)
- 操作系统为保证安全,仅通过系统调用对外开放硬件访问接口,任何程序(包括 C 标准库)都需通过系统调用才能自上而下访问操作系统→硬件驱动→硬件;
- printf/fprintf/fscanf/fwrite/fread/fgets/gets 等文件操作库函数,本质是对文件类系统调用的封装,其底层均依赖系统调用实现对硬件的读写。
二、open
系统接口中使用 open 函数打开文件,open 函数的函数原型如下:
int open(const char* pathname, int flags, mode_t mode);

2.1 第一个参数
open 函数的第一个参数是 pathname,表示要打开或创建的目标文件。
- 若 pathname 以路径的方式给出,则当需要创建该文件时,就在 pathname 路径下进行创建。
- 若 pathname 以文件名的方式给出,则当需要创建该文件时,默认在当前路径下进行创建。(注意当前路径的含义)
2.2 第二个参数
open 函数的第二个参数是 flags,表明打开文件的方式。
我们要告诉操作系统:'我要读写模式打开'、'如果文件不存在就创建'、'每次写都追加到末尾'。
- 如果按照常规思维,这需要 3 个布尔类型的参数(
isReadWrite,isCreate,isAppend)。如果有 10 种操作模式,难道要写 10 个参数吗?
显然不是。Linux 大神们只用了一个 int 类型(32 位)就搞定了。这背后的核心魔法,就是比特位传递标志位。
2.2.1 核心原理:把整数当成'32 个开关的面板'
我们可以把一个 类型的变量,想象成一个拥有 的控制面板。









