Linux 文件接口和文件管理

news2024/11/14 15:36:30

目录

一、回顾c语言文件操作

二、系统调用的文件操作

系统调用文件接口

open:

close:

write:

代码测试:

​编辑

​编辑

read:

语言和系统函数间的关系:

flags的实现思路

三、OS内文件的管理

语言角度理解文件描述符

代码测试

进程角度理解文件描述符

文件打开的存储方式

代码测试

把硬件当文件开看待


一、回顾c语言文件操作

创建一个文件是在磁盘中创建的在没有写入时,它的大小是0,但这个文件任然占据了磁盘空间。文件=属性+内容。文件需要属性来描述它的大小、修改时间、权限等,占据磁盘空间的就是文件的属性。

我们在使用c语言的fopen打开文件会返回一个FILE的结构体指针,在语言角度上这个FILE就是这个文件,我们通过对FILE的操作达到对文件的管理。

fopen有三种重要的打开方式:

如果忘了这些文件的操作可以看一下我前面的博客:CSDN

对于打开文件无论是vim打开,还是执行代码打开,本质上都是进程在打开文件

二、系统调用的文件操作

文件是再硬盘上的,对硬件的管理只能由OS完成,我们使用OS必须通过OS提供的系统调用。

显然fopen的实现肯定是使用了系统调用接口,我们打开文件也可以使用系统调用接口。

系统调用文件接口

open:

打开文件

参数介绍:

pathname:要打开或创建的目标文件(和fopen打开文件所传第一个参数一样)

flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags(fopen那些w的不同打开方式,就是使用是flags不同的值完成的)。

flags参数:

  • O_RDONLY: 只读打开
  • O_WRONLY: 只写打开
  • O_RDWR : 读,写打开
  • 上面这三个常量,必须指定一个且只能指定一个
  • O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
  • O_APPEND: 追加写

mode:创建文件时需要mode来设置文件的权限,不需要创建文件就不需要mode。

返回值:成功,返回文件描述符,失败返回-1。

close:

关闭文件,传入文件描述符关闭对应的文件。

write:

输出函数

参数介绍:

fd:文件描述符

buf:需要输出的对象

const:输出对象的空间大小

代码测试:

使用上面这些函数达到和使用fopen打开一个不存在的文件,并写入一些内容的效果:

int main()
{
  int fp = open("test1.txt",O_WRONLY | O_CREAT);
  const char* message = "hello file\n";
  write(fp,message,strlen(message));
  close(fp);
  return 0;
}

传字符串大小时不要把'\0'也传进去,最好用strlen拿到大小。

文件是创建出来了,但它的权限确实两个x一个T?这也就无法读文件。这是因为没有使用带mode参数的open,mode是设置文件权限,没有mode创建出来的文件的权限介绍一堆乱码。

现在文件就可以被打开了,但仔细看test1.txt的权限就会发现和我们设置的权限是不一样的。这是因为umask它会改变文件的权限,在c语言中也可以设置当前程序的umask。

umask是系统函数,不需要管它的返回值,当前程序设置完umask,这个umask的值就只会在当前进程中使用,不会改变bash的umask。

int main()
{
  umask(0000);
  int fp = open("test1.txt",O_WRONLY | O_CREAT,0666);
  const char* message = "hello file\n";
  write(fp,message,strlen(message));
  close(fp);
  return 0;
}

read:

输入函数,读文件。

它的参数和使用方法跟write是一样的,不过是从给文件数据,变成了拿文件数据。

语言和系统函数间的关系:

通过上面的使用就能感觉出来,c语言文件类的函数是封装了系统文件的函数,这有两个好处:

1、使用上变的更简单了,学习成本得到了降低。

2、Linux有自己的系统调用函数,window也有自己的调用函数,可能实现思路是一样的,但参数、命名和一些小功能上是会存在差异的。c语言(各个语言都是)编写库的时就会将各个系统之间的文件函数(不限于文件函数),单独做处理,封装成统一的函数让我们使用,语言这时就有了跨平台性,我们在不同系统下编写代码就不需要重新学习不同的文件函数了。

flags的实现思路

