Linux文件系统调用接口文件描述符的理解
创始人
2024-03-15 23:07:56
0

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

文章目录

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

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

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

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

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

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

二、文件的系统调用接口

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

① open

#include 
#include 
#include 
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//0100void 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 
#include 
mode_t umask(mode_t umask);
//mode_t是被typedef过的,特就是一个unsigned int类型的数
umask(0);//这样即可

②close

#include
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 
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* -> _filenoreturn 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);//0close(2);//关闭2号文件描述符int fd2 = open("log2.txt",O_WRONLY|O_CREAT|O_TURNC,0666);printf("fd2:%d\n",fd2);//2int fd3 = open("log3.txt",O_WRONLY|O_CREAT|O_TURNC,0666);printf("fd3:%d\n",fd3);//3return 0;
}

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

在这里插入图片描述

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...