湖南响应式网站建设,跨境电商一般卖哪些产品,如何承接设计网站建设,宜兴做网站公司文章目录一、前言二、回顾C语言文件操作三、初识系统调用openreadwriteclose四、文件系统初识五、结语一、前言
二、回顾C语言文件操作
int main()
{FILE* fp fopen(log.txt, w);if (fp NULL){perror(fopen);}int cnt 0;fputs(…
文章目录一、前言二、回顾C语言文件操作三、初识系统调用openreadwriteclose四、文件系统初识五、结语一、前言
二、回顾C语言文件操作
int main()
{FILE* fp fopen(log.txt, w);if (fp NULL){perror(fopen);}int cnt 0;fputs(hello, fp);fclose(fp);return 0;
}像我们使用的诸如fopen、fclose、fputs等一系列函数其实是C语言提供给我们的。这些函数分别封装了open、close、write、read等一系列系统调用向上提供给用户。
三、初识系统调用
open
标志位 我们在函数中设置参数开关的话虽然能达到达成某个条件就触发某个功能的效果但如果传递多个标志位就会显得拥堵因此系统用一个整数flags、并用flags的每一个比特位表示一个标志位这样一个int就可以同时至少传递32个比特位绝对是够用的了。
open
int open(const char* pathname,int flags);
int open(const char* pathname,int flags,mode_t mode);系统调用open让我们能够按照一定方式打开一个文件并给我们返回一个int类型的值。 pathname代表文件的路径 flags就是我们上面提到的标志位标志位采用宏的方式设置如O_RDONLY、O_WRONLY、O_TRUNC(清空文件原有内容)、O_APPEND(不清空文件原有内容) mode需要我们设置文件的权限如果需要的话 open的返回值
如果使用open打开一个文件并接收这个函数的返回值我们会发现这个返回值是数字3那0、1、2去哪里呢
其实open的返回值被称为 文件标识符 之所以从3开始是因为任何进程在启动的时候都会默认打开三个流标准输入流、标准输出流标准错误流这三个流占用了0、1、2的标识位。
read
ssize_t read(int fd, const void* buf,size_t len);write
ssize_t write(int fd, const void* buf, size_t count);close
close(int fd)实际上像C语言提供的fopen、fputs、fclose等函数都是封装了这些系统调用当我们使用fopen打开一个w文件时其实在open中传入了多个标志位。不管任何语言如何封装都是要调用底层的系统调用。
四、文件系统初识
文件如何管理
结合之前讲过的内容我们知道进程在创建后会有一个task_struct的结构体里面存放着进程相关内容而这个结构体里存放着一个 结构体指针 files这个指针指向的另一个结构体就存放着一个存放文件标识符的数组并拿这个数组去寻找打开的各种文件。如图所示 LINUX下的“一切皆文件”
如图我们使用操作系统的本质就是以进程的方式去访问当一个进程创建好以后如果我们使用键盘和显示器读写操作的时候进程会统一创建struct file结构体其中包含文件的基本信息、缓冲区、以及函数指针来指向驱动程序提供操作硬件的方法尽管各个设备的驱动方法不尽相同但站在进程的视角他只需要管理struct file这个结构体这就是一切皆文件的理解。 重定向理解
根据上面的理解假如有这样一段代码
int main()
{close(0)//关闭了标准输入流int fd open(log.txt,O_RDONLY);int a,b;scanf(%d%d,a,b);return 0;
}进程中文件描述符分配把下标最小的没有使用的文件描述符分配给新文件。 由于我们已经把标准输入流0关闭并打开了文件log.txt此时log.txt的文件标识符就顺利成章的成了0因此我们就是从log.txt中读取数据了。
但这样关闭再重定向并不方便我们也可以使用dup2函数来实现重定向
int dup2(int oldfd ,int newfd) //将 oldfd 重定向到 newfd如何做到重定向呢
在上层无法感知的情况下在OS内部更改进程对应的文件描述符表中特定下标的指向。
缓冲区理解
先来思考一个问题
int main()
{fprintf(stdout,hello world\n);const char* msg hello write!\n;write(1,msg,strlen(msg));fork(); return 0;
}运行两个命令为什么结果不同呢为什么hello world被打印了两次呢 要解释这个问题我们需要结合重定向和刷新缓冲的策略来理解
刷新策略 a.显示器采用的刷新策略行缓冲 b.普通文件采用的刷新策略全缓冲
我们的程序里fprintf是C库提供的函数我们在写入数据的时候要先将数据写入C库提供的缓冲区内按照刷新策略将内容拷贝到系统内相应的文件缓冲区而write直接将数据拷贝到系统内相应的文件缓冲区直接运行程序由于显示器是行缓冲策略因此fork的时候已经把数据都刷新到屏幕了。而重定向后fprintf采用全缓冲的策略但由于内容不会达到全缓冲要求自然不会刷新数据在C库的缓冲区一直到fork以后才能刷新 所谓的刷新即对其中内容清空这样就会触发写时拷贝父子进程自然都会刷新一次。
五、结语
到这里今天的内容就全部结束了如果感到对你有所帮助欢迎三连支持我们下次再见。