Linux---文件(2)---文件描述符缓冲区(语言级)
目录
文件描述符
基础知识
文件描述符
对“Linux一切皆文件”的理解
文件描述符分配规则
缓冲区
刷新策略
存放位置
解释一个"奇怪的现象"
格式化输入输出
文件描述符
基础知识
在系统层面上,文件操作都是通过文件描述符来操作的。
程序在启动的时候,会默认打开三个文件流stdin(标准输入流)、stdout(标准输出流)、stderr(标准错误流)。这三个也是文件,在程序启动时由操作系统默认打开,程序退出时由操作系统默认关闭。这三个文件也有其对应的文件描述符,分别为0、1、2。所以,我们在程序中打开的文件的文件描述符是从3开始的。
C语言的文件接口,本质就是封装了系统调用。
C语言封装系统调用本质上是为了解决跨平台性、可移植性。在任何平台都使用的同一套C语言对文件的接口,底层会去调用不同平台的系统调用接口。在语言上访问文件的接口是不一样的,但只要是在一个系统中,底层调用的系统调用接口都是相同的。
在系统的角度来看,操作文件依赖的是文件描述符。
而在C语言中,操作文件却用的是文件指针。
这是因为C语言中的FILE是C语言标准库自己封装的一个结构体,在FILE结构体中,必定封装了文件描述符、文件属性、文件内容指向等字段。
进程创建出来后,操作系统将stdin、stdout、stderr文件加载到内存,由FILE结构体对象将其文件的信息记录下来,并将对象节点以某种数据结构进行连接管理。由于这三个文件已经占用了0、1、2,所以我们在进程中打开的文件的文件描述符就从3开始。
文件描述符
文件描述符本质是数组下标。
操作系统要管理被进程打开的文件,就要"先描述,再组织",利用特定的数据结构节点来管理被打开的文件,此后,对被打开的文件做管理就变成了对特定的数据结构进行管理了。
CPU执行到处理文件时,内部通过文件描述符调用相关的系统调用接口,操作系统通过访问进程PCB中的struct files_struct结构体指针,通过这个指针找到文件描述符表,再以文件描述符作为下标索引对应管理文件的struct file结构体的指针,通过对这个结构体进行处理,等到文件退出时再将修改的信息对磁盘文件中做更新。
在缓冲区上访问文件内容,缓冲区通过与磁盘的刷新来对文件做修改操作。
文件描述符本质上就是数组下标。
对“Linux一切皆文件”的理解
1、每个硬件都有与之匹配的特有的读写方法。
2、操作系统要管理每个硬件("先描述,再组织")
3、利用类似多态调用的思想,实现调用时调用指针所指向的对象的方法。
操作系统用上层统一的接口来屏蔽硬件读写差异。
文件描述符分配规则
文件描述符分配规则:最小的没有被使用的文件描述符会优先分配给最新打开的文件。
系统打印时如果没有特殊要求,系统只在stdout文件中去打印,本质上是系统只在文件描述符为1的文件中去打印。
当文件描述符为1的文件是stdout时,则输出到显示器文件上。
当文件描述符为1的文件是其他文件时,则输出到其他文件上去。
所以,修改1号文件描述符的文件,即可发生类似于重定向的操作。
重定向的本质就是修改文件描述符表中指针指向的内容,将这个内容修改为其他文件的地址(覆盖掉原来的地址即可),写入操作就会写入到其他文件中去。
直接覆盖文件描述符表对应下标的内容接口
这种处理会导致一个文件被多个指针指向,操作系统会对此情况进行处理。
printf/fprintf/sprintf函数在输出的时候都去stdout文件中输出,
本质是都输出到文件描述符为1的文件中去。
scanf/fscanf/sscanf函数在输入的时候都去stdin文件中去读取,
本质是都从文件描述符为0的文件中去读取。
重定向操作也是通过dup2系统调用接口,将对应的文件描述符表的内容做修改,从而实现的。
缓冲区
缓冲区本质是一块内存区域。
缓冲区的设计是用空间换时间,存在本质是为了提高用户的操作效率。
此缓冲区为语言层面的缓冲区,与操作系统内核中的缓冲区无关。
C语言本身自带缓冲区。
缓冲区是将数据聚集起来,做少次数的数据传输,来提高效率。
以用户写入操作举例,用户通过调用用户级接口向指定文件写入数据,C语言会将用户传的数据写入到自己的缓冲区中,等到缓冲区达到某种规则时,C语言会将自己缓冲区内的内容通过系统调用接口写入到操作系统内核中该进程对应的缓冲区中(C语言会通过进程PCB中的文件描述符表,以文件描述符为下标索引到管理文件的节点,通过节点的字段找到该进程对应的内核缓冲区)。由操作系统决定何时将缓冲区中的内容写入刷新到磁盘文件中。
每个进程都有自己的内核缓冲区。
系统调用本身是有成本的。
单次调用一次系统调用的效率高。比如:申请相同大小的空间,第一种方法:多次调用系统调用且每次申请较小的空间资源。第二种方法:少次调用系统调用接口且每次申请较多的空间资源。这两种方法,第二种是比第一种的效率高的,所以我们应该尽可能的减少调用系统调用接口的次数。
操作系统深知应尽可能少调用系统调用,所以在内存空间足够的情况下,对于系统调用接口,会在内存中预先申请大量的空间资源来提供使用。比如:我们调用fork系统调用的时候,看似我们调用了系统调用,其实是操作系统提前在内存中申请的空间资源,提前创建空壳进程PCB、页表、mm_struct等,等到我们调用该系统调用时,操作系统就不用给我们重新申请资源、创建PCB等操作了,就直接使用内存中提前准备好的空壳进程的一套资源,只需要写入对应的字段即可,这种做法提高了操作系统的效率。当然,当内存中资源不足的时候,操作系统会做各种挂起、终止不必要进程等操作,来保证操作系统的正常运行。
缓冲区就是提前申请好的内存空间。比如:我们在使用数据结构插入接口时,会直接插入到提前申请好的内存空间上去,不用再调用扩容机制接口,来提高效率。
执行多次写入操作都是将数据写入到语言级缓冲区中,此缓冲区按照自己的机制/策略,在合适的时机调用系统调用接口,将数据一次性全部写入到内核缓冲区中,再由操作系统决定,将内核缓冲区中的数据刷新到磁盘上,此操作有效减少了调用系统调用接口的次数,提高效率。
用户级别接口只需要将数据写入到语言级的缓冲区中,语言层就会给用户返回调用结果。从语言级缓冲区到内核缓冲区再到刷新到磁盘文件中这个过程,不用用户关心处理,这操作由操作系统整体把控,此操作还有效提高了语言级接口的使用效率。
刷新策略
语言级缓冲区通过系统调用接口将数据刷新(拷贝)到内核缓冲区的策略为:
1、无刷新---无缓冲:没有设计缓冲区,每次调用语言级接口都会调用系统调用。
2、行刷新:以'\n'字符为标志,每次刷新'\n'字符之前的数据,显示器文件就是行刷新。
3、全缓冲:缓冲区被写满后,才会被刷新。普通文件就是全缓冲。
如果上述情况都没有满足时,比如:行刷新但没有检测到'\n'、全刷新但缓冲区没有被写满
1、强制刷新接口
2、进程退出时,会自动刷新。
存放位置
语言级缓冲区本质是在管理文件的FILE结构体中,由该FILE结构体维护。
每一个文件都有对应的FILE结构体,都有对应的语言级缓冲区。
语言级缓冲区被管理该文件的FILE结构体维护,内存缓冲区被进程PCB维护。
C语言封装的意义:
1、将数据写入到语言级缓冲区中
2、调用系统调用
解释一个"奇怪的现象"
C语言的缓冲区,如果是向显示器文件中输出,刷新方案就是行刷新,如果是向普通文件中输出,刷新方案就是全刷新。
系统调用接口会直接将用户输入的数据写入到内核级缓冲区中,C语言级接口会先写到语言级缓冲区中再写到内核缓冲区中。
格式化输入输出
FILE类型是C语言提供的,就存在C语言级缓冲区。
stdin一般都有输入缓冲区,stdout一般都有输出缓冲区。
我们在使用printf函数时,是向显示器文件中做输出,但显示器文件属于字符设备文件,只认识字符,不能识别我们输入的非字符数据类型,此种情况,就是格式化输出的工作了。
格式化输出本质是将非字符类型转化为一个个的字符,然后拷贝至发送缓冲区中,然后由printf函数获取输出。
printf函数输出,实际上输出的都是字符。在printf函数内部,都是以字符来对待数据的,格式化输出会将全部的非字符类型转化为字符类型,拷贝到发送缓冲区中,格式化输出时,再将其拷贝至语言级缓冲区中即可。
格式化输入,实际上将用户输入的数据视作字符,保存在stdin输入缓冲区中,由格式化输入将一个个的字符转化为各种数据类型,再通过变量地址写入到变量中。
数据流动本质上就是拷贝数据,所有的文件接口本质上也是拷贝接口。
我们所学的C++中的cin、cout本质都是类,都存在缓冲区,我们将这种语言级别的缓冲区称作字节流,读写都是从字节流中获取。
相关文章:

