【Linux系统化学习】文件描述符fd

目录

基础IO预备知识

C语言文件接口

"w"的方式打开,fputs写入

以"a"的方式打开,fputs写入

使用位图传参

系统调用操作文件

open的使用

 第一种形式

第二种形式

write()

文件描述符

文件描述符和进程的关系

默认的三个IO流和文件描述符的关系


基础IO预备知识

在之前的文章中我们提到过:文件 = 内容 + 属性

我们直接给出下面几条结论:

  • 对所有的文件的操作:a.对内容操作 b.对属性操作
  • 内容是数据,属性其实也是数据;因此储存文件必须储存内容和属性。
  • 我们想要访问一个文件,就必须先将这个文件打开。
  • 通过进程打开文件且一个进程可以打开多个文件。
  • 未被打开的文件存储在磁盘中,打开的文件存储在内存中。

我们知道文件默认是在磁盘中的,我们想要打开文件就必须访问磁盘;用户是没有权限访问磁盘的必须使用系统调用,通过操作系统将文件从磁盘加载到内存中进行操作。使用系统调用就要创建进程,因此用户是通过进程打开文件的,一个进程又可以打开很多个文件;打开的文件像内存中的进程一样,进程需要被管理,打开加载在内存中的文件也需要被管理。操作系统管理的方式——先描述在组织;像进程一样,一个文件被打开一定要现在内核中形成被打开的文件对象,然后再将这些文件对象使用某种数据结构串联起来即可。

在本篇文章中我们研究文件操作的本质是:进程和文件的关系


C语言文件接口

在之前C语言的文件操作中我们学习了一些相关C语言的文件操作包括以各种方式打开文件,关闭文件等等。这里我们只简单复习下以”w”和“a"的方式打开文件及使用fputs向文件中写入。

"w"的方式打开,fputs写入

  1 #include<stdio.h>2 int main()3 {4     FILE* fp = fopen("log.txt","w");5     if(fp)6     {7         perror("fopen");8     }9     fputs("aaaaaaaaaaaaaaaaaa",fp);                                                     10     fclose(fp);               11     return 0;                 12 }  

 

总结:以读("w")的方式打开文件,当文件不存在时候会在当前工作目录下创建新文件;但是以这个方式写入是从头开始覆盖式写入,相当于将之前文件的内容清空再写入。相当于Linux中的输入重定向。

以"a"的方式打开,fputs写入

  1 #include<stdio.h>2 int main()3 {4     FILE* fp = fopen("log.txt","a");5     if(fp)6     {7         perror("fopen");8     }9     fputs("ccccccccccccc",fp);                                                          12     fclose(fp);13     return 0;14 }

总结:以追加("a")的方式打开文件,会在文件末尾进行写入。相当于Linux下的追加重定符。

 


使用位图传参

在学习Linux的系统调用之前我们还要学习下使用位图传参。

对于我们的自定义函数来说,定义了几个参数在使用时候就要传几个实参;但是我们传递的实参非常多时,又对应函数参数的一个参数该怎么办?

将我们的参数按位与(|)形成一个新的参数,这个参数的每个比特位为代表一个参数; 对传入的参数进行位操作即可。

  1 #include <stdio.h>2 3 #define Print1 1      // 00014 #define Print2 (1<<1) // 00105 #define Print3 (1<<2) // 01006 #define Print4 (1<<3) // 10007 8 void Print(int flags)9 {10     if(flags&Print1) printf("hello 1\n");11     if(flags&Print2) printf("hello 2\n");12     if(flags&Print3) printf("hello 3\n");13     if(flags&Print4) printf("hello 4\n");14 }15 16 17 int main()18 {19     Print(Print1);20     Print(Print1|Print2);21     Print(Print1|Print2|Print3);22     Print(Print3|Print4);23     Print(Print4);24     return 0;25 } 

 

如上面的代码那样使用位图的思想解决多个实参对应一个实参进行传参操作。 


系统调用操作文件

上面我们提到操作系统是不相信我们用户的,用户直接对操作系统的文件操作不了;需要使用操作系统提供的系统接口——open、close。open系统调用代表打开文件,close代表关闭文件。

