Linux学习之C/C++文件操作底层调用及原理

前言:我们都知道,我们学习的C/C++是无法直接与底层硬件进行交互的,所有需要与底层硬件的交互都是通过操作系统作为中介完成的,那Linux到底是怎么做到的呢?接下来我们将揭开它神秘的面纱。

目录

一,操作系统如何管理文件

1)Linux之下一切皆文件

2)先描述,再组织

3)具体管理方法

二,C/C++读写文件的函数是如何完成的?

1)fwirte , fread ,fopen ,fclose

2)open,write,read,close

3)为什么要包装一层

三,重定项

1)重定项的使用

2)重定项的原理——dup2


一,操作系统如何管理文件

首先我们要明白操作系统是人类发明出来的,那么它的结构创造一定要符合我们人类的逻辑,对于一大堆文件我们该如何管理呢?

1)Linux之下一切皆文件

这是什么意思呢?难道Linux管理的键盘,鼠标,显示器也是文件吗?当然它们实际上并不是文件,那为什么所有人默认这个准则呢?因为Linux提供了一个统一的视角来看待所有被管理的东西,在Linux看来所有被他管理的东西都是文件,这样子有什么好处呢?举个例子

假设一个新校长要高效管理一个学校,这里面什么人都有,有教务处处长,教授,执教老师,助教,学生,保安,宿管阿姨。它们之间的各种差异这么大,我们想要直接全部管理无疑难度很大,那怎么办?我们不妨把他们全部看作被管理者,把他们在学校的身份的关键信息全部总结起来,记录成一张表格,表格记录他们的职位,年龄,性别,学号,电话号码等关键信息,当我们需要找他们办事的时候通过这张纸联系他们,并对他们进行操作。我们对他们操作转需要借助这个表格,表格给我们提供了一个统一的视角来管理各种完全不同身份的人,我们可以无视他们的差距,这无疑提高了我们的效率。

在上面的例子里面,各种身份的人就是各种硬件,校长就算操作系统,表格就是我们说Linux之下一切皆文件的文件,但实际上他们的特性可能天差地别,但是对于我们操作系统来说并不重要,反正我们通过管理文件的方式来管理你们。

补充:上面的例子里面的表格在Linux里面其实就算struct结构体,因为Linux是C写的,那时候还没出现C++类之类的概念,也就是操作系统是通过各种struct结构体管理硬件等。

2)先描述,再组织

这也是我们人类认识新事物的方法和过程,假如我们从来没有见过螃蟹,我们第一次看见,我们首先肯定会感到奇怪,然后我们第一件事肯定先用我们学习的词汇来试图描述它,比如红色的,甲壳,很多条腿,只有我们把他们的特征描述起来,我们脑海里才会对它有一个概念。那我们为什么要组织呢?假如因为我们对螃蟹这种从来没见的东西而产生了好奇,我们绝对对它进行研究。这时候我们有了很多只螃蟹,我们对它进行管理,仅仅知道它们是螃蟹已经明显不够了,我们需要对它们进行编号或者起名字之类的,这就算组织,我们为什么要组织呢?肯定是为了方便管理啊。这条包括上面的概念是Linux及其重要的,希望大家理解。

3)具体管理方法

首先我们把各种硬件之间我们需要特性全部进行总结,形成一个struct结构体,在Linux里面这个结构体采用的是数组的形式,数组里面是文件指针,0号下标指向的是标准输入,1号下标指向的是标准输出,2号下标指向的是标准错误我们看下图来理解。

二,C/C++读写文件的函数是如何完成的?

1)fwirte , fread ,fopen ,fclose

我们都知道fwirte , fread ,fopen是语言层面的函数,它们是无法直接调用系统底层文件的,只能通过操作系统的帮助,所有我们可以推断fwrite,fread,open里面绝对包装了系统接口,fwrite调用的是wirte的接口,fread是调用系统的read接口,fopen则是调用open接口,fclose自然是调用了close。

2)open,write,read,close

