欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

【Linux系统编程】文件IO系统——IO标准库函数与系统调用

时间:2023-06-25
文章目录

IO标准库函数与系统调用 缓冲区 

行缓冲测试无缓冲测试 IO标准库函数与系统调用 

标准库函数运行在用户空间下,而系统调用运行在内核空间下。

IO标准库函数中使用了系统调用。例如,fopen(3) 调用 open(2) 打开指定的文件,返回一个文件描述符(就是一个int类型的编号),分配一个 FILE 结构体,其中包含该文件的描述符(FD)、IO缓冲区和当前读写位置等信息,返回这个 FILE 结构体的地址。Linux中输入命令 man 2 open 查看第二章节系统调用的 open。

使用命令 man man 查看 man 命令的帮助,man帮助手册的第3部分是库函数的调用,如fopen(3),第2部分是系统调用,即由系统内核提供的函数,如 open(2)。


fgetc(3) 通过传入的 FILE * 参数找到该文件的描述符、IO缓冲区和当前读写位置,判断能否从IO缓冲区中读到下一个字符,如果能读到就直接返回该字符,否则调用 read(2),把文件描述符传进去,让内核读取该文件的数据到IO缓冲区,然后返回缓冲区的下一字符。

fputc(3) 判断该文件的IO缓冲区是否有空间再存放一个字符,如果有空间则直接保存在IO缓冲区中并返回,如果IO缓冲区已满就调用 write(2),让内核把IO缓冲区的内容写回文件。

fclose(3) 如果IO缓冲区中还有数据没写回文件,就调用 write(2) 写回文件,然后调用 close(2) 关闭文件,释放 FILE结构体 和 IO缓冲区。

fgetc、fputc 等函数本质上只是用户对传入的 FILE * 参数进行操作,并没有直接对文件进行操作,用户只是调用系统调用,让操作系统内核帮我们操作文件。操作系统才是直接对文件进行操作的角色,用户只是通过系统调用间接操作文件。用户对 FILE * 这个指针参数进行操作便能完成对文件整体的操作,故将 FILE * 参数称为句柄(类似于门把手,可以通过门把手打开整扇门)。

缓冲区 

同时,IO标准库帮我们维护 buffer 这个IO缓冲区,因此IO标准库也叫做缓冲IO函数。buffer 缓冲区的作用是帮助提高文件读写的效率,可以将IO缓冲区类比为收发快递的菜鸟驿站,当用户寄出去的快递达到一定数量的时候,才会统一发货,否则会提高运输次数,浪费资源(当程序要写进文件的字符达到一定数量的时候,才会统一写进文件,最大化利用资源,因为用户态和内核态的转换需要时间)。

当商户给用户发多件货物时,肯定是统一发送至菜鸟驿站比较高效节约运输次数(当程序要从文件中读取字符时,先切换至内核态,拉一批字符出来到IO缓冲区,再切回用户态逐一读取字符,这样只需要切换两次状态)。

缓冲区分为三类:全缓冲、行缓冲、无缓冲。全缓冲是指待缓冲区填满的时候,再进行系统调用将缓冲区内容输入到内存或输出到磁盘;行缓冲是指当缓冲区出现换行符或填满时,立即进行系统调用;无缓冲是指当缓冲区用东西进来的时候,马上进行系统调用。

stdout 是行缓冲,遇到换行符或填满才将缓冲区内容输出到标准输出(屏幕)中;stderr 是无缓冲,立即将“错误信息”输出到标准输出中。

行缓冲测试

#include int main() { fputc('A', stdout); fputc('B', stdout); fputc('C', stdout); while (1) {} //加入死循环,使程序一直在运行,避免进程结束将缓冲区内容输出到屏幕 return 0;}#include int main() { fputc('A', stdout); fputc('B', stdout); fputc('C', stdout); fputc('n', stdout); //加入了换行符 while (1) {} return 0;}#include int main() { //向缓冲区中输入1024个字符 for (int i = 0; i < 1024; i++) { fputc('A', stdout); } while (1) {} return 0;}#include int main() { for (int i = 0; i < 1025; i++) { fputc('A', stdout); } while (1) {} return 0;}

test1结果如下,屏幕没有任何输出。

test2结果如下,stdout 缓冲区中有换行符输入,立即进行系统调用将缓冲区内容(ABCn)输出到标准输出(屏幕)中。

test3结果如下,向缓冲区中输入1024个A后,仍然没有进行系统调用将缓冲区内容输出到屏幕中,说明缓冲区大小至少为1024个字节(即1KB),因为缓冲区满了之后,需要再输入一个字符才能将缓冲区内容输出到屏幕。

test4结果如下,向缓冲区输入1025个A后,缓冲区内容通过系统调用输出到了屏幕中,是因为当输入第1024个A之后,缓冲区刚好满了,在输入第1025个字符时,发现缓冲区满了,立即通过系统调用将缓冲区内容(1024个A)输出到屏幕中,最后再将第1025个A输入到缓冲区中,即此时缓冲区中仍然有一个A。

无缓冲测试

#include int main() { fputc('A', stderr); fputc('B', stderr); fputc('C', stderr); while (1) {} return 0;}

test1结果如下,stderr 缓冲区中一旦有字符输入,立即进行系统调用将该字符输出到屏幕中。

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。