700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 网络与IO知识扫盲(一):Linux虚拟文件系统 文件描述符 IO重定向

网络与IO知识扫盲(一):Linux虚拟文件系统 文件描述符 IO重定向

时间:2021-08-01 09:57:55

相关推荐

网络与IO知识扫盲(一):Linux虚拟文件系统 文件描述符 IO重定向

系统IO原理

在 Linux 中:

VFS(Virtual Filesystem Switch):虚拟文件系统,是一个目录树。树上不同的节点可以映射到物理的文件地址,可以挂载。

相当于一个解耦层,在具体的文件系统之上抽象的一层,为能够给各种文件系统提供一个通用的接口,使上层的应用程序能够使用通用的接口访问不同文件系统、不同的驱动。

inode号:文件打开的时候有一个inode号,读到pagecache页缓存中。

两个程序如果打开的是统一文件,共享的是同一个pagecache 4k。

如果后续我们对pagecache进行了修改,会产生脏数据,这时候需要使用flush刷新到磁盘中去。“脏”这个标识是内核对于上层打开的文件的一个统一的管理,并不是针对某一个文件。内核会根据自己的设定,把数据输入到磁盘中去。如果你在5秒钟内产生了3.8G数据,又恰好没有触发内核的写磁盘操作,这时候突然断电会导致你这些数数据的丢失。

如果两个线程同时修改同一块数据,会加锁。

Redis的持久化,也是受操作系统内核这种机制的约束。

虚拟目录树

boot目录在分区3中,其他目录都在分区1中。

计算机引导的时候,先挂载了3分区,又挂载了1分区。新的挂载覆盖了原有的boot目录

虚拟文件系统进行了一个抽象:一切接文件。

磁盘文件、摄像头、打印机,都被看做是文件,基于文件的这种抽象,就可以应用到IO流了。

那么如何区分这些不同的文件?我们引入文件类型:

硬链接

两个变量名指向了同一个物理位置

无论是硬链接还是软连接,如果修改任意一方,另外一个文件也会看到这个变化。

如果删掉了其中一个文件,另外一方还能找到这个文件。相当于只是删除了一个引用。

软链接

软链接是两个独立的文件。修改任意一个文件,另一个文件能看到这个变化。

如果删除原有的msb.txt,则xxoo.txt找不到链接了,会标红报错。

如果删除原有的msb.txt,则xxoo.txt找不到链接了,会标红报错。

下面我们开始搞事情,做一个小实验,证明一切皆文件

用dd命令生成一个空的mydisk.img文件

挂载到虚拟的环回设备上,挂载之后进行格式化

把新的loop0挂载到原来的/mnt/ooxx目录中去

现在/mnt/ooxx是空的

我们希望用子目录模仿根目录里面的目录结构,以及程序的摆放位置。

1、找到bash所在位置,拷贝过来

2、将bash需要动态链接的文件,也拷贝过来

将根目录切换到当前目录,并将当前目录下的bin下的bash启动

在当前bash中输出“hello mashibing”,重定向到根目录下的abc,txt文件中

可以看到abc.txt被输出到新的根目录下。

那么Docker呢?也是这个原理吗?

这个实验不同于Docker,Docker更加复杂,它不只是文件系统的命名空间的一个子域。

Docker复用的是物理机的内核,Docker里面跑的是进程,先有镜像,有了img镜像之后,才有container容器的概念。

源于整个虚拟文件系统的支撑。

文件描述符

1、lsof命令

lsof是list open files的简称,它的作用主要是列出系统中打开的文件,基本上linux系统中所有的对象都可以看作文件,lsof可以查看用户和进程操作了哪些文件,也可以查看系统中网络的使用情况,以及设备的信息。

创建一个文件描述符8,用来读取ooxx.txt

NODE列:表示Inode号

如果lsof加上-o参数的话,会显示一列OFFSET,表示当前读文件位置的指针。

使用read读文件:

新开了一个bash标签页,用一个新的文件描述符6,去读取ooxx.txt

证明两个进程读取文件时,不会相互影响:

我们可以得出这个结论,内核为每一个进程各自维护了一套数据,包括fd文件描述符。

