使用U盘传数据时操作系统做了什么(源码分析)(四)

2017-04-10 00:18:00
2puT
转贴
298
摘要:使用U盘传数据时操作系统做了什么(源码分析)(四)

不同文件系统间数据的传输

对于我上面演示的cp /run/media/pf/pf/0.png /home/pf命令,简单抽象的执行过程是这样的: 
1.打开/run/media/pf/pf/0.png文件 
2.在/home/pf文件下中新建0.png文件 
3.读取/run/media/pf/pf/0.png文件数据到缓冲区 
4.从缓冲区将数据写入/home/pf/0.png 
5.关闭这两个文件 
我们知道,我相互传数据的这两个文件系统是不同的,那么,不同的文件系统之间为什么可以用同一个系统调用来进行操作呢? 
答案是linux的虚拟文件系统,那么内核中具体是如何实现的? 
我这里以读取/run/media/pf/pf/0.png文件数据到缓冲区为例进行内核源码的分析。 

首先,当用了read()系统调用,会进入内核态调用sys_read()。这个函数的实现源码如下:

我们可以看到,这里使用了宏定义SYSCALL_DEFINE3,这样就可以传递变长参数。这里的重点执行函数在于vfs_read()。也就是说接下来会调用这个函数继续执行操作。我们进入其定义。

前面三条都是判断语句。重点在于后面的判断语句:如果file->f_op->read不存在则执行do_sync_read()函数,若存在,则执行file->f_op->read()函数。 
从这里可以很显然的看到,file与f_op都是结构体,file中定义了f_op,f_op中定义了read。现在,来看一下file结构体的样子。

之前在基础章描述过它,这里不再重复描述。这里的重点是要找到f_op。 
我们可以看到它是一个file_operations类型的结构体。 
file_operations想必大家都知道,这是一个文件操作的结构体,其中定义的都是文件操作的函数,也就是接口。内核中源码实现如下:

这个结构体也位于/include/linux/Fs.h中。 
想必现在大家就明白了,f_op调用的read()其实就是这个结构中定义的函数read。但是,这里的read并没有具体的实现。对于不同的文件系统,它们可能就有不同的实现方案。例如我linux的EXT4文件系统对于file_operations的实现与我U盘NTFS文件系统对于file_operations的实现就不相同。 
EXT4文件系统file_operations结构的具体实现:

定义在/fs/ntfs/File.c中。 
NTFS文件系统file_operations结构的具体实现:

定义在/fs/ext4/File.c中。 
可以看到,它们对于文件读、写等实现函数是相同的,但是对于有些函数如release、open等,实现函数则是不同的。 
到此,大家可能就明白了linux文件系统是如何实现相同的系统调用实现对于不同文件系统的操作。实际上核心就是使用了file_operation这个接口实现的。

五、总结

实际上,在linux中有许多非常巧妙的设计,而且这些巧妙的设计也确实有其必然性。重要的是要学会透过现象看本质,抓住一般规律。本篇博客对于linux文件系统的分析还不算深入,今后还会进一步进行深入学习。





原文地址:http://mp.weixin.qq.com/s/4BSrPOgAqFTJb2_I3yKuZQ

发表评论
评论通过审核后显示。
联系我们