Linux文件系统调用接口文件描述符的理解

news2024/11/23 23:06:43

🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
在这里插入图片描述

文章目录

  • 一、对系统调用进行封装的理由
  • 二、文件的系统调用接口
    • ① open
      • open的选项--位图
      • open的权限
      • 程序中设置umask权限掩码
    • ②close
    • ③write
    • ④read
  • 三、文件描述符
    • 默认打开的三个流
    • 什么是FILE
    • 文件的分类
    • 文件打开所对应的file结构体
    • 文件为什么一定要在内存中打开
    • 进程和文件的对应关系
    • open&&fwrite所做的事
  • 四、文件描述符的分配规则

一、对系统调用进行封装的理由

①.系统调用对于我们来说是比较难的,因为我们需要系统要去干什么,需要传哪些参数,所以学习成本太高,所以语言层次,对系统调用接口进行了封装,导致了不同的语言,有不同的语言级别的文件访问接口

封装出来的接口是有多个的,但是文件类的系统调用接口,在Linux上,只有一套

②跨平台
如果语言不提供对文件的系统封装接口,那么所有的访问文件操作,必须使用操作系统提供的系统调用接口,一旦这样,那编写的代码在其他平台就运行不了了,而我如果进行封装,不同的平台进行不同的封装,但是提供给用户的接口都是一样的,这样,就实现了跨平台

比如说把每个平台的代码都实现一遍,采用条件编译动态裁剪的方式,在哪个平台就用哪个平台的接口,这样就跨平台了,所以项目中也推荐使用语言级别的文件接口,就是因为跨平台

二、文件的系统调用接口

fopen -> open
fclose -> close
fread -> read
fwrite -> write

① open

#include <sys/types.h>
#include <sys/stst.h>
#include <fcntl.h>
int open(const char*pathname,int flags,mode_t mode);
//第一个参数是路径,第二个是选项,第三个是设置权限

open返回的东西叫做文件描述符

对于三个参数
第一个就不用说了,是打开文件的路径
第二个是选项,以下三个接口中必须要有一个,其次还有O_APPEND,O_TRUNC,C_CREAT等
在这里插入图片描述
第三个是设置文件权限,比如0666

比如打开文件log.txt

int fd/*文件描述符*/ = open("log.txt",O_WRONLY|O_TRUNC|O_CREAT,0666)
//三个选项分别表示 写,覆盖,创建

那open的选项为什么是这样传?我们来了解一下位图

open的选项–位图

#define ONE 0x1 //0001
#define TWO 0x2 //0010
#define THREE 0x4//0100

void show(int flags)
{
	if(flags & ONE)//说明有没有ONE
		...
	if(flags & TWO)
		...
	if(flags & THREE)
		...
}
int main()
{
	show(ONE);
	show(TWO);
	show(ONE | TWO);
	show(ONE | TWO | THREE);
	return 0;
}

open的权限

不加权限时生成的文件 的权限时随机的
因为open有都和读和写两种方式,所以他的权限也就只能是默认值(随机)

int fd = open("log.txt",O_RDONLY);//读方式打开

而写的时候有可能需要创建文件,当创建文件的时候,就需要带上权限

比如0666,一个八进制数,0666时默认的普通文件的权限(第一位是我们不关心的)
代表的权限是 -rx-rx-rx-,因为会被umask权限掩码给修饰掉
具体的请看Linux权限详解

程序中设置umask权限掩码

#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t umask);
//mode_t是被typedef过的,特就是一个unsigned int类型的数
umask(0);//这样即可

②close

#include<unistd.h>
int close(int fd);
//用法:
int fd = open("log.txt",O_WRONLY|O_TRUNC|O_CREAT,0666);
close(fd);//关闭文件描述符

③write

//用法:
const char* buffer="hello write";
write(fd,buffer,strlen(buffer));
//表示写入多大的一个char*的数据

④read

#include <unistd.h>
ssize_t/*无符号整数*/ read(int fd,void *buf,size_t count);
//表示从文件中读到buffer

三、文件描述符

文件描述符(file descriptor)

当我们可以打开多个文件时
在这里插入图片描述在这里插入图片描述
可以发现,第一个文件打开的时候就是3了,那0 1 2呢?

默认打开的三个流

C/C++会默认打开三个流:
①stdin 对应文件描述符为 0 标准输入流
②stdout 对应文件描述符为 1 标准输出流
①stderr 对应文件描述符为 2 标准错误流

他们都是FILE类型的,那说明是FILE

什么是FILE

FILE*叫做文件指针,又叫做文件句柄
在这里插入图片描述
FILE是一个C标准库提供的结构体
C的文件类函数一定要第哦啊用系统接口(不是所有的库函数都要调用系统第哦啊用),对于系统,是只认识文件描述符fd的,所以FILE中必定也封装了fd,通过查看源码可以发现,FILE中有成员 _fileno,也就是fd