Linux---文件(2)---文件描述符缓冲区(语言级)
目录 文件描述符 基础知识 文件描述符 对“Linux一切皆文件”的理解 文件描述符分配规则 缓冲区 刷新策略 存放位置 解释一个"奇怪的现象" 格式化输入输出 文件描述符 基础知识 在系统层面上,文件操作都是通过文件描述符来操作的。 程序在启…...

云计算实训39——Harbor仓库的使用、Docker-compose的编排、YAML文件
一、Harbor部署 1.验证python版本 [rootdocker2 ~]#python --version 2.安装pip [rootdocker2 ~]# yum -y install python2-pip #由于版本过低,需要对其进行一个升级 #更新pip [rootdocker2 ~]#pip install --upgrade pip 3.指定版本号 [rootdocker2 ~]# p…...

lambda表达式用法——C#学习笔记
“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。 实例如下: 代码如下: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.…...

【C++ Primer Plus习题】11.6
问题: 解答: main.cpp #include <iostream> #include "Stonewt.h" using namespace std; const int SIZE 6;int main() {Stonewt stone_arr[SIZE] { 253.6,Stonewt(8,0.35),Stonewt(23,0) };double input;Stonewt eleven Stonewt(11, 0.0);Stonewt max st…...
Redis八种数据结构简介
Redis数据结构 Redis新旧版本中一共出现过八种数据结构,分别是SDS、双向链表、压缩列表、整数集合、哈希表、跳表、quicklist、listpack。 SDS SDS是用于存储Redis中字符串的数据结构,Redis底层使用的语言是C语言,因此字符串也是C语言的字…...
数据治理策略:确保数据资产的安全与高效利用
数据治理策略:确保数据资产的安全与高效利用 在数字化时代,数据已成为企业最宝贵的资产之一。然而,随着数据量的爆炸性增长和数据来源的多样化,如何有效地管理和利用这些数据成为企业面临的重要挑战。数据治理策略的制定和执行&a…...

