[Linux]基础IO详解(系统文件I/O接口、文件描述符、理解重定向)

        hello,大家好,这里是bang___bang_ ,今天和大家谈谈Linux中的基础IO,包含内容有对应的系统文件I/O接口,文件描述符,理解重定向。

  

目录

1️⃣初识文件

2️⃣ 系统文件I/O接口

🍙open

🍙write

🍙read

🍙close

3️⃣文件描述符

🍙0&1&2

🍙内核中文件描述符的探究

🍙分配规则

4️⃣重定向

🍙重定向现象 

🍙重定向的本质

🍙dup2系统调用


1️⃣初识文件

        文件=内容+属性(属性也是数据)

        文件的所有操作:a.对内容    b.对属性

        文件在磁盘(硬件)上放着,我们访问文件,先写代码->编译->exe->运行->访问文件。

        本质上是 进程 在访问文件。

Linux下一切皆文件。曾经我们理解的文件就是磁盘上的那些普通文件能read,write。

        在C语言中,我们对显示器有方法:printf->这是write(output);键盘:scanf->这是read(input)。也就是说我们的显示器和键盘也是文件。

        站在系统的角度来说:我们的程序要加载到内存,键盘相当于把我们的数据输交给内存(input),而内存把读取到的数据刷新到文件或者显示器当中(output)。

系统角度:能够被input读取,或者能够被output写出的设备就叫做文件!

2️⃣ 系统文件I/O接口

        在C语言中,文件操作接口有fopen,fwrite,fprintf,fclose等等,实际上这些接口都是封装了系统I/O接口。

🍙open

pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项
参数 :
         O_RDONLY: 只读打开
         O_WRONLY: 只写打开
         O_RDWR : 读,写打开
        O_RDONLY  O_WRONLY  O_RDWR 这三个常量,必须指定一个且只能指定一个
         O_CREAT : 若文件不存在,则创建它。需要使用 mode 选项,来指明新文件的访问权限
         O_APPEND: 追加写
        O_TRUNC: 清空文件
mode: 为新建文件设置权限

问题:如何实现flags传入多个参数选项呢?

答:采用位图的思想,flags的参数实际上是一个int类型的数,参数之间进行|运算,就能实现传入多个参数的效果。

源码定义

🌰O_WRONLY | O_CREAT 

模拟结果

检测是否有当前状态,只需要使用flag&状态的值。

0110 0101 & 0000 0001 = 0000 0001 有O_WRONLY状态

0110 0101 & 0110 0100 = 0110 0100 有O_CREAT状态

open函数图中我框选了返回值为一个文件描述符,在下面讲解。

🌰简单使用open

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<assert.h>int main()
{int fd=open("log.txt",O_WRONLY | O_CREAT,0666);assert(fd!=-1);printf("open sucess! fd:%d\n",fd);return 0;    
}

权限解释

🍙write

 功能:把缓冲区buf的前count字节写入与文件描述符fd关联的文件中。它返回实际写入的字节数。