在上面我们说了,操作系统对“文件”管理是通过struct结构体数组,那我们打开一个文件只需要找到这个文件的下标和这个数组的地址,这个数组的地址我们不需要提供,是操作系统管理的,我们拿到数组的下标就可以管理“文件”。没错在open,write,read函数中这个下标是一个很重要的参数。

int open(const char *pathname, int flags, mode_t mode);
//mode是设定的文件权限,后面不做讲解,不理解可以看我往期权限博客

上面的是open函数,第一个参数pathname是要创建或者打开的文件,第二个参数flag是打开的方式,打开方式要细讲。

O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
上面这些打开方式参数是被define 定义过的,所有是这样子,最后会被宏替换的。它们其实是一些数字,最后会通过位图来决定打开的方式。什么是位图?
假如我们只有一个char类型的数,但是我们需要这个char类型代表一个甚至多个状态,我们该怎么办?
我们可以利用字节的下一级单位是比特,比特位有八位,每一个位代表一个状态,这样子char就可以表示八个状态。接下来举个例子
define O_RDONLY 1
define O_WRONLY 2
define O_RDWR 4
define O_CREAT 8
define O_APPEND 16
void test(int a){
if(a&1){
cout<<"只读打开"<<endl;
}
if(a&2){
cout<<"只写打开"<<endl;
}
if(a&4){
cout<<"读写打开"<<endl;
}
if(a&8){
cout<<"若文件不存在就打开"<<endl;
}
if(a&16){
cout<<"追加写"<<endl;
}
}
int main(){
test(O_RDWR|O_CREAT|O_APPEND);//可读可写并追加写
return 0;
}

很多人这时候就有疑问了,我用不同的数字大小表示不同的状态不也行吗?

但是这个就产生了一个问题,我们写出来是要考虑用户的,如果我们采取数字的,甚至给数字再定义一个英文名字,英文名字的起名要蕴含多重意思自然就变长了,可读性就差了,综上所述这样子没有位图这样子直观和方便。

返回值则是“文件”数组的下标

ssize_t write(int fd, const void *buf, size_t count);

fd是文件描述符的下标,也就是“文件”数组的下标,将buf里面的内容写入文件,count则是写入的大小。如果返回值=-1则write出现了错误,一般来说是写入内容的大小。(sizt_t是无符号整形,-1被转换后就是无符号整形能存储的最大值)

ssize_t read(int fd, void *buf, size_t count);

同样fd是“文件”数组下标,读取出来的内容会存储再buf里面,count是读取的大小。返回值是实际读取的大小,如果读取失败返回-1.

int close(int fd);

关闭文件只需要“文件”数组下标,返回值为0代表关闭成功,为-1代表关闭失败。

补充:为什么一定要关闭文件,首先打开一个文件需要加载到内存,创建对于的struct结构体,如果打开很多文件而无法关闭对于计算机不是一个很大的负担吗?造成了效率和资源的浪费

3)为什么要包装一层

跨平台:每个平台的底层系统接口是不一样的,如果不包装,当代码换一个平台跑,我们就需要掌握一个平台的系统调用接口

用户体验:使用系统调用的成本很高,要理解一定的底层才能准确把握,而系统调用可以减少学习成本

三,重定项

1)重定项的使用

在编程中,重定向(Redirection)是一种将程序的输入或输出从一个默认的设备或位置转移到另一个设备或位置的操作。这种机制允许程序员将程序的输出结果保存到文件中,或者将程序的输出结果发送到网络或其他设备上。在C语言中,重定向的概念主要是通过修改标准输入输出流来实现的。

a>b//将a要进行的打印之类的程序运行结果操作到b里面输出 //会将b里面的内容清空
a<b//a将以b程序运行的结果代替键盘等默认设备作为输入   //只支持一行
a>>b// 不会清空原本b的内容,会追加输出
a<<b// 允许定义一个多行的输入,将其作为a的输入
2)重定项的原理——dup2

dup2函数可以改变文件指针的指向,我们将原本指向输入输出默认设备的文件指针改为我们想要的文件就可以了,想要实现这个操作很简单,通过Linux里面文件操作依赖与“文件”下标,我们只需要通过下标就能找到要改变的文件和被改变的文件,然后改变默认文件指针即可。

