前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【Linux探索学习】第二十二弹——用户缓冲区:系统如何更好的控制数据交互

【Linux探索学习】第二十二弹——用户缓冲区:系统如何更好的控制数据交互

作者头像
GG Bond1
发布2024-12-18 16:57:11
发布2024-12-18 16:57:11
9200
代码可运行
举报
文章被收录于专栏:C/C++葵花宝典
运行总次数:0
代码可运行

Linux学习笔记:

https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482

前言:

前面两章我们已经讲了一些文件操作和文件重定向问题,以及一些相关的知识点,比如文件在内存中的存储位置,物理内存和虚拟内存的概念,文件描述符的问题等,今天我们要再学一个与内存有关的概念——用户缓冲区。 在操作系统中,缓冲区是用于存储数据的内存区域。在 Linux 中,用户缓冲区通常指的是由用户空间应用程序分配和管理的内存区域,用来存储从外部设备读取或写入的数据。操作系统通过缓冲区来避免频繁地进行 I/O 操作,提高效率,同时保证数据的完整性和一致性。 本篇主要通过一些代码示例来帮助大家理解缓冲区的问题,内容偏向于基础一点的,学习完之后可以结合一些Linux相关的书籍再看看

我们讲解的重点会放在讲解什么是缓冲区上,对于缓冲区存在的作用和种类等方面上了解一下就行

一、什么是缓冲区?

我们通过几个场景来揭露这个问题,首先我们先来看下面这串代码及其输出结果:

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
#include<string.h>
#include<unistd.h>              
int main()    
{             
    const char *fstr="hello fwrite\n";
    const char *str="hello write\n";
              
    //C语言接口
    printf("hello printf\n");   //stdout -> 1
    fprintf(stdout,"hello fprintf\n");   //stdout -> 1
    fwrite(fstr,strlen(fstr),1,stdout);  //fread, stdout -> 1
    //操作系统提供的系统接口
    write(1,str,strlen(str));                                                                                                                                                                                           
    return 0; 
 }            

运行结果:

我们可以把这个结果输出重定向到指定文件中去

代码语言:javascript
代码运行次数:0
复制
./myfile>log.txt
cat log.txt

但是如果我们在代码段的最后一行加入fork函数来创建子进程,我们就会得到一个不一样的输出结果:

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
#include<string.h>
#include<unistd.h>              
int main()    
{             
    const char *fstr="hello fwrite\n";
    const char *str="hello write\n";
              
    //C语言接口
    printf("hello printf\n");   //stdout -> 1
    fprintf(stdout,"hello fprintf\n");   //stdout -> 1
    fwrite(fstr,strlen(fstr),1,stdout);  //fread, stdout -> 1
    //操作系统提供的系统接口
    write(1,str,strlen(str));           
    fork();                                                                                                                                                                                
    return 0; 
 }            

运行结果:

我们发现再次输出重定向时结果发生了很大的改变,调用C语言接口的语句被打印了两遍,而系统调用接口则只被打印一遍,而且顺序也发生了变化,调用系统接口的先被打印

为什么会出现这种情况呢?在解释之前我们先来看下面这种情况:

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
#include<string.h>
#include<unistd.h>              
int main()    
{             
    const char *fstr="hello fwrite\n";
    //const char *str="hello write\n";
              
    //C语言接口
    printf("hello printf\n");   //stdout -> 1
    fprintf(stdout,"hello fprintf\n");   //stdout -> 1
    fwrite(fstr,strlen(fstr),1,stdout);  //fread, stdout -> 1
    close(1);
    //操作系统提供的系统接口
    //write(1,str,strlen(str));           
    //fork();                                                                                                                                                                                
    return 0; 
 }            

我们只留下C语言的几个打印方式,同时在打印执行完后把1号文件关闭了

运行结果:

上面的每一条打印语句我们都通过\n来刷新缓冲区的,如果我们把\n去掉再执行一遍:

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
#include<string.h>
#include<unistd.h>              
int main()    
{             
    const char *fstr="hello fwrite";
    //const char *str="hello write\n";
              
    //C语言接口
    printf("hello printf");   //stdout -> 1
    fprintf(stdout,"hello fprintf");   //stdout -> 1
    fwrite(fstr,strlen(fstr),1,stdout);  //fread, stdout -> 1
    close(1);
    //操作系统提供的系统接口
    //write(1,str,strlen(str));           
    //fork();                                                                                                                                                                                
    return 0; 
 }            

运行结果:

我们发现没有任何输出结果,这又是什么原因呢? 注意:是在close(1)关闭和\n去掉同时存在的情况下才有了这样的结果

但是如果我们是对系统接口执行这个操作:

执行结果:

我们发现此时有打印结果


其实原因如下:

我们对上面的内容做一个叙述:我们都知道我们写入的内容是要先存在缓冲区的,但实际上我们通过C语言的接口所写的内容,比如print、fprint等接口所写内容所存在的缓冲区并不是在内核中的,它是在内核以外的,是语言的这些接口随后调用write系统接口才将其写入内核中去的,在我们关闭1号显示器文件时,内核中写入的内容会被我们输出到显示其中,但是缓冲区中的内容我们需要先调用write接口写入内核中去,但是1号文件都被关闭了,所以自然 是不能再写入内核中去的,所以最后就不能被显示在显示器上

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是缓冲区?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档