flags是让文件以不同的方式打开,每种方式就有开和关两种状态,这里是使用了一个整形,整形的每一个二进制位都对应的是不同的方式(不是32位都使用了,状态也没那么多),通过判断当前位上是否为1,决定执行这一位的功能是否执行。

实现一段简单的代码来完成上面描述的功能:

#include<stdio.h>

#define one 1
#define tow 2
#define three 3
#define four 4

void print(int flags)
{
  if(flags>>0 & 1) //右边第一位是否右值
  {
    printf("flags : first place\n");
  }
  if(flags>>1 & 1) //右边第二位
  {
    printf("flags : second place\n");
  }
  if(flags>>2 & 1) //第三位
  {
    printf("flags : third place\n");
  }
  if(flags>>3 & 1) //四
  {
    printf("flags : fourth place\n");
  }
}

int main()
{
  print(one);
  printf("\n");
  print(one | three);
  printf("\n");
  print(tow | three | four);
  return 0;
}

把函数内的printf换成文件打开的不同功能,就能实现处fopen的不同方式打开文件。

三、OS内文件的管理

语言角度理解文件描述符

fopen返回的是一个结构体FILE,open返回的却是一个整形,先来看看这个整形存放的是上面。

int main()
{
  int fp1 = open("test1.txt",O_WRONLY | O_CREAT,0664);
  printf("fp1 : %d\n",fp1);
  int fp2 = open("test2.txt",O_WRONLY | O_CREAT,0664);
  printf("fp2 : %d\n",fp2);
  int fp3 = open("test3.txt",O_WRONLY | O_CREAT,0664);
  printf("fp3 : %d\n",fp3);
  int fp4 = open("test4.txt",O_WRONLY | O_CREAT,0664);
  printf("fp4 : %d\n",fp4);
  close(fp1);
  close(fp2);
  close(fp3);
  close(fp4);
  return 0;
}

可以观察到打开的文件返回值就像排列好的一样,但它并不是从0开始的。c语言默认是打开三个输入输出流:stdin(输入流:键盘)、stdout(输出流:显示器)、stderr(标准错误,输出流:显示器)Linux下一切皆文件,这里也可以用到c语言上,它将显示器和键盘看做了文件,我们使用的printf和scanf也就是将数据写入stdout和读取stdin。这三个文件在底层自然也是使用open打开,它们分别对应的就是0(标准输入:键盘)、1(标准输出:显示器)、2(标准错误:显示器),这个进程打开其他的文件也就依次跟在后面,每个文件都对应的是唯一的值,我们对文件的操作就变成了对这些值的操作,这些值被称作文件描述符。

代码测试

对1文件进行写入:

int main()
{
  const char* s= "hahaha\n";
  write(1,s,strlen(s));
  return 0;
}

结果就和printf打印一样。

现在知道了文件描述符本质是文件的映射,我们在来站在进程的角度看看是如何映射的。

进程角度理解文件描述符

文件打开的存储方式

文件只能被进程打开,进程是可以打开多个文件,那这些文件肯定是要被管理起来的,Linux中管理这种存在很多统一信息类型,但值不同的对象,会采用先描述,再组织的理念。

描述文件的信息,那不就是文件的属性吗?根据冯诺依曼体系,哪怕是只打开文件也需要将文件加载到内存中,OS就给文件创建了一个struct file的结构体描述文件,再使用链表的形式组织起来。但文件的数据不会存放到内存中,OS会给每个文件开辟一块空间文件内存级的缓存,我们无论是读还是写,都需要将进程的数据放到里面或是磁盘文件的数据拷贝到里面,间接进行对文件的修改。

但是每个进程的文件描述符都是像下标一样连续的,bash内的进程有很多个,进程不可能组织着去打开文件让进程所需文件连在一起。所以OS就给每个进程创建了一个struct files_struct*指向一个结构体,这个结构体里存放了一个struct file*的数组,这个数组前三个元素自然就是0、1、2三个流文件,每打开一个文件就将这个文件放入到数组中,文件描述符也就是这个数组的下标,对应的是不同文件。

文字还是很难理体会到它是如何储存的,来通过图片感受一下:

再来看open打开文件是在做什么:

  1. 创建file
  2. 开辟文件内存级的缓存
  3. 查看进程的文件描述符标(struct file*[])
  4. 把file地址填入对应的表中
  5. 返回下标
