Linux之文件fd

news2024/9/24 15:16:44

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶     C++进阶​    ​​​​算法

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

目录

 一.文件内容的回顾

二.提炼一下对文件的理解

 三.理解文件

 3.1 open

 3.2 close

3.3write

四.文件描述符fd

4.1fd

4.2理解一切皆文件

4.3大致了解一下打开文件和写文件的过程

4.4 文件描述符0,1,2的证明

五.封装

5.1在Linux层面上c语言对底层的封装

5.2c语言为什么这样做

六 再次理解一下一切接文件 


 一.文件内容的回顾

        在c语言中我们学过文件的操作,在这里我先回顾一下文件的操作,代码如下:

#include<stdio.h>
#include<string.h>

int main()
{
    FILE *fp=fopen("log.txt","w");
    if(fp==NULL)
    {
        perror("fopen");
        return 1;
    }
    const char*str="hello file";
    fprintf(fp,"%s",str);
    fclose(fp);

    return 0;
}

我们查看log.txt的内容 

 

我们打开的方式为’w‘,当文件不存在时创建一个文件然后写入,当文件存在时清空文件的内容然后写入,当然还存在另一种写入方式'a',追加。我们在linux中可以使用重定向来创建文件

> a.txt

可以创建一个空文件

我们可以输入

echo hello> a.txt

 将hello输入到文件a.txt

每一次输入都是会清空文件的内容然后输入。

当然也存在一种和a方式一样的,

echo file>>a.txt

 可以追加到a.txt文件中

二.提炼一下对文件的理解

        文件=内容+属性。打开文件本质就是进程打开文件,文件没有打开的时候存在哪里?文件没有打开的时候存在磁盘中;一个进程可以打开多个文件吗? 可以。系统中可以存在多个进程吗?可以。很多情况下的,操作系统中一定存在的大量被打开的文件,操作系统需要对这些打开的文件进行管理,先描述在组织,所以操作系统中一定存在一个类似于PCB的结构

 三.理解文件

        文件在磁盘中,磁盘时外设,对文件的操作就是对外设进行操作,用户不可以直接对外设进行操作,操作系统可以对外设进行操作,我们想要写文件就需要操作系统进行操作,所以一定存在一个接口(例如我们c/c++中fprintf/fopen等)可以让操作系统进行文件的操作。

 3.1 open

我们查看守则

man 2 open

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

        const char *pathname是指文件的文件名或者文件路径,int flags这个参数是使用位图的形式传入的,mode_t mode是指文件的权限。我们看代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int fp=open("log.txt",O_CREAT|O_WRONLY,0666);
    return 0;
}

我们可以看到可以出现一个log.txt文件: 

对于flags这个参数它类似于

#define A 1
#define B 1<<1
#define C 1<<2

int main()
{
    int a=A|B|C;
}

对于这个文件的权限为什么是644而不是666呢?这个和掩码有关,具体不做解释。 

 3.2 close

        我们查看守则

man 2 close

关闭需要文件描述符fd进行关闭。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fp=open("log.txt",O_CREAT|O_WRONLY,0666);
    if(fp<0)
    {
        perror("open");
        return 1;
    }

    close(fp);
    return 0;
}

3.3write

        我们看手则

man 2 write

 第一个参数int fd是指文件描述符, 第二个参数const void *buf是输入的内容,第二个参数 size_t count是输入内容的长度。我们看代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fp=open("log.txt",O_CREAT|O_WRONLY,0666);
    if(fp<0)
    {
        perror("open");
        return 1;
    }
    const char*str="hello file";
    write(fp,str,strlen(str));
    
    close(fp);
    return 0;
}

我们查看log.txt文件的内容

四.文件描述符fd

4.1fd

        我们先看一下库中open的返回值