ts格式转mp4,四款亲测好用软件推荐!
在这个数字视频时代,我们经常会遇到各种视频格式兼容性问题,尤其是从网络下载的高清电影或电视剧集,很多时候都是以TS格式存储。然而,当我们想要在移动设备、社交媒体或视频编辑软件中播放、上传时,MP4格式因其广泛的兼…...

10、Django Admin修改标题
admin from django.contrib import admin from .models import Category, Origin, Hero, Villain # 添加以下代码 admin.site.site_header "系统管理" admin.site.site_title "管理员界面" admin.site.index_title "欢迎来到这里ÿ…...

ESRI ArcGIS Pro 3.1.5新功能及安装教程和下载
ESRI ArcGIS Pro 3.1.5 主要新功能包括: 改进的数据编辑和管理:支持更多数据格式和更精细的属性表操作。增强的空间分析工具:新增和优化空间分析工具,提高数据分析效率。更好的3D可视化:改进3D渲染性能,支…...

人工智能,语音识别也算一种人工智能。
现在挺晚了,还是没有去睡觉,自己在想什么呢,也不确定。 这是一篇用语音写的文章,先按自己的想法说出来,然后再适当修改,也许就是一个不错的文章。 看来以后就不需要打字了,语音识别度很高&#…...
Token和Refresh Token
获取令牌(Token) 和 刷新令牌(Refresh Token) 在认证和授权机制中有不同的使用场景和目的,二者主要的区别和为什么需要刷新令牌可以通过以下几点解释: 1. 获取令牌和刷新令牌的区别 获取令牌(Token&#x…...

STM32(一)简介
一、stm32简介 1.外设接口 通过程序配置外设来完成功能 2.系统结构 3.引脚定义 4.启动配置 5.最小系统电路...

接口测试工具:Postman详解
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、前言 在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性…...
Linux中全局变量配置,/etc/profile.d还是/etc/profile
全局环境变量可以放在 /etc/profile 或 /etc/profile.d/ 中,但两者的使用方式和目的有所不同: /etc/profile 作用: /etc/profile 是一个系统范围的启动脚本,在用户登录时执行。它主要用于设置全局环境变量和配置,适用于所有用户。…...

【java入门】关键字、标识符与变量初识
🚀 个人简介:某大型国企资深软件开发工程师,信息系统项目管理师、CSDN优质创作者、阿里云专家博主,华为云云享专家,分享前端后端相关技术与工作常见问题~ 💟 作 者:码喽的自我修养ǹ…...
Java常用类库
Java常用类库 1. **Java基础类库**1.1 **java.lang**1.2 **java.util**1.3 **java.io**1.4 **java.nio**1.5 **java.time** 2. **第三方类库**2.1 **Apache Commons**2.2 **Google Guava**2.3 **Jackson**2.4 **Lombok** 3. **Spring相关类库**4. **并发类库**4.1 **java.util.…...

2024年高教社杯数学建模国赛C题超详细解题思路分析
本次国赛预测题目难度,选题人数如下所示 难度评估 A:B:C 1.8:1.3:1 D:E1.5:1 选题人数 A:B:C 1:1.5:2.8 D:E0.5:1.2 C题一直以来都是竞赛难度最低、选题人数最多的一道本科生选题,近三年C题的选题人数一直都是总参赛队伍的一半左右,2023年…...

深度学习(七)-计算机视觉基础
计算机视觉 计算机视觉在广义上是和图像相关的技术总称。包括图像的采集获取,图 像的压缩编码,图像的存储和传输,图像的合成,三维图像重建,图像增强,图像修复,图像的分类和识别,目…...

机器人笛卡尔空间轨迹规划原理与MATLAB实现
机器人笛卡尔空间轨迹规划是指在给定的笛卡尔坐标系(通常是三维空间坐标系)中规划机器人的末端执行器(如抓手、焊枪等)的移动路径。这种规划方式直观且易于理解,因为它直接关联到任务空间中机器人的位置和姿态。下面将…...
数据结构:树与二叉树
1、树的基本概念 1.1树的定义 树是n个结点的有限集。 若n0,称为空树;若n>0称为非空树,非空树有且仅有一个称之为根的结点。 除根结点以外的其余结点可分成m个互不相交的有限集T1,T2,......Tm,每个有限集合本身又是一棵树,并…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...