可以通过下面的方式打引出来看

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

文件的分类

文件被分为两类:
1、被打开的文件(因为要加载到内存中,所以也叫做内存文件)
对硬件的任何操作,都会经过操作系统,操作系统去调用驱动
2、没有打开的文件,也叫做磁盘文件
文件 = 内容+属性

文件打开所对应的file结构体

对文件的操作都是要CPU参与的,所以想访问文件,要先加载到内存,那系统中就存在这大量的被打开的文件,OS要想办法把这些打开的文件也组织起来

//文件对应的file结构体
struct file
{
	struct file*next;
	struct file*prev;
	//...
	//包含了一个被打开文件的几乎所有的内容
	//不仅仅是包含属性,而是各种信息
}

文件为什么一定要在内存中打开

因为打开文件就是为了读写,读写文件是需要通过代码来访问的,通过代码访问前提就是代码要被执行,根据冯诺依曼体系,执行代码的机构一定是CPU,访问数据必须先加载到内存,没有l加载到内存,CPU也就访问不到,软件也跑不起来,所以文件必须先在内存中打开。
冯诺依曼

进程和文件的对应关系

进程的PCB中有一个fs指针,指向的是files结构体,files结构体中就有fd_array,称作文件映射表或者文件描述符表
在这里插入图片描述
fd本质就是一个数组的下标

open&&fwrite所做的事

open是系统调用接口,创建文件对象file插入list,用hashtable(指针数组),叫做fd_array(文件描述符表),来记录文件对象的指针,把这个结构体对象指针的fd_array下标返回。(这个fd_array的首地址保存在files_struct当中,files_struct的地址保存在PCB当中)

fwrite是函数调用,通过FILE*中的_fileno(也就是fd),调用write这个OS提供的系统调用接口,找到进程的task_strcut(PCB),找到fs指针,找到files_struct,找到fd_array文件描述符表,找到file,就可以写入了

四、文件描述符的分配规则

int main()
{
	close(0);//关闭0号文件描述符
	int fd1 = open("log1.txt",O_WRONLY|O_CREAT|O_TURNC,0666);
	printf("fd1:%d\n",fd1);//0
	close(2);//关闭2号文件描述符
	int fd2 = open("log2.txt",O_WRONLY|O_CREAT|O_TURNC,0666);
	printf("fd2:%d\n",fd2);//2
	int fd3 = open("log3.txt",O_WRONLY|O_CREAT|O_TURNC,0666);
	printf("fd3:%d\n",fd3);//3
	return 0;
}

从上面的代码以及结果中可以看出:
fd的分配规则:是分配最小的,没有被占用的文件描述符

在这里插入图片描述

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

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

相关文章

字节输入流【InputStream】(读文件)

字节输入流【InputStream】 java.io.InputStream 抽象类是表示字节输入流的所有类的超类&#xff0c;可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。 public void close(): 关闭此输入流并释放与此流相关联的任何系统资源。 public abstract int read(): …

Telegraf

Telegraf是什么&#xff1f; Telegraf 是 InfluxData 公司开源的一款十分流行的指标采集软件&#xff0c;可以从数据库、系统和物联网传感器收集和发送度量和事件&#xff0c;它用Go编写&#xff0c;编译成一个没有外部依赖的二进制文件–需要非常少的内存&#xff0c;相…

数仓建模理论(一)

学习目录一、关系建模与维度建模二、维度表和事实表&#xff08;重点&#xff09;三、事实表类型四、维度模型分类一、关系建模与维度建模 &#xff08;1&#xff09;关系建模 关系建模将复杂的数据抽象为两个概念——实体和关系&#xff0c;并使用规范化的方式表示出来。关系…

【计算机毕业设计】73.房屋租赁系统求租合同源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;房屋租赁系统当然也不能排除在外。房屋租赁系统是以实际…

Mybatis源码解析(八):插件机制

Mybatis源码系列文章 手写源码&#xff08;了解源码整体流程及重要组件&#xff09; Mybatis源码解析(一)&#xff1a;环境搭建 Mybatis源码解析(二)&#xff1a;全局配置文件的解析 Mybatis源码解析(三)&#xff1a;映射配置文件的解析 Mybatis源码解析(四)&#xff1a;s…

flex布局列表页(一行内容比较多,长度比较长)

一、Flex 布局是什么&#xff1f; Flex 是 Flexible Box 的缩写&#xff0c;意为"弹性布局"&#xff0c;用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。 二、基本概念 采用 Flex 布局的元素&#xff0c;称为 Flex 容器&#xff08;flex co…

Java开发必须掌握的运维知识 (九)-- Docker容器监控信息可视化仪表:Grafana

一、Grafana 是用来干什么的&#xff1f; Grafana 是一个监控仪表系统&#xff0c;它是由 Grafana Labs 公司开源的的一个系统监测 (System Monitoring) 工具。它可以大大帮助你简化监控的复杂度&#xff0c;你只需要提供你需要监控的数据&#xff0c;它就可以帮你生成各种可视…