我们看下面代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fpa=open("loga.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    printf("fpa : %d\n",fpa);

    int fpb=open("logb.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    printf("fpb : %d\n",fpb);

    int fpc=open("logc.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    printf("fpc : %d\n",fpc);

    int fpd=open("logd.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    printf("fpd : %d\n",fpd);
    
    return 0;
}

代码运行的结果为:

fpa为3,fpb为4,fpc为5,fpd为6 ,文件描述符没有0,1,2,其中0是标准输入流,1是标准输出流,2是标准错误流

这三个的返回类型为FILE。

一个进程可以对应多个文件,操作系统需要知道文件的状态,需要对打开的文件进行管理,先描述在组织,我们可以看下面的图片:

 文件描述符的fd的本质是什么?内核进程:文件映射关系的数组下标。open在干什么?创建file,开辟文件缓冲区的空间,加载文件数据,查看文件的描述符表,file地址填入对应的表和下标,返回下标。

4.2理解一切皆文件

        键盘,显示器,鼠标等都是硬件,但是一切皆文件,所以硬件在操作系统也是以文件存储,既然是文件,那么就有一个struct_file ,看下图:

在操作系统中每一个struct_file都有一些函数指针来进行硬件的访问,这是类的多态级的技术。

4.3大致了解一下打开文件和写文件的过程

       我们在log.txt文件中进行写入 helloworld,我们看下面的图片:

 先打开文件,返回一个文件描述符,通过这个文件描述符进行写文件,然后在进程strict_task中找到这个文件描述符表,然后通过文件描述符表下表为文件描述符,根据这个的地址找到文件的属性和文件的内容然后写入文件,操作系统再定时将内容刷新到磁盘中。

4.4 文件描述符0,1,2的证明

        在stdin.stdout,stderr对应的结构体中有一个变量_fileno来存储文件描述符,我们看下面的代码代码:

#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    printf("stdin : %d\n",stdin->_fileno);
    printf("stdout : %d\n",stdout->_fileno);
    printf("stderr : %d\n",stderr->_fileno);
    
    return 0;
}

运行结果如下: 

 

同样当我们创建一个文件时,它也会封装文件描述符,看下面代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    printf("stdin : %d\n",stdin->_fileno);
    printf("stdout : %d\n",stdout->_fileno);
    printf("stderr : %d\n",stderr->_fileno);
    
    FILE* fp=fopen("log.txt","w");
    if(fp<0)
    {
        perror("feopn");
        return 1 ;
    }
    printf("fp : %d\n",fp->_fileno);
    return 0;
}

结果如下:

 

五.封装

5.1在Linux层面上c语言对底层的封装

        直接看代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fp1=open("log.txt",O_CREAT|O_WRONLY|O_TRUNC,0666);
    if(fp1<0) 
    {
        perror("fopen");
        return 1;
    }
    return 0;
}

在这段代码中文件的打开和c语言中的下面代码效果一样:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    FILE* fp=fopen("log.txt","w");
    if(fp==NULL)
    {
        perror("fopen");
        return 1;
    }
    return 0;
}

所以这里是对底层的封装,,同样追加写也有对应的封装:

  int fp=open("log.txt",O_CREAT|O_WRONLY|O_APPEND,0666);

5.2c语言为什么这样做

        对底层进行封装的一个重要原因就是语言不具有跨平台性,当我们在windos平台写一段代码,在Linux中就有可能不能运行,这就是因为语言奴具有跨平台性,所以它就会出一个接口,例如我们的fopen/fwrite等都是对底层进行封装,看下面图片可以大致了解一下其中的实现

 

六 再次理解一下一切接文件 

        Linux中一切皆文件,那么显示器也是文件,既然是文件那我们就可以通过代码在显示器上写一些内容,我们输入指令:

ls /dev/pts

 当我们再开一个终端,再次输入这个指令可以看到:

我们在第一个终端上运行代码:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fd=open("/dev/pts/1",O_WRONLY|O_APPEND);
    if(fd<0)
    {
        perror("open");
        return 1;
    }
    const char * str="hello linux\n";
    while(1)
    {
      write(fd,str,strlen(str));
      sleep(1);
    }

    close(fd);
    return 0;
}

