而标准 IO 在接口设计与使用方式上 , 却不会与某类特定的操作系统进行“绑定” 。 相反 , 它会提供更加统一和通用的接口 , 来屏蔽底层不同系统的不同实现细节 , 做到“一次编写 , 到处编译” 。
除此之外 , 即使上述两段采用不同级别 IO 接口实现的 C 代码 , 在实际的可观测执行效果方面基本一致 , 但它们在程序运行时 , 资源的背后使用逻辑上却有着较大的差异 。
带缓冲的标准 IO 模型那么 , 这两种 IO 模型除了在接口使用方式上有不同外 , 还有哪些重要差异呢?简单来讲 , 与低级 IO 相比 , 标准 IO 会为我们提供带缓冲的输入与输出操作 。 事实上 , 标准 IO 接口在实现时 , 会直接使用所在平台提供的低级 IO 接口 。 而低级 IO 接口在每次调用时 , 都会通过系统调用来完成相应的 IO 操作 。
关于系统调用的内容 , 这一讲的后面还会提到 。 并且 , 我也会在第 31 讲中再为你深入介绍 。 在这里你只需要知道 , 系统调用的过程涉及到进程在用户模式与内核模式之间的转换 , 其成本较高 。 为了提升 IO 操作的性能 , 同时保证开发者所指定的 IO 操作不会在程序运行时产生可观测的差异 , 标准 IO 接口在实现时通过添加缓冲区的方式 , 尽可能减少了低级 IO 接口的调用次数 。
让我们再把目光移回到之前的两段示例代码上 。 不知道你在运行对应的两段程序时 , 是否有观察到它们之间的差异呢?实际上 , 使用低级 IO 接口实现的程序 , 会在用户每次输入新内容到标准输入流中时 , 同时更新文件 “temp.txt” 中的内容 。 而使用标准 IO 接口实现的程序 , 仅会在用户输入的内容达到一定数量或程序退出前 , 再更新文件中的内容 。 而在此之前 , 这些内容将会被存放到缓冲区中 。
当然 , C 标准中并未规定标准 IO 接口所使用的缓冲区在默认情况下的大小 , 对于其选择 , 将由具体标准库实现自行决定 。
除此之外 , 标准 IO 还为我们提供了可以自由使用不同缓冲策略的能力 。 对于简单的场景 , 我们可以使用名为 fflush 的接口 , 来在任意时刻将临时存放在缓冲区中的数据立刻“冲刷”到对应的流中 。 而在相对复杂的场景中 , 我们甚至可以使用 setvbuf 等接口来精确地指定流的缓冲类型、所使用的缓冲区 , 以及可以使用的缓冲区大小 。
比如 , 我们可以在上述标准 IO 实例对应 C 代码的第 4 行后面 , 插入以下两行代码:
// ...
char buf[1024
;
setvbuf(fp buf _IOFBF 5);
// ...
此时 , 再次编译并运行程序 , 其执行细节与之前相比会有什么不同?欢迎在评论区告诉我你的发现 。
用于低级 IO 接口的操作系统调用接下来 , 让我们再来看一看低级 IO 的相关实现细节 。
在前面的内容中我曾提到过 , 低级 IO 接口在其内部会通过系统调用来完成相应的 IO 操作 。 那么 , 这个过程是怎样发生的呢?
实际上 , 你可以简单地将系统调用当作是由操作系统提供的一系列函数 。 只是相较于程序员在 C 源代码中自定义的“用户函数”来说 , 系统调用函数的使用方式有所不同 。 与调用用户函数所使用的 call 指令不同 , 在 x86-64 平台上 , 我们需要通过名为 syscall 的指令来执行一个系统调用函数 。
操作系统会为每一个系统调用函数分配一个唯一的整型 ID , 这个 ID 将会作为标识符 , 参与到系统调用函数的调用过程中 。 比如在 x86-64 平台上的 Linux 操作系统中 , open 系统调用对应的 ID 值为 2 , 你会在接下来的例子中看到它的实际用法 。
同用户函数类似的是 , 系统调用函数在被调用时 , 也需要通过相应的寄存器来实现参数传递的过程 。 而正如我在第 05 讲 中提到的那样 , SysV 调用约定中规定 , 系统调用将会使用寄存器 rdi、rsi、rdx、r10、r8、r9 来进行实参的传递 。 当然 , 除此之外 , rax 寄存器将专门用于存放系统调用对应的 ID , 并接收系统调用完成后的返回值 。
- 文艺辣评丨新东方直播:一场语言的行为艺术?
- c语言|负责任地推荐这3部手机,好看又配置强,用到2026年不成问题
- 老虎|36家科技巨头组建元宇宙标准论坛!被批为“纸老虎”!我们应该相信吗?
- 卫报|元宇宙、虚拟数字人,微软等科技巨头布局行业标准,中国也在行动
- jedec|芯动科技宣布LPDDR5X速率突破10Gbps,比JEDEC标准高出17.2%
- 京东|Java:有哪些快速学习Java语言的技巧?
- 长江存储|荣耀Magic4系列标准版和Pro版该咋选? 搞清这几方面,可信手拈来
- 红杉资本|广州蓝景技术分享—开发语言JavaScript之多线程
- 诺基亚|听人话生成代码厉害了,国内首个自然语言生成方法级代码的AI
- “第二地球”判定标准来了,科学家:或可用大气矿尘寻找外星生命