jdk11新特性——JShell交互性工具

目录一、jshell概述二、jshell位置三、jshell示例3.1、示例一&#xff08;声明变量并赋值&#xff09;3.2、示例二&#xff08;输出打印内容&#xff09;3.3、示例三&#xff08;帮助命令&#xff09;一、jshell概述 java9引入了jshell这个交互性工具&#xff0c;让Java也可以…

BUUCTF Misc 黑客帝国 [MRCTF2020]你能看懂音符吗 [HBNIS2018]caesar [HBNIS2018]低个头

黑客帝国 下载文件 一长串16进制&#xff0c;复制到在线16进制转文本 很明显是一个RAR文件&#xff0c;使用脚本将16进制转换成文件 import binasciihex_data这里填十六进制数据 outopen(res.rar,wb) out.write(binascii.unhexlify(hex_data)) out.close() 需要密码&#xff…

[附源码]计算机毕业设计校园疫情防范管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

# 智慧社区管理系统-核心业务管理-03投诉信息

一 后端 1:entity package com.woniu.community.entity;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;Data AllArgsConstructor NoArgsConstructor public class Complaint {private int id;private int comId;private String c…

多功能跑步机外观及结构设计

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1背景及意义 1 1.2国内外发展情况 2 1.3研究主要内容 3 第2章 多功能跑步机结构设计 5 2.1 传动机构设计 5 2.1.1 设计步骤及参数选择 5 2.1.2多楔带带轮结构和尺寸选择 8 2.2 电动机类型与参数的选择 10 2.2.1类型功率选择 10 2.2.2…

连连看核心算法与基本思想(附全部项目代码链接与代码详细注释)

文章目录0.说明1.基本要求2.思路分析(加入核心代码)2.1 游戏初始化局面2.2 两点是否可连2.3 游戏是否结束2.4 判断死锁3.注意事项与全部代码0.说明 对于数据结构和算法&#xff0c;我并不是很精通&#xff08;真的很一般&#xff09;&#xff0c;因此在这里只是做一个自己的简…

以太网 TCP协议(数据交互过程、窗口机制)

2.7.1 以太网 TCP协议&#xff08;数据交互过程、窗口机制&#xff09; 环境介绍&#xff1a; 1、客户端访问FTP服务器进行下载文件&#xff0c;由于FTP是基于TCP协议进行工作的&#xff0c;所以客户端在访问FTP服务器时必然会进行建立TCP连接。 2、通过在交换机上对任意端口进…

Bootstrap5 网格系统

Bootstrap 提供了一套响应式、移动设备优先的流式网格系统&#xff0c;随着屏幕或视口&#xff08;viewport&#xff09;尺寸的增加&#xff0c;系统会自动分为最多 12 列。 我们也可以根据自己的需要&#xff0c;定义列数&#xff1a; 111111111111444486612 Bootstrap 5 的…

Java项目:ssm客户关系管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 客户关系管理系统主要功能包括&#xff1a; 系统管理&#xff1a; 用户管理 日志管理 权限管理 角色管理 系统信息 客户管理 我的客户 联系跟进…

音视频学习(十三)——flv详解

简介 全称FLASHVIDEO&#xff0c;是一种新的视频格式&#xff0c;主要的特点是文件小、加载速度快。 结构 flv的结构相对简单&#xff0c;可以通过下图来初步了解其组成&#xff1a; flv flv header(9字节) flv bodyflv header Signature(3字节) Version(1字节) Flags(…

rocketmq消息过滤

1、目的 消费者订阅了某个主题后&#xff0c;Apache RocketMQ 会将该主题中的所有消息投递给消费者。若消费者只需要关注部分消息&#xff0c;可通过设置过滤条件在 Apache RocketMQ 服务端进行过滤&#xff0c;只获取到需要关注的消息子集&#xff0c;避免接收到大量无效的消…

51单片机学习笔记5 流水灯实现及蜂鸣器控制

51单片机学习笔记5 流水灯实现及蜂鸣器控制一、流水灯1. 硬件电路2. 代码实现&#xff08;1&#xff09; 点亮一个LED的基本操作&#xff08;2&#xff09; 使用算术左移实现流水灯&#xff08;3&#xff09; 使用库文件左移函数二、蜂鸣器1. 蜂鸣器介绍2. 硬件电路原理图ULN20…

唯愿山城无恙-烟火寻常--爱摸鱼的美工(五)

-----------作者&#xff1a;天涯小Y 非常时期的非常生活&#xff01; 今天是承上启下的一天 无论好坏&#xff0c;本月都收官了 洗去一身的疲惫 大脑放空&#xff0c;搓澡 热衷搓澡的程度&#xff0c;简直不像南方人 收拾一下,迎接新的开始 原本一年之中&#xff0c;我最爱几…