我们接下来看看dup2函数的参数

int dup2(int oldfd, int newfd);

oldfd和newfd文件描述符也即“文件数组”下标,会将原本指向newfd的文件转而指向oldfd,每对newfd进行操作就相当于对oldfd操作。如果操作成功返回newfd,失败则返回-1

接下来看个例子,将4号文件与默认输出重定项

int flag=dup2(4,2);
if(flag==-1){
cout<<"文件重定项失败"<<endl;
}
else{
cout<<"成功将默认输出与4号文件重定项"<<endl;
cout<<"666";//将会输入到4号文件
}

完结撒花

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/474690.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全平台7合一万能DIY小程序源码系统 带完整的安装代码包以及安装搭建教程

在当下的小程序市场中&#xff0c;虽然已有众多开发工具和服务平台&#xff0c;但很多用户仍然面临着开发难度大、功能不齐全、定制性差等问题。小编给大家分享一款全平台7合一万能DIY小程序源码系统。该系统旨在解决用户在小程序开发过程中的痛点&#xff0c;提供一站式的小程…

WordPress Plugin NotificationX插件 SQL注入漏洞复现(CVE-2024-1698)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。 0x02 漏洞概述 WordPress plugin NotificationX是一个应用插件。2.8.2版本及之前 存在安全漏洞,该…

飞腾+FPGA+AI电力行业智能数据采集与分析网闸解决方案

行业痛点: 安全物联网闸在监控平台中的具体作用&#xff1a;35KV变电站是煤矿的动力核心&#xff0c;采矿人员上下井、煤炭提升输送、矿井通风等核心设备均依靠变电站提供电源。监控中心及时掌握变电站的运行状态对煤矿的安全生产非常重要。如若外部通过监控网络来控制变电站会…

Hyper Casual FX

此包包含&#xff1a; 五彩纸屑-2种 灰尘 - 1 种 闪光灯 - 8 种类型 闪耀 - 3 种类型 闪亮 - 1 种 水-2种 它可以在没有任何设置的情况下开箱即用 下载&#xff1a;​​Unity资源商店链接资源下载链接 效果图&#xff1a;

C语言编程实现文件加解密

目录 1. OpenSSL导入程序项目2. 编写加解密程序1. 程序代码2. 命令行传参3. 文件的读写4. 加解密中的细节 1. OpenSSL导入程序项目 下载并安装OpenSSL&#xff0c;下载地址打开VS&#xff0c;创建控制台应用 记得配置文件位置 右键项目名称&#xff0c;找到属性&#xff0c;并…

MySQL面试复习记录

一、mysql文章地址汇总 以下均为蓝云飘飘的文章&#xff1a; MySQL数据库&#xff08;一&#xff09;_写出sql语句,列出薪资比‘王海涛’的薪资高的所有员工,显示姓名,薪资-CSDN博客 MySQL数据库&#xff08;二&#xff09;_sql里的性别是什么代表-CSDN博客 ★★★★★ My…

(基础)AJAX概念和axios使用、URL、请求方法和数据提交、HTTP协议、接口、form-serialize插件

AJAX概念和axios使用 AJAX概念 AJAX就是使用XMLHttpRequest对象与服务器通信&#xff0c;它可以使用JSON、XML、HTML和text文本等格式发送和接收数据&#xff0c;AJAX最吸引人的就是它的异步特性&#xff0c;也就是说它可以在不重新刷新页面的情况下与服务器通信&#xff0c;…

Effect:由渲染本身引起的副作用

React 组件中的两种逻辑类型&#xff1a; 渲染逻辑代码 位于组件的顶层&#xff0c;接收 props 和 state&#xff0c;进行转换&#xff0c;返回屏幕上看到的 JSX&#xff0c;只计算不做其他任何事情&#xff1b;事件处理程序 嵌套在组件内部的函数&#xff0c;由特定的用户操作…

【timm笔记1】

1. 安装timm pip install timm2. 打印模型 import timm# 获取并打印所有可用的预训练模型名称 available_models = timm.list_models() # 打印出所有的模型 print(available_models)# 打印所有包含"resnet"字符的模型名称 resnet_models = timm.list_models(*resne…