open的使用

open系统调用含有两种形式,第一种形式适用于打开存在的文件,当打开不存在时会造成文件的权限乱码;第二种形式适用于打开不存在的文件。此函数的返回值大于0代表打开成功打开文件,小于0代表打开失败。

参数说明

pathname:打开的文件名

flags:对文件进行各种操作对应数字的按位与(|),下面的几个参数为常用的操作对应数字的宏定义。

        O_WRONLY:只读

        O_CREAT:创建新文件

        O_TRUNC:覆盖式写入

        O_APPEND:追加式写入

mode:形成新文件的权限

 第一种形式

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>                                                                      6 7 int main()8 {9     int fb = open("vlog.txt",O_WRONLY|O_CREAT|O_TRUNC);10     if(fb<0)11     {12         perror("open");13         return 0;14     }15     close(fb);16 }

如上图所示:权限只有rwx,这里蹦出来一个T,显然乱码了。 

第二种形式

1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 7 int main()8 {9     int fb = open("vlog.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);                            10     if(fb<0)11     {12         perror("open");13         return 0;14     }15     close(fb);16 }

总结:通过第二种函数我们将创建的新文件的权限进行设置,但是系统中含有umask。设置的权限和文件的权限不一样,需要我们手动修改umask之后便可以相同。

write()

这个系统调用是用来对文件进行写入操作的;返回值我们会在以后的文章中介绍此处不用过多了解。

参数说明

  • fb:需要进行操作的文件描述符
  • buf:需要写入的字符串(这个字符串不用以’\0‘结尾,因为这个规定是C语言的不是文件系统的
  • count:写入字符串的长度的

写入的方式和打开时传入的参数有关。


文件描述符

使用系统调用open会返回一个整形,这个整形叫做文件描述符。并且使用系统调用write以这个整形为参数时会对文件写入,感觉好神秘,通过一个整数对系统文件操作。

一个进程可以打开多个文件,我们不妨打开好几个文件将每个文件的文件描述符打印出来。

 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 int main()8 {9     int fba = open("fba.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);10     int fbb = open("fbb.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);11     int fbc = open("fbc.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);12     int fbd = open("fbd.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);13     printf("%d\n",fba);14     printf("%d\n",fbb);15     printf("%d\n",fbc);16     printf("%d\n",fbd);                                                                 17     return 0;}

是从3开始的连续小整数,其实这三个整数是数组的下标

文件描述符和进程的关系

上面我们提到一个进程可以打开很多文件,操作系统为了方便管理这些文件会对每个文件编写相应的结构体即 struct file,但是操作系统不想让进程和每个文件对应的结构体耦合过大,因此对此进程打开的所有文件又组织起来创建一个结构体 struct files _struct,在此进程的PCB中含有一个 struct files_struct * files指向这个结构体;其中这个结构体中还有一个指针数组,从下标3开始数组中的每个元素为struct file * fd ,一一指向这个进程打开的文件。

结论:操作系统访问文件只认文件描述符。

默认的三个IO流和文件描述符的关系

刚开始学习Linux的时候就说过一个特别重要的结论:Linux下一切皆文件;当我们使用键盘、显示器编写C语言(包含其他编程语言)的时候,其实就是对键盘文件、显示器文件进行文件读写;当我们执行C语言的时候系统默认给我们打开三个流:stdin、stdout、stderr。这三个流分别对应我们的键盘、显示器、显示器;用于我们进行输入、输出,像scanf就是对键盘文件的读取、printf就是对显示器的写入。(stderr流会在后面的文章中介绍到)

这三个流对应的返回值是FILE*,和C语言对系统文件的各种函数的返回值一样。C语言可以对系统中的文件进行操作,必定封装了系统调用open、close。FILE用来保存打开文件的信息的,里面肯定封装了文件描述符(fd);因此我们可以使用C语言对系统文件进行操作。

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 int main()8 {9     printf("stdin->fd:%d\n ",stdin->_fileno );10     printf("stdout->fd:%d\n ",stdout->_fileno );11     printf("stderr->fd:%d\n ",stderr->_fileno );12     13     FILE* fp =fopen("vlog.txt","w");14     printf("fp->fd:%d \n",fp->_fileno);15     fclose(fp);                                                                         16           }


今天对Linux下文件描述符的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!! 

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

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

相关文章

C语言:函数递归

创作不易&#xff0c;给个三连吧&#xff01;&#xff01; 一、什么是递归 递归式一种解决问题的方法&#xff0c;在C语言中&#xff0c;递归就是自己调用自己。 递归的思想&#xff1a; 把⼀个⼤型复杂问题层层转化为⼀个与原问题相似&#xff0c;但规模较小的⼦问题来求解…

考研数据结构笔记(2)

线性表 线性表的定义线性表的基本操作lnitList(&L)DestroyList(&L)Listlnsert(&L,i,e)ListDelete(&L,i,&e)LocateElem(L,e)GetElem(L,i)Length(L)PrintList(L)Empty(L)Tips:引用值 小结 根据数据结构的三要素–逻辑结构、数据的运算、存储结构&#xff0c;…

嵌入式学习Day14 C语言 --- 位运算

位运算 注意&#xff1a;符号位也遵循这个规则 一、按位与(&) 运算规则&#xff1a;一假则假 int a 0x33;a & 0x55;0011 00110101 0101 &----------0001 0001 //0x11 二、按位或(|) 运算规则&#xff1a;一真则真 int a 0x33;a |0x55;0011 00110101 0101 |…

Asp .Net Core 集成 NLog

简介 NLog是一个基于.NET平台编写的日志记录类库&#xff0c;它可以在应用程序中添加跟踪调试代码&#xff0c;以便在开发、测试和生产环境中对程序进行监控和故障排除。NLog具有简单、灵活和易于配置的特点&#xff0c;支持在任何一种.NET语言中输出带有上下文的调试诊断信息…

Python 数据分析库之polars使用详解

概要 数据分析是现代应用程序和业务决策的关键组成部分。Python 作为一门强大的编程语言,拥有丰富的数据处理库和工具,其中之一就是 Polars。Polars 是一个现代化的数据操作和分析库,它提供了高性能的数据操作功能,支持链式方法调用,并且兼容 Pandas 和 Arrow 格式。本文…

微信小程序合集更更更之实现仿网易云播放动效

实现效果 写在最后&#x1f352; 源码&#xff0c;关注&#x1f365;苏苏的bug&#xff0c;&#x1f361;苏苏的github&#xff0c;&#x1f36a;苏苏的码云~

鸿蒙开发-UI-组件导航-Tabs

鸿蒙开发-UI-组件 鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 文章目录 一、基本概念 二、导航 1.底部导航 2.顶部导航 3.侧边导航 4.导航栏限制滑动 三、导航栏 1.固定导航栏 2.滚动导航栏 3…

写后台接口,前后台数据对接(vue+springboot)

一、怎么写接口&#xff1f;&#xff1f;&#xff1f; 1.Entity&#xff08;定义一堆属性之类的&#xff09; altins>getter和setter方法 2.Controller 3.Service&#xff08;查询出数据&#xff09; 调用了一个方法 4.Mapper 5.回到service&#xff08;返回数据&#x…

2024年微信公众号链接爬取

通过输入&#xff08;或文件导入&#xff09;公众号名称&#xff0c;即可爬取该公众号所有历史文章。 通过公众号官方网站调用API&#xff0c;打开开发者工具后发现有 打开后发现有搜索结果的fakeid&#xff0c;这是每个公众号的标识。 点击某公众号后出现 这是具体公众号文章…

Windows中如何使用 Anaconda 和 gempy地质建模

GemPy是一个免费开源的Python软件包&#xff0c;主要用于建立三维地质模型。以下是windows下GemPy的安装过程。 一、&#xff08;可选步骤&#xff09;N卡加速 如果使用的是英伟达的RTX显卡&#xff0c;可以去N卡官网下载cuda安装包以启用GPU加速。 首先检查显卡支持的CUDA版…

二层交换机配置以太网通道

实验大纲 二层聚合端口配置 1.构建网络拓扑结构图 2.修改交换机名字 3.创建聚合组进入聚合接口模式 4.将端口绑定到聚合端口&#xff08;接口模式&#xff09; 5.聚合接口下端口配置&#xff08;聚合接口模式) 6.具体配置 7.验证端口通道1的状态 8.配置ip 9.测试连通…

外汇天眼:欧洲证券和市场管理局(ESMA)撤销对迪拜商品清算公司的欧盟认可

欧洲证券与市场管理局&#xff08;ESMA&#xff09;宣布&#xff0c;欧洲监管机构&#xff08;EBA、EIOPA和ESMA - 即ESA的联合上诉委员会&#xff09;一致决定驳回迪拜商品清算公司&#xff08;DCCC&#xff09;对ESMA提起的上诉&#xff0c;并因此确认ESMA决定撤销其认可。DC…

分析网站架构:浏览器插件

一、Wappalyzer 1.1 介绍 Wappalyzer 是一款用于识别网站所使用技术栈的浏览器插件。它能够分析正在浏览的网页&#xff0c;检测出网站所使用的各种技术和框架&#xff0c;如内容管理系统&#xff08;CMS&#xff09;、JavaScript库、Web服务器等。用户只需安装 Wappalyzer 插…

春节放大招,阿里通义千问Qwen1.5开源发布

2月6日阿里发布了通义千问1.5版本&#xff0c;包含6个大小的模型&#xff0c;“Qwen” 指的是基础语言模型&#xff0c;而 “Qwen-Chat” 则指的是通过后训练技术如SFT&#xff08;有监督微调&#xff09;和RLHF&#xff08;强化学习人类反馈&#xff09;训练的聊天模型。 模型…

113.乐理基础-五线谱-五线谱的调号(二)

内容参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;五线谱的调号&#xff08;一&#xff09;-CSDN博客 调号一共有15个&#xff1a;如下图 上一个内容里写了&#xff0c;C、D、E、F、G、A、B这七个调号&#xff0c;如下图 然后所有调号的五线谱版本&#xff1a; 然后…

博客|基于Springboot的个人博客系统设计与实现(源码+数据库+文档)

个人博客系统目录 目录 基于Springboot的个人博客系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 &#xff08;1&#xff09;用户管理 &#xff08;2&#xff09;文章分类管理 &#xff08;3&#xff09;公告信息管理 &#xff08;4&#…

re:从0开始的CSS学习之路 5. 颜色单位

0. 写在前面 没想到在CSS里也要再次了解这些颜色单位&#xff0c;感觉回到了大二的数字图像处理&#xff0c;可惜现在已经大四了&#xff0c;感觉并没有学会什么AI的东西 1. 颜色单位 预定义颜色名&#xff1a;HTML和CSS规定了147种颜色名。例如&#xff1a;red yellow green …

Harbor介绍、整体架构和安装

Harbor介绍、整体架构和安装 文章目录 Harbor介绍、整体架构和安装1.Harbor介绍2.Harbor 整体架构3.安装Harbor3.1 主机初始化3.1.1 设置ip地址3.1.2 配置镜像源3.1.3 关闭防火墙3.1.4 禁用SELinux3.1.5 禁用swap3.1.6 设置时区 3.2 安装docker3.3 安装docker compose3.4 下载H…

kafka 文件存储机制

文章目录 1. 思考四个问题&#xff1a;1.1 topic中partition存储分布&#xff1a;1.2 partiton中文件存储方式&#xff1a;1.3 partiton中segment文件存储结构&#xff1a;1.4 在partition中如何通过offset查找message: 2. kafka日志存储参数配置 Topic是逻辑上的概念&#xff…

EMC学习笔记(二十二)降低EMI的PCB设计指南(二)

降低EMI的PCB设计指南&#xff08;二&#xff09; 1.电源和地概述2.电感量3.两层板和四层板4.单层和双层设计中的微控制器接地5.信号返回地6.模拟、数字信号与大功率电源7.模拟电源引脚和模拟参考电源8.四层板电源设计参考注意事项 tips&#xff1a;资料主要来自网络&#xff0…