代码测试

文件描述符的变化:

int main()
{
  close(0);
  close(2);
  int fp = open("test1.txt",O_WRONLY);
  printf("fp : %d\n",fp);
  close(fp);
  return 0;
}

发现是结果是: fd: 0 或者 fd 2 可见,文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

把硬件当文件开看待

虽然Linux内一切皆文件,但把硬件这种实质性的东西当文件来处理,还是有些抽象。硬盘中的文件创建file,是有文件属性可以填写的,硬件呢?

OS是通过驱动层来管理硬件的,驱动层一般由各个硬件厂商提供接口,这些接口有硬件的基本信息(品名、型号、电压电流大小等)和修改硬件数值的函数(比如修改鼠标的DPI)。file内这些基本信息使用struct device封装,函数使用函数指针去指向它们,将这些函数指针称为方法表。

有的设备没有读写或其他一些功能,那file内对应函数的函数指针就置为空,表示没有这种功能。

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

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

相关文章

时序预测 | 基于MAMbaS+transformer时间序列预测模型(pytorch)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MAMBAS,transformer python代码&#xff0c;pytorch架构 可以发刊&#xff0c;先发先的&#xff0c;高精度代码。 需知&#xff1a;好的创新性模型可以事半功倍。。 适合功率预测&#xff0c;风电光伏预测&#xff0…

ubuntu通过smba访问华为设备

文章目录 ubuntu通过smba访问华为设备华为设备设置ubuntu设置访问测试 ubuntu通过smba访问华为设备 华为设备设置 华为设备在华为分享一栏下有共享至电脑的选项&#xff0c;打开即可&#xff0c;这里会创建用户名和密码进入设置 -> 关于手机/平板电脑 -> 状态信息&…

Android 10.0 mtk平板camera2横屏预览旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,所以就需要看下mtk的camera2的相关预览功能,然后看下进入 launcher camera的时候看下如何实现预览横屏显示 如图所示: 2.mtk平…

【Linux】文件魔法师:时间与日历的解密(8/15完成)

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;文件魔法师&#xff1a;时间与日历的解密 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题 | 代码…

Golang | Leetcode Golang题解之第390题消除游戏

题目&#xff1a; 题解&#xff1a; func lastRemaining(n int) int {a1 : 1k, cnt, step : 0, n, 1for cnt > 1 {if k%2 0 { // 正向a1 step} else { // 反向if cnt%2 1 {a1 step}}kcnt >> 1step << 1}return a1 }

数学建模强化宝典(6)0-1规划

前言 0-1规划是决策变量仅取值0或1的一类特殊的整数规划。这种规划的决策变量称为0-1变量或二进制变量&#xff0c;因为一个非负整数都可以用二进制记数法用若干个0-1变量表示。在处理经济管理和运筹学中的某些规划问题时&#xff0c;若决策变量采用0-1变量&#xff0c;可把本来…

upload-labs-master靶场通关攻略

第一关 上传并进行抓包&#xff0c;修改后缀为php 第二关 抓包修改后缀 第三关 改后缀为php3 第4关 使用Apache的配置文件.htaccess来上传文件 然后再上传php文件 第5关 使用.user.ini来上传文件 然后再上传jpg文件 访问upload目录下的readme.php文件 第6关 大小写绕过 第…

公钥密码学

1. 非对称密码学 非对称密码学&#xff08;Asymmetric Cryptography) 中的 “非对称” 指的是用于加密数据的密钥和用于解密数据的密钥是不一样的&#xff08;如果一样&#xff0c;那就是对称密码学&#xff09;。对称密码学也称为共享密钥密码学。类似地&#xff0c;非对称密码…

大模型笔记01--基于ollama和open-webui快速部署chatgpt

大模型笔记01--基于ollama和open-webui快速部署chatgpt 介绍部署&测试安装ollama运行open-webui测试 注意事项说明 介绍 近年来AI大模型得到快速发展&#xff0c;各种大模型如雨后春笋一样涌出&#xff0c;逐步融入各行各业。与之相关的各类开源大模型系统工具也得到了快速…

neural-admixture:基于AI的快速基因组聚类