我们在另一个终端上可以看到:

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

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

相关文章

狂飙的鸭子,哪里跑!安定的力量(深度好文)——早读(逆天打工人爬取热门微信文章解读)

容我也来卖个小聪明&#xff0c;学习洞见&#xff0c;深度好文 引言Python 代码第一篇 洞见 安定的力量&#xff08;深度好文&#xff09;第二篇结尾 引言 老刺激了 骑着自行车在路上狂摇 刚刚好赶上打卡时间 早上一切很平和 听书 吃绿豆饼茶 做早餐 准点一天的排泄 老天估计…

快手矩阵系统:一键发布,多平台自动文案生成

在当今信息爆炸的时代&#xff0c;自媒体平台的崛起为用户提供了广阔的展示舞台。然而&#xff0c;对于内容创作者来说&#xff0c;如何高效地在多个平台上发布内容&#xff0c;同时保持文案的吸引力和独特性&#xff0c;一直是一个不小的挑战。幸运的是&#xff0c;随着技术的…

基于xinference推理引擎 + glm4-9b-chat模型的本地化部署探索

【备注】从langchain-chatchat v0.3开始&#xff0c;所有的模型配置&#xff0c;均由推理模型&#xff08;如&#xff1a;xinference &#xff09;进行加载和启动。 xinference 中配置并启动模型 1、查看支持的模型 xinference registrations --model-type LLM 2、执行tran…

相约 TDBC丨拓数派将亮相 2024 可信数据库发展大会!

2024 年&#xff0c;我国数据库正处于蓬勃发展期和关键应用期&#xff0c;在人工智能迅猛发展和数据要素市场化建设的浪潮下&#xff0c;为进一步推动全球数据库产业进步&#xff0c;2024 可信数据库发展大会将于 2024 年 7 月 16-17 日&#xff0c;在北京朝阳悠唐皇冠假日酒店…

计网ip层重要面经总结

文章目录 127.0.0.1, localhost, 0.0.0.0有什么不同?ipv6还需要NAT吗&#xff1f;DNS查询服务器的基本流程浏览器输入一个URL到显示器显示的过程PING是怎么工作的&#xff1f;ipv4和ipv6究竟有哪些区别&#xff1f;什么是跨域&#xff0c;什么情况下会发生跨域问题&#xff1f…

前端面试题42(MVVM与MVC区别)

MVVM&#xff08;Model-View-ViewModel&#xff09;和MVC&#xff08;Model-View-Controller&#xff09;都是软件架构模式&#xff0c;主要用于简化应用程序开发中的复杂性&#xff0c;尤其是在用户界面和数据管理方面。尽管它们有一些相似之处&#xff0c;但在设计理念和实施…

GD32MCU最小系统构成条件

大家是否有这个疑惑&#xff1a;大学课程学习51的时候&#xff0c;老师告诉我们51的最小系统构成&#xff1f;那么进入32位单片机时代&#xff0c;gd32最小系统构成又是怎么样的呢&#xff1f; 1.供电电路 需要确保供电的电压电流稳定&#xff0c;以东方红开发版为例&#xff…

基于深度学习的行人重识别

目录 1、基于表征学习的ReID方法 2、基于度量学习的ReID方法 &#xff08;1&#xff09;对比损失(Contrastive loss) &#xff08;2&#xff09;三元组损失(Triplet loss) &#xff08;3&#xff09; 四元组损失(Quadruplet loss) &#xff08;4&#xff09;难样本采样三元…

React+TS前台项目实战(三十)-- 首页构建之基于react-query和性能hook实现全页面数据渲染

文章目录 前言一、首页源码详细注释说明技术分析1. 页面功能分析2. 代码详细注释 二、效果展示总结 前言 前三篇文章详细介绍了首页的响应式布局&#xff0c;采用关注点分离进行模块拆解&#xff0c;现在只需按需引入模块&#xff0c;页面更加简洁&#xff0c;代码的维护性得到…

【鸿蒙学习笔记】关系型数据库概述

