【Linux】Linux 操作系统 - 19 , 重谈文件(三) ~ 学好 Linux 精髓是什么 , 缓冲区又是什么 ???【面试】
文章目录
- ● Linux 精髓 --- 一切皆文件
- 如何做到的 ??
- ● 缓冲区
- 一 、什么是缓冲区 ?
- 二 、理解缓冲区
- 0 .
- 1 . 用户级语言层缓冲区和内核级文件缓冲区
- 2 . 用户级语言层缓冲区在哪里呢 ??
- 3 . 用户满足什么条件语言层缓冲区会刷新呢 ??
- 4 . 再谈以上代码出现的现象的原因 ? (0. 中的代码)
- 总结
- ● 缓冲区的使用(要理解本质 , 重要 , 面试题)
- 总结
● Linux 精髓 — 一切皆文件
在 Linux 中 , 一切皆文件 , 对没错 , 你没听错 !!! 是一切 .
有人可能会想了 , Linux 系统不是还要管理硬件吗 ?? 能把硬件叫文件 ?? 怎么做到的 ??
先引出以下概念 :
前提铺垫
如何做到的 ??
所以 , 真的是一切皆文件吗 ???
对于进程一层而言 , 因为上层都是用的同一个函数指针 , 同名 , 同参类型的函数指针会屏蔽底层不同硬件的差异 , 通过函数指针指向不同的硬件 , 这样对于上层来说 , 无论访问什么都是通过 read , write 这样的系统调用来访问的 , 所以 , 对上层而言一切皆文件 !
所以 , 要访问一个硬件 , 都是通过函数指针进行访问 !!!
这个模式相当于 C++ 中的多态 ! , struct file 这一层相当于基类 , 指向的不同的硬件相当于派生类 !
- 源码
● 缓冲区
一 、什么是缓冲区 ?
缓冲区 是内存空间的⼀部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输人或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输⼊设备还是输出设备,分为输入缓冲区和输出缓冲区 。
简单来讲 : 缓冲区就是内存的一段空间 , 用来缓冲存储数据的 ! 提高效率的 !
二 、理解缓冲区
0 .
这里先看一段代码 :
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int main()
{ close(1);int fd = open("log.txt" , O_CREAT | O_WRONLY | O_TRUNC , 0666);// printf 默认向显示器打印 , 但是现在像 log.txt 打印printf("fd : %d\n" , fd);printf("Hello Linux!\n");printf("Hello Linux!\n");printf("Hello Linux!\n");//系统调用写内容const char* str = "I am Linux!\n";write(fd ,str , strlen(str));// 1 . 不用 close 关闭 fd , 后程序什么效果 ?//close(fd);// 2 . 用 close 关闭 fd , 后程序什么效果 ? close(fd);return 0;
}
-
不用
-
用
??? 为什么效果会不一样呢 ?? 到底什么原因 ?? 笔者介绍以下后 , 会再次谈 !
1 . 用户级语言层缓冲区和内核级文件缓冲区
我们经常谈缓冲区 , 但是这个缓冲区究竟是指的什么呢 ??
-
引出
-
具体谈
-
总结 , 我们平常谈的缓冲区到底是什么呢 ??
我们平常说的缓冲区其实是 , 用户级语言层的缓冲区 !
对于缓冲区我们要明白的 : -
缓冲区是有两个 : 1. 语言层的缓冲区 2 . 系统级的内核文件缓冲区
-
当对显示器写入时(需要在显示器打印时) , 1 . 先把内容拷贝到标准库的语言层缓冲区中 2.当语言层缓冲区满足刷新条件时 , 再拷贝到内核级的文件缓冲区中 !
-
当需要从硬件中读取时 , 会先把内容拷贝到内核文件缓冲区 , 满足刷新条件时 , 会拷贝到上层的语言层缓冲区 !
-
总之 : 明白 , 缓冲区并不只有系统级 , 并且用户不能直接和系统打交道 , 中间需要语言层缓冲区的存在 !
2 . 用户级语言层缓冲区在哪里呢 ??
目前 ,只知道在标准库中 , 但具体呢 ??
注意观察 ,我们使用的 fprintf , fwrite 等都会有 FILE* 这样的东西 ?? 那 FILE 是什么呢 ??
所以 , 对于这样的接口来说 , FILE* 是什么 ?
FILE *fopen(const char *pathname, const char *mode);
FILE* 就是一个结构体指针 , 指向 FILE 这个结构体 , 每当有一个文件成功打开时 , C语言就会创建一个 FILE 的对象 ! 会存该文件的文件描述符 , 缓冲区等 ..
- 源码验证
3 . 用户满足什么条件语言层缓冲区会刷新呢 ??
当满足以上条件之一时 , 都会进行刷新 !!!
4 . 再谈以上代码出现的现象的原因 ? (0. 中的代码)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>int main()
{ close(1);int fd = open("log.txt" , O_CREAT | O_WRONLY | O_TRUNC , 0666);// printf 默认向显示器打印 , 但是现在像 log.txt 打印printf("fd : %d\n" , fd);printf("Hello Linux!\n");printf("Hello Linux!\n");printf("Hello Linux!\n");//系统调用写内容const char* str = "I am Linux!\n";write(fd ,str , strlen(str));// 1 . 不用 close 关闭 fd , 后程序什么效果 ?//close(fd);// 2 . 用 close 关闭 fd , 后程序什么效果 ? close(fd);return 0;
}
总结
对于缓冲区这里 , 最终我们要掌握什么知识呢 ??
● 缓冲区的使用(要理解本质 , 重要 , 面试题)
给出以下代码 , 观察现象 , 并回答为什么 ? 面试题
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>int main()
{// 库函数 // 用向显示器打印的接口 printf("hello printf!\n"); // 默认向 1 - stdout 打印fprintf(stdout , "hello fprintf\n");const char* str = "hello fwrite\n";fwrite(str ,strlen(str) , 1 , stdout);// 系统调用 const char* s = "hello write\n";write( 1 , s , strlen(s));//创建子进程 fork();return 0;
}*********** 用 gcc buf.c , 默认编译 , 生成 a.out 的可执行程序 *********** 解释一下 , 为什么第一次出现 4 条内容 ; 第二次会出现 7 条 , 库函数内容出现均出现两次 , 系统调用却只出现一次呢 ??????? 第一次 : ./a.outhello printf!hello fprintfhello fwritehello write------------------
第二次 :./a.out > test.txt cat test.txt hello writehello printf!hello fprintfhello fwritehello printf!hello fprintfhello fwrite
注 : 这个题要好好理解 , 很重要 !!!