2024年03月 Discourse 3.3.0.beta1 版本的更新

在这个版本的更新中 Discourse 完成了 Ember 5 版本的升级和更新。 Ember.js是一个用于创建 web 应用的 开源JavaScript MVC 框架&#xff0c;采用基于字符串的Handlebars 模板&#xff0c;支持双向绑定、观察者模式、计算属性&#xff08;依赖其他属性动态变化&#xff09;、…

Oracle数据库冷备份(实例)

冷备份 1、 select file#,name,bytes/1024/1024 mb from v$datafile; 2 、缩减 便于copy alter database datafile 2 resize 100m;show parameter spfilecreate undo tablespace u2 datafile /u01oracle/oradata/qq/u2.dbf size 2m autoextend on; //建新的 alter system…

为prj添加kconfig支持

为prj添加kconfig支持 KConfig是一个配置系统&#xff0c;它允许用户和开发者通过配置文件/配置界面选择需要的编译选项。目前大量的项目都有用到该配置系统&#xff08;linux、u-boot、rt-thread、esp-idf/adf、zephyr等&#xff09;&#xff0c;可以说是一个项目的构建系统中…

代码随想录阅读笔记-字符串【实现 strStr()】

题目 实现 strStr() 函数。 给定一个 haystack 字符串和一个 needle 字符串&#xff0c;在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在&#xff0c;则返回 -1。 示例 1: 输入: haystack "hello", needle "ll" 输出:…

可应用于工业控制器,新能源充电桩等众多涉及RS232通讯的产品的国产芯片——D3232,性价比高,交货周期短

D3232芯片主要用于工控主板、工业控制器、程序烧录下载器、仿真器、新能源充电桩等众多涉及RS232通讯的产品。 二、基本特性 D3232芯片由两个线路驱动器、两个线路接收器和双电荷泵电路组成&#xff0c;具有HBM>15kV、CDM>2kV的ESD保护能力&#xff0c;并且接收端输入电压…

javaweb遇到的servlet问题,jar包问题

有时候会遇到这种问题&#xff0c;有的地方会报红 这是因为这个找不到这个包&#xff0c;这个项目缺少jar包 在tomcat9之前还不是Jakarta这个名字&#xff0c;我的运行环境与服务器是jdk17与tomcat10 解决方法&#xff1a; 在项目结构中&#xff0c;找到模块&#xff0c;再…

HTTP Error 400. The request hostname is invalid.

异常信息 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Bad Request</TITLE> <META HTTP-EQUIV"Content-Type" Content"text/html;…

数据库系统概论-第15章 内存数据库管理系统

用内存的数据库&#xff0c;场景接触较少&#xff0c;不细看。 15.1 概述 15.2 内存数据库的发展历程 15.3 内存数据库的特性 15.4 内存数据库的关键技术 15.5 小结

实测国内AI大模型问答效果

随着ChatGPT热度的攀升&#xff0c;越来越多的公司也相继推出了自己的AI大模型。按照github工程awesome-LLMs-In-China所列举的&#xff0c;现如今国内AI大模型已达243个&#xff0c;比较著名的有文心一言、通义千问等。各大应用也开始内置AI玩法&#xff0c;如抖音的AI特效。下…

深度学习-2.9梯度不稳定和Glorot条件

梯度不稳定和Glorot条件 一、梯度消失和梯度爆炸 对于神经网络这个复杂系统来说&#xff0c;在模型训练过程中&#xff0c;一个最基础、同时也最常见的问题&#xff0c;就是梯度消失和梯度爆炸。 我们知道&#xff0c;神经网络在进行反向传播的过程中&#xff0c;各参数层的梯…

工大智信智能听诊智慧医疗的创新

智能听诊器&#xff0c;智慧医疗的新突破 工大智信智能听诊器是一款结合了先进技术和医疗专业知识的创新产品。它以其独特的优势&#xff0c;为医疗行业带来了前所未有的突破和变革。 传统听诊器依赖于医生的主观判断和经验&#xff0c;而工大智信智能听诊器采用了先进的传感技…