🌰测试write

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<assert.h>
#include<string.h>
int main()
{int fd=open("log.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);assert(fd!=-1);printf("open sucess! fd:%d\n",fd);const char* buf="This is a test\n";write(fd,buf,strlen(buf));return 0;    
}

🍙read

功能:从与文件描述符fd相关联的文件中读取count个字节的数据。并把它放入到数据区buf中。

🌰测试read,读取上面write写的内容

int main()
{int fd=open("log.txt",O_RDONLY);assert(fd!=-1);printf("open sucess! fd:%d\n",fd);char res[64];read(fd,res,sizeof(res));printf("res:%s",res);return 0;    
}

🍙close

 

功能:将文件描述符fd相关联的文件关闭。

🌰close操作演示

int main()
{int fd=open("log.txt",O_RDONLY);assert(fd!=-1);printf("open sucess! fd:%d\n",fd);close(fd);return 0;    
}

3️⃣文件描述符

🍙0&1&2

🌰fd的显示问题:

int main()
{int fd1=open("log1.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);int fd2=open("log2.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);int fd3=open("log3.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);int fd4=open("log4.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);assert(fd1!=-1);assert(fd2!=-1);assert(fd3!=-1);assert(fd4!=-1);printf("open sucess! fd1:%d\n",fd1);printf("open sucess! fd2:%d\n",fd2);printf("open sucess! fd3:%d\n",fd3);printf("open sucess! fd4:%d\n",fd4);close(fd1);close(fd2);close(fd3);close(fd4);return 0;    
}

问题:为什么fd是从3开始? 

答:实际上C/C++程序默认会打开三个文件流:标准输入stdin(0),标准输出stdout(1),标准错误stderr(2)

0,1,2一般对应的物理设备是:键盘,显示器,显示器。

🍙内核中文件描述符的探究

在上面我们可以发现文件描述符fd就是一个小整数,那么在内核中文件描述符究竟是什么呢?

内核结构
        当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行 open 系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表 files_struct, 该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上, 文件描述符就是该数组的下标 。所以,只要拿着文件描述符,就可以找到对应的文件。
抽象结构图

🍙分配规则

在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

🌰验证分配规则,关闭文件0,进行分配。

int main()
{close(0);int fd=open("log1.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);assert(fd!=-1);printf("open sucess! fd:%d\n",fd);close(fd);return 0;    
}

问题:如果关闭文件描述符1,为什么没有输出显示。

答:文件描述符1对应显示器,关闭后自然就不会有内容显示到显示器了,但是也没有显示到文件log.txt中。

4️⃣重定向

🍙重定向现象 

问题:上面例子中内容没有显示到显示器和文件log.txt中,那么内容实际上在哪个地方?

答:在文件的缓冲区中

那是不是意味着我们刷新缓冲区就可以将内容显示出来?

int main()
{close(1);int fd=open("log.txt",O_WRONLY | O_CREAT| O_TRUNC,0666);assert(fd!=-1);printf("open sucess! fd:%d\n",fd);fflush(stdout);//刷新缓冲区close(fd);return 0;    
}

刷新后成功输出,内容本来应该输出到显示屏,但是现在输出到了log.txt这实际上就是输出重定向!!!(O_CREAT创建文件,O_TRUNC刷新文件,实现C语言中的w模式;O_APPEND追加内容,实现C语言中的a模式)

🍙重定向的本质

重定向的本质,其实是在OS内部,更改fd对应的内容的指向!!

🍙dup2系统调用

在重定向中,我们通常不使用close关闭fd,再重定向,而是直接使用系统调用dup2来重定向。 

将oldfd的内容给newfd,即newfd对应内容指向oldfd

🌰dup2系统调用测试

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<assert.h>
#include<unistd.h>int main()
{int fd=open("log.txt",O_WRONLY | O_CREAT| O_TRUNC,0666);assert(fd!=-1);dup2(fd,1);printf("open sucess! fd:%d\n",fd);close(fd);return 0;    
}
dup2实现重定向

文末结语,本文讲解Linux的基础IO,包含内容:初识文件,系统文件I/O接口open、read、write、close,文件描述符的详细讲解以及文件描述符的分配规则,重定向现象的演示及重定向的本质讲解,实现重定向的系统调用dup2。如有需要,希望能有所帮助!!!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8.12常见的锁策略

1.悲观锁和乐观锁 悲观锁:预测场景中,非常容易出现锁冲突. 乐观锁:预测场景中,不太会出现锁冲突. 2.重量级锁和轻量级锁(和1有关联) 重量级锁:加锁开销比较大. 轻量级锁:加锁开销比较小. 开销:时间和占用系统资源. 3.自旋锁和挂起等待锁 自旋锁:轻量级锁的一种实现.在用…

SolidWorks 3D Interconnect介绍

目前市面上有的三维设计软件有很多&#xff0c;如UG、Pro/E、CATIA等&#xff0c;而且每个三维设计软件都会生成自己文件格式。由于产品设计的原因&#xff0c;我们避免不了的会需要去使用不同三维设计软件的文件&#xff0c;这对于工程师来说其实是一件比较麻烦的事。 为什么…

使用隧道HTTP时如何解决网站验证码的问题?

使用代理时&#xff0c;有时候会遇到网站验证码的问题。验证码是为了防止机器人访问或恶意行为而设置的一种验证机制。当使用代理时&#xff0c;由于请求的源IP地址被更改&#xff0c;可能会触发网站的验证码机制。以下是解决网站验证码问题的几种方法&#xff1a; 1. 使用高匿…

一篇文章教会你一个优秀的程序员如何维护好自己的电脑

程序员如何维护好自己的电脑 1. 程序员的电脑种类都有哪些2. 硬件如何维护2.1 开关机问题2.2 Windows更新问题2.3 笔记本充电和电池问题2.4 笔记本清灰问题 3. 系统及软件维护3.1 杀毒软件和垃圾清理问题3.2 磁盘分盘问题3.3 浏览器和搜索引擎的选择3.4 系统备份和PE盘的使用 总…

VUE框架:vue2转vue3全面细节总结(2)导航守卫

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人_python人工智能视觉&#xff08;opencv&#xff09;从入门到实战,前端,微信小程序-CSDN博客 最新的uniapp毕业设计专栏也放在下方了&#xff1a; https://blog.csdn.net/lbcy…

Dockerfile构建mysql

使用dockerfile构建mysql详细教学加案例 Dockerfile 文件 # 使用官方5.6版本&#xff0c;latest为默认版本 FROM mysql:5.6 #复制my.cof至容器内 ADD my.cnf /etc/mysql/my.cof #设置环境变量 密码 ENV MYSQL_ROOT_PASSWORD123456my.cof 文件 [mysqld] character-set-server…

捕捉时刻:将PDF文件中的图像提取为个性化的瑰宝(从pdf提取图像)

应用场景&#xff1a; 该功能的用途是从PDF文件中提取图像。这在以下情况下可能会很有用&#xff1a; 图片提取和转换&#xff1a;可能需要将PDF文件中的图像提取出来&#xff0c;并保存为单独的图像文件&#xff0c;以便在其他应用程序中使用或进行进一步处理。例如&#xff…

nginx的优化和防盗链 重要!!!

实验一、隐藏版本号 要把nginx的版本号隐藏起来&#xff0c;防止恶意攻击 方法一&#xff1a;修改配置文件 在http模块中加入一个命令 server_token off&#xff1b; 过程&#xff1a; 备份&#xff0c;改配置文件一定要备份 修改配置文件 在http模块中添加 server_tokens …

展示Streamlit文本魔力(六):从头顶到脚尖

文章目录 1 前言✨2 st.markdown - 引入丰富的Markdown文本3 st.title - 引入引人注目的大标题4 st.header - 引入简洁的小标题5 st.subheader - 添加次级标题6 st.caption - 添加解释性文字7 st.code - 显示代码块8 st.text - 显示文本9 st.latex - 显示LaTeX公式10 st.divide…

Spring Cloud Alibaba (一)

1 微服务介绍 1.1 系统架构演变 随着互联网的发展&#xff0c;网站应用的规模也在不断的扩大&#xff0c;进而导致系统架构也在不断的进行变化。 从互联网早起到现在&#xff0c;系统架构大体经历了下面几个过程: 单体应用架构--->垂直应用架构--->分布 式架构--->S…

OpenMMLab MMDetectionV3.1.0-SAM(环境安装、模型测试、训练以及模型后处理工具)

OpenMMLab Playground 概况 当前通用目标检测的研究方向正在朝着大型多模态模型发展。除了图像输入之外&#xff0c;最近的研究成果还结合了文本模式来提高性能。添加文本模态后&#xff0c;通用检测算法的一些非常好的属性开始出现&#xff0c;例如&#xff1a; 可以利用大量…

【敏捷开发】测试驱动开发(TDD)

测试驱动开发&#xff08;Test-Driven Development&#xff0c;简称TDD&#xff09;是敏捷开发模式中的一项核心实践和技术&#xff0c;也是一种设计方法论。TDD有别于以往的“先编码&#xff0c;后测试”的开发模式&#xff0c;要求在设计与编码之前&#xff0c;先编写测试脚本…