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

24 篇文章 1 订阅

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

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

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

封装出来的接口是有多个的,但是文件类的系统调用接口,在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的分配规则:是分配最小的,没有被占用的文件描述符

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪皮兄弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值