fd维护了一些关于文件的偏移、Inode号,以及元数据信息等。

这些内容看起来和Java没什么关系,但是在使用Java进行文件IO时,关系到每种不同的写法的成本。所以还是很重要的~

Socket 文件类型示例

用文件描述符8,指向一个socket连接

关于/proc目录

与其它常见的文件系统不同的是,/proc是一种伪文件系统(也即虚拟文件系统),存储的是当前内核运行状态的一系列特殊文件

/proc/$$是当前bash的文件

$$BASHPID是当前bash的pid

/proc/$$/fd是当前程序的所有的文件描述符,也可以使用lsof -op $$看见当前进程的文件描述符的细节,包括偏移量、指针等等。

关于0标准输入1标准输出

<表示输入>表示输出

ls 命令的标准输出

ls ./ 1> ls.out将ls的标准输出1重定向到ls.out

cat 命令的标准输入、标准输出

cat 0< test.txt 1> cat.out将cat的标准输入重定向为 test.txt , 将其标准输出重定向为 cat.out

read命令的标准输入、标准输出

重定向操作符<>的对接

让两个流写到不同的文件中去:

让两个流写到相同的文件中去:

管道命令|

head默认读前 10 行

head -3读前 3 行

tail默认读后 10 行

tail -3读后 3 行

head -8 test.txt | tail -1通过管道,让左面的输出流入右面的输入,实现仅输出第 8 行

Linux 前置知识

进程之间的父子关系

当前所在的bash的进程id号

在当前bash中新开一个bash,打印新开的bash的进程id号

使用pstree查看进程关系

使用exit,又回到了11053

关于变量

父进程定义的变量x,不能在子进程取到,除非使用export

这也是为什么在/etc/profile/配环境变量的时候,要添加export的原因

关于代码块、管道开启的子进程

在一个花括号中,所有的指令在同一个进程中执行。

bash是解释执行的,如果看到管道,会将管道左侧的命令独立开启一个子进程,管道右侧的命令独立开启一个子进程,用管道进行对接。而进程的隔离级别很高,所以在新开启的进程中对变量a的修改,不会影响父进程a的值。

$$的优先级高于|$BASHPID的优先级高于|

看一下进程号,可以发现管道两侧开启的是独立的子进程

实际上,我们进行的是如下管道操作:

下面这个图可以看到,管道左侧的进程右侧的进程通过管道被对接起来

我们也可以使用

lsof -op 4512

lsof -op 4513

这两个命令,看到两个子进程中正在开启的管道。

PageCache

做完上面的铺垫,我们可以先对PageCache做一个粗俗的理解了。

事实上,在很多地方都有缓存:

应用程序中:在application中可以有缓冲区(比如我们在Java中常用的BufferXXX IO)内核中的页缓存硬盘上的缓冲区

如果每次应用程序想要读数据的时候,都要通过cpu去取的话,效率会很低,于是我们了加入协处理器。

下面我们搞一个事情

写一个mysh小脚本,待会儿使用的时候参数传给0

OSFileIO.java

public class OSFileIO {static byte[] data = "123456789\n".getBytes();static String path = "/root/testfileio/out.txt";public static void main(String[] args) throws Exception {switch ( args[0]) {case "0" :testBasicFileIO();break;case "1":testBufferedFileIO();break;case "2" :testRandomAccessFileWrite();case "3"://whatByteBuffer();default:}}//最基本的file写public static void testBasicFileIO() throws Exception {File file = new File(path);FileOutputStream out = new FileOutputStream(file);while(true){// Thread.sleep(10);out.write(data);}}//测试buffer文件IO// jvm 8kB syscall write(8KBbyte[])public static void testBufferedFileIO() throws Exception {File file = new File(path);BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));while(true){Thread.sleep(10);out.write(data);}}//...

用上面的mysh启动,传参为0,也就是执行了testBasicFileIO()这个方法

测试突然断电。断电前我们看到,out.txt文件在不断增大:

断电后重启,文件大小都是0:

上面这个测试说明了缓冲区的存在。在一段时间内,并没有进行磁盘的刷写。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。