最近学习祖源分析方面的内容&#xff0c;发现已经有了GPU版的软件&#xff0c;可以几十倍地加快运算速度&#xff0c;推荐使用&#xff01;小数据集的话家用显卡即可hold住&#xff0c;十分给力&#xff01; ADMIXTURE 是常用的群体遗传学分析工具&#xff0c;可以估计个体的祖…

注册中心技术选型

优质博文&#xff1a;IT-BLOG-CN 市面上流行的开源注册中心很多&#xff0c;耳熟能详的有Eureka、Zookeeper、Nacos、Consul。我们在选型的时候也主要从这四个组件中进行筛选。下面就对我们内部的讨论内容进行整理&#xff1a; 第一个维度&#xff1a;开源公司的实力 Eureka…

InceptionV4 Pytorch 实现图片分类

一、目录结构 训练过程&#xff1a; 在训练集和测试集分类目录中放好待训练的分类图片&#xff08;f1,f2,f3&#xff09;运行模型训练代码&#xff0c;生成模型参数文件运行分类测试文件&#xff0c;设置待验证的图片路径&#xff0c;调用模型文件得出分类结果 二、模型构建代…

Auto-Unit-Test-Case-Generator -- java项目自动测试生成

0.Pre-预备知识&#xff1a; 0.1.Maven是什么&#xff1f; [by Maven是什么&#xff1f;有什么作用&#xff1f;Maven的核心内容简述_maven是干什么用-CSDN博客 ] 是Java 领域中最流行的自动化构建工具之一&#xff0c;Maven 作为 Java 项目管理工具&#xff0c;具有: 包管…

AI的基本使用

AI使用 一、网页端AI二、手机端AI三、AI提问指令大全四、AI绘画 一、网页端AI 讯飞星火网页版百度文心一言通义万相&#xff08;主要用于生图&#xff09;通义听悟&#xff08;主要用于音频&#xff09;通义智文&#xff08;主要用于生文&#xff09;腾讯文档里的智能助手&…

Laravel 中间件与事件应用教程

前言 在 Laravel 框架中&#xff0c;中间件&#xff08;Middleware&#xff09;和事件&#xff08;Events&#xff09;是两种强大的机制&#xff0c;用于处理 HTTP 请求和应用程序中的特定动作。它们各自有独特的应用场景和优势。本教程将详细介绍中间件和事件的基本概念、区别…

网络压缩之稀疏模型设计

通过网络架构的设计来达到减少参数量的效果。等一下 要跟大家介绍深度可分离卷积&#xff08;depthwise separable convolution&#xff09;。在讲这个方法之前&#xff0c;先复 习一下CNN。在 CNN 的这种卷积层里面&#xff0c;每一个层的输入是一个特征映射。如图1 所 示&…

Mysql——高可用集群部署

目录 一、源码编译mysql 二、mysql的主从复制 2.1、主从复制 2.2、延迟复制 2.3、慢查询日志 2.4、MySQL的并行复制 三、MySQL半同步模式 四、mysql高可用组复制 五、mysql-router 六、mysql高可用MHA 七、为MHA添加VIP功能 一、源码编译mysql 1、安装依赖 [rootm…

HX711—称重模块

1、简介 HX711 采用了海芯科技集成电路专利技术&#xff0c; 是一款专为高精度电子秤而设计的 24 位 A/D 转 换器芯片。 2、原理图 PCB参考设计原理图 3、模块驱动代码&#xff08;固件库&#xff09; 数据读取代码分析 HX711信号读取时序 初始化&#xff1a; 将 PD_SCK&…

C练手题--A snail enters a bar! 【7 kyu】

一、原题 链接&#xff1a;Training on A snail enters a bar! | Codewars Problem Description: A snail is crawling along a rubber band that has an initial length of x units. The snail moves at a constant speed of y units per minute. As the snail crawls from t…

upload-labs靶场通关(附靶场环境)

链接: https://pan.baidu.com/s/1GQP5zthh598A4Mp-WQM4vA 提取码: zovn 环境搭建 步骤一&#xff1a;将环境附件下载到phpstudy_pro\WWW下面修改名字为upload 步骤二&#xff1a;询问绑定地址 第一关 less-1 步骤一&#xff1a;上传一句话木马 步骤二&#xff1a;更改文件名…