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

news2024/12/24 10:18:05

        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.coloradmin.cn/o/825123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

51单片机学习--DS1302可调时钟

之前学习过用定时器做的时钟&#xff0c;但是那样不仅误差大还费CPU&#xff0c;接下来利用DS1302时钟模块做一个可调实时时钟 这一次直接编写DS1302模块&#xff0c;首先要在DS1392.c 中根据下面的模块原理图进行位声明&#xff1a; sbit DS1302_SCLK P3^6; sbit DS1302_IO …

05 Ubuntu下安装.deb安装包方式安装vscode,snap安装Jetbrains产品等常用软件

使用deb包安装类型 deb包指的其实就是debian系统&#xff0c;ubuntu系统是基于debian系统的发行版。 一般我们会到需要的软件官网下载deb安装包&#xff0c;然后你既可以采用使用“软件安装”打开的方法来进行安装&#xff0c;也可以使用命令行进行安装。我推荐后者&#xff…

电脑更新win10黑屏解决方法

电脑更新win10黑屏解决方法 电脑黑屏出现原因解决步骤 彻底解决 电脑黑屏 出现原因 系统未更新成功就关机&#xff0c;导致系统出故障无法关机 解决步骤 首先长安电源键10s关机 按电源键开机&#xff0c;出现logo时按F8进入安全模式。 进入自动修复环境后&#xff0c;单击…

快速排序——“数据结构与算法”

各位CSDN的uu们好呀&#xff0c;今天又是小雅兰的数据结构与算法专栏啦&#xff0c;下面&#xff0c;就让我们进入快速排序的世界吧&#xff01;&#xff01;&#xff01; 快速排序 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&…

工序委外PR审批后,不允许按工单自动更新PR交期

工序委外PR审批后&#xff0c;不允许按工单自动更新PR交期 工序委外PR审批后&#xff0c;更改工单结束日期&#xff0c;PR的交期还是会按工单重新更新交货日期&#xff1f; 检查配置&#xff1a; 1.生产模块集成的配置没有找到这么细的配置点 2.PR审批标识调整也没有效果 没找…

webrtc的回声消除延迟时间估算

叫回声消除的延迟时间估算不太合理&#xff0c;这里核心就是估算调用webrtc的条件边界&#xff0c;都知道webrtc回声消除的生效的前提就是一定要拿到远端声音的信息&#xff0c;然后拿近端声音和远端声音对齐&#xff0c;从近端声音中&#xff0c;结合远端声音模拟出远端声音在…

MySQL安装 找不到 MSVCP100.dll

安装mysql5.6.51时&#xff0c;出现由于找不到 MSVCP100.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。 这应该是缺少VS运行库文件导致的&#xff0c;运行库就是支持大部分程序运行的基础&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编…

Toolformer :让AI学会使用工具

paper: 《Toolformer: Language Models Can Teach Themselves to Use Tools 》 核心思想&#xff0c; 1. Sampling API Calls &#xff1a;设计设计prompt,让模型生成含API调用的文本&#xff08;如图3&#xff09;&#xff0c;只保留K个概率最高的API调用 2. Executing API …

nvm安装和切换node版本

1、nvm list查看已安装的node版本 2、查看当前使用的npm和node版本 3、安装某版本的node 4、 切换node版本

一行命令删除tag为<none>的镜像

sudo docker images | grep none | awk {print $3;} | xargs sudo docker rmi

理解APP开发的法规和合规性问题

随着移动应用程序的快速普及&#xff0c;越来越多的用户选择使用这些应用程序。但它们也会带来一些问题&#xff0c;其中许多是由于应用程序开发过程中存在的法规和合规性问题。用户需要了解这些问题&#xff0c;以及如何解决它们。 APP开发是一个不断变化的领域&#xff0c;其…

我的创作纪念日——256天

机缘 最开始我写博客没有什么特别的原因&#xff0c;主要是因为以下几点&#xff1a; 练习自己的语言组织能力 记录自己学习生活中学到的知识 为和我同一个学习阶段的朋友提供帮助 事实上最开始我根本不指望我的博客有多少人看&#xff0c;主要是想找一个好的保存 Markdown 笔…

穷举深搜暴搜回溯剪枝(2)

一)电话号码的字母组合 17. 电话号码的字母组合 - 力扣&#xff08;LeetCode&#xff09; 1)画出决策树:只是需要对最终的决策树做一个深度优先遍历 把图画出来&#xff0c;知道每一层在干什么&#xff0c;代码就能写出来了 2)定义全局变量: 1)定义一个哈希表来处理数字和字符串…

【freespace】YOLOP: You Only Look Once for Panoptic Driving Perception论文解读

目录 Abstract 摘要 1、简介 2、 相关工作 2.1. 交通目标检测 2.2. 可驾驶区域分割 2.3. 车道检测 2.4. 多任务的方法 3. 方法 3.1. 编码器 3.1.1 骨干 3.1.2 脖子 3.2. 解码器 3.2.1 探测头 3.2.2 可驾驶区域分段头&车道线分段头 3.3. 损失函数 3.4. 训练模…

Windows同时安装两个版本的JDK并随时切换,以JDK6和JDK8为例,并解决相关存在的问题(亲测有效)

Windows同时安装两个版本的JDK并随时切换&#xff0c;以JDK6和JDK8为例&#xff0c;并解决相关存在的问题&#xff08;亲测有效&#xff09; 1.下载不同版本JDK 这里给出JDK6和JDK的百度网盘地址&#xff0c;具体安装过程&#xff0c;傻瓜式安装即可。 链接&#xff1a;http…

华为OD机试真题 JavaScript 实现【机器人活动区域】【2023Q1 200分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、JavaScript算法源码六、效果展示1、输入2、输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试&am…

EXCEL,多条件查询数字/文本内容的4种方法

目录 1 问题&#xff1a;如何根据多条件查询到想要的内容 2 方法总结 2.1 方法1&#xff1a; sumif() 和sumifs() 适合查找符合条件的多个数值之和 2.2 方法2&#xff1a;使用lookup(1,0/((区域1条件1)*(区域2条件2)*....),结果查询区域) 2.3 方法3&#xff1a;使用 ind…

rknn模型在rv1126开发板上跑

在前面&#xff0c;已经将 onnx模型转为 rknn模型。 yolov5 onnx模型 转为 rknn模型_爱钓鱼的歪猴的博客-CSDN博客 这里探讨的是&#xff1a;rknn模型在rv1126开发板上运行 目录 1、rknn模型在PC端进行推理测试&#xff0c;评估模型精度 2、模型预编译 3、rknn模型部署到r…

【LeetCode】根据二叉树创建字符串

根据二叉树创建字符串 题目描述算法分析编程代码 链接: 根据二叉树创建字符串 题目描述 算法分析 当单纯的按照前序遍历输出后&#xff0c;我们只要对&#xff08;&#xff09;进行一些修改就好 编程代码 /*** Definition for a binary tree node.* struct TreeNode {* …