目录标题 关系型数据库的运行机制样例代码共通方法 DBUtilsIndex 代码效果 关系型数据库的运行机制 1、 关系型数据库对应用提供通用的操作接口&#xff0c;底层使用SQLite作为持久化存储引擎&#xff0c;支持SQLite具有的数据库特性&#xff0c;包括但不限于事务、索引、视图…

MongoDB教程(一):Linux系统安装mongoDB详细教程

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、Ubuntu…

【单片机毕业设计选题24059】-太阳能嵌入式智能充电系统研究

系统功能: 系统由太阳能电池板提供电源&#xff0c; 系统上电后显示“欢迎使用智能充电系统请稍后”&#xff0c; 两秒钟后进入主页面显示。 第一行显示太阳能电池板输入的电压值 第二行显示系统输出的电压值 第三行显示采集到的太阳能电池板温度 第四行显示设置的太阳能…

【Linux杂货铺】1.环境变量

1.环境变量基本概念 环境变量&#xff08; environment variables &#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数。如&#xff1a;我们在编写 C / C &#xff0b;代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪…

信创会不会烂尾

最近又有不少人开始忽悠信创概念了&#xff0c;感觉这又是部分人发财的噱头&#xff0c;集体资源浪费的开始! 我们软件业几代人和全世界的差距能短时间内追上?人家会本着友谊第一比赛第二的原则&#xff0c;站在原地等你追&#xff1f;然后和你一起相扶到美好的未来&#xff1…

华为HCIP Datacom H12-821 卷37

1.多选题 下面关于Network- Summary-LSA 描述正确的是 A、Network- Summary-LSA中的Metric被设置成从该ABR到达目的网段的开销值 B、Network- Sumary-LSA中的Net mask 被设置成目的网段的网络掩码 C、Network- Summary-LSA 是由ASBR产生的 D、Network- Summary-LSA 中的Li…

年度必看|2024全球工业网络市场份额预测报告

重点摘要 每年&#xff0c;HMS Networks 都会对工业网络市场进行全面分析&#xff0c;旨在估计工厂自动化中按类型和协议划分的新连接节点的分布情况。最新研究表明&#xff0c;工业网络市场继续扩张&#xff0c;预计 2024 年将增长 7%。值得注意的是&#xff0c;工业以太网仍然…

python 实验八 数据分析与展示

一、实验目的 掌握掌握matplotlib库中pyplot模块的使用。 二、实验环境 Window10&#xff08;x64&#xff09;&#xff0c;Python 3.8&#xff08;x64&#xff09;&#xff0c;PyCharm Community Edition 2020.3.2&#xff08;x64&#xff09; 三、实验内容 现有列表hight…

WAV 和 FLAC 哪个音质好?常见音频格式又如何转换?

音频文件的格式种类繁多&#xff0c;每种格式都有其独特的优势和应用场景。其中&#xff0c;WAV 和 FLAC 作为两种常见的无损音频格式&#xff0c;备受音频发烧友和专业人士的青睐。它们不仅能够保留原始录音的全部细节&#xff0c;还为听众提供了近乎 CD 品质的听觉体验。然而…

文字转语音免费工具有哪些?嘎嘎好使的配音工具推荐

每天刷视频看多了大家随手创作的各种生活小段子&#xff0c;自己不免也心痒痒地想玩上一把&#xff0c;可奈何却搞不懂各种旁白配音怎么弄。 好在经过一番摸索之后&#xff0c;可算是被我整明白免费文字转语音该怎么操作了&#xff01;接下来就把我搜集到的4款宝藏配音神器整理…

Windows 怎么删除D盘?多种方法详解!

有关Windows电脑的文件整理&#xff0c;文章详细介绍了怎么删除D盘的多种方法&#xff0c;释放不必要的空间。 “我最近在整理电脑文件的时候遇到一个问题&#xff0c;我想请教一下大家。我的Windows电脑上有一个D盘&#xff0c;里面存放了一些不需要的文件&#xff0c;我想彻…