文件IO(文件IO说明,文件IO基本函数,实现文件操作,函数参数分析,过程分析,open函数打开文件时分析)【linux】(b)

文件IO说明

文件io讲的是,如何调用Linux OS所提供的相关的OS API,实现文件的读写。
如何理解“文件IO”这个词IO就是input output的意思,文件io就是文件输入输出,也就是文件读写。读写的是数据。
不过读文件和写文件,到底哪一个是input,哪一个是output呢?
答:input和output,其实是以CPU作为参考点来看的:
在这里插入图片描述
当有OS的时候,应用程序基于OS运行时,必须通过OS API假借OS之手,才能操作底层硬件,无法回避。当然前提是有操作系统,如果没有操作系统,裸机程序不需要操作系统支持,我们这里只说明使用操作系统的情况。

文件IO基本函数

文件IO所涉及的OS API(系统函数):
1)open函数:打开文件
(2)close函数:关闭文件
(3)read函数:从打开的文件读数据
(4)write函数:向打开的文件写数据
(5)lseek函数:移动在文件中要读写的位置
(7)dup函数:文件读写位置重定位函数,本来是写到这个文件,重定位后可以写到另一个文件里面
(8)fcntl函数:文件描述符设置函数
(9)ioctl函数:一个特殊的函数

本章的函数,在后续博客中会频繁使用,所以这些函数一定要会用,但是不要去死记,函数参数很多,想记也记不住,涉及细节时,使用man查一查自然就知道了。

实现文件操作

文件读写的简单例子

(1)第一步:打开文件
open函数
(2)第二步:读、写等操作文件
read、write函数
(3)第三步:关闭文件
close函数

使用man命令查看这些函数的详细说明。

我们通过man 2 open 查看打开文件的函数,找到所需要的头文件和函数格式,下面也会有相应的使用描述。(下面是我们给出在linux操作系统中给出的命令查看结果)
在这里插入图片描述
man 2 read
在这里插入图片描述

man 2 write
在这里插入图片描述

函数参数分析

上面是给出的原版,接下来我们对于函数参数进行解释说明。
man 2 open

在这里插入图片描述

man 2 read
在这里插入图片描述

man 2 write
在这里插入图片描述

那我们接下来使用文件读写操作给一个文件写入”hello world”

在这里插入图片描述
在这里插入图片描述

上面的代码中我们在最后没有写出来关闭文件,这是不规范的,但是整个程序在执行完成之后也会关闭文件所以程序在之后也会运行出来不会出错,在之后的内容中我们都会加上文件关闭代码更加规范。

接下来我们进行上面代码的编译和运行:
在这里插入图片描述
我们可以看到编译没有问题,打开文件也没有问题,但是buf2在读取数据的时候没有读取到。这是为什么呢?我们先来查看一下文件里有没有写入内容
在这里插入图片描述

我们可以到数据是已经写入到文件里面的,只是buf2没有读取到。

在这里插入图片描述

那么我们就需要把光标调整到开始的位置。
我们的OS API已经提供了将光标移动到最开始位置的函数我们直接调用API进行使用:
在这里插入图片描述

在这里插入图片描述我们对于代码进行修改,写入之后,读取数据之前我们把文件光标一定到最开始的位置:在这里插入图片描述在这里插入图片描述

修改之后我们就可以正常打印出来结果:
在这里插入图片描述

过程分析

1)open函数

在这里插入图片描述

(a)利用文件名,通过文件系统找到块设备上的文件文件系统就是一个程序代码,组织管理着块设备上的所有文件文件系统属于OS的一部分。

(b)找到文件后,调用块设备驱动程序,打开文件
驱动程序也是属于OS的一部分。
· 打开成功:返回一个非负整数的操作符(文件描述符)
· 打开失败:返回-1,表示打开失败

使用fd存放返回值,便于我们使用这个返回值。
文件打开成功后就可以操作文件了。

2)write函数

利用打开成功后返回的,非负整数的文件描述符,向文件里面写数据。

3)lseek函数

利用文件描述符,将文件读写的位置调整到文件头上。
为什么要调到文件头上?
write时,文件读写的位置到了末尾了,read读末尾的话,读到的内容就是空的,看不到read的效果。

4)read函数

从文件头上开始,读取指定长度的数据到buf中。
printf打印显示,查看效果。

open函数打开文件时分析

如果open打开失败的话(比如文件不存在就会导致失败)
open啥也不会干就直接返回了。
但是如果open将文件打开成功的话,open具体做了哪些事情呢?

1)记录打开文件的信息

(a)程序运行起来后就是一个进程了,OS会创建一个task_struct的结构体,记录进程运行时的各种信息,比如所打开文件的相关信息。
在这里插入图片描述

(b)open将文件成功打开后,在task_struct中又会创建一些结构体(数据结构),用于记录当前进程目前所开文件的信息,后续所有的文件操作,都需要依赖于这些信息,其中就包括指向打开文件的文件描述符。

2)open函数会申请一段内存空间(内核缓存),后续读写文件时,用于临时缓存读写文件时的数据。

在这里插入图片描述

(a)什么是缓存?
就是开辟的一段内存空间,比如char buf[100],这就是一段100字节的缓存空间,用于临时存放中转的数据。
(b)为什么叫内核缓存?
open是OS所提供的系统函数,属于OS内核的一部分,所以open函数所开辟的缓存空间,就是内核缓存。
(c) 在我们的例子程序中,我定义了buf1和buf2这两个数组,这两个数组是我自己的应用程序定义的,因此就叫应用缓存。
其实定义的一切变量空间,比如int a,int b[30]等,都是缓存,都是用于临时缓存数据,只是我们以前没有这么叫过。
在这里插入图片描述
(d)open为什么要开内核缓存空间?
内存读写速度 > 磁盘读写速度的,有了在内存中开辟的内核缓存后,上层读写数据时,会直接读写缓存,速度会很快,至于缓存与磁盘上文件数据的交换,就留给下层去做,这样可以节省上层操作的时间。
(e)注意:open时只是开辟了内核缓存空间,里面并没有数据,只有当进行读写数据时,才会缓存读写的数据。
(f)读写时,缓存间数据的流动:
在这里插入图片描述文件IO的开端我们就先说明到这里
在后续部分我们会对于每一个细节进行展开相信说明。

发布了47 篇原创文章 · 获赞 68 · 访问量 4014
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览