系统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:

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

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

  1. Linux C:文件描述符、IO重定向、恢复标准输入输出

    目录 一.文件描述符 二.IO重定向 三.重定向回终端.伪终端 四.恢复标准输入输出 一.文件描述符 在Linux中,文件描述符是一个非负整数的数据类型.是FILE结构体中的一个成员属性. 每打开或者 ...

  2. 玩转linux文件描述符和重定向,玩转Linux文件描述符和重定向

    本文介绍linux中文件描述符与重定向的相关知识,文件描述符是与文件输入.输出相关联的整数,它们用来跟踪已打开的文件.有需要的朋友参考下. 原文出处: linux下的文件描述符是与文件输入.输出相关联 ...

  3. 玩转Linux文件描述符和重定向

    本文介绍linux中文件描述符与重定向的相关知识,文件描述符是与文件输入.输出相关联的整数,它们用来跟踪已打开的文件.有需要的朋友参考下. 原文出处:http://www.jbxue.com/arti ...

  4. Linux下利用文件描述符恢复的成功失败实验

    数据误删除是作为初级运维人员常常遇到的"低级错误",一些有经验的老手有时也在疲劳.不冷静的情况下"马失前蹄".一旦误删除数据文件,尽快采用影响最小.最迅速的手段 ...

  5. linux 反弹shell(一)文件描述符与重定向

    0X00 前言 由于在反弹shell的过程中有一些非常精简的语句,但是一直没有深入理解,只是作为一个伸手党/搬运工,于是下定决心要将其弄明白,而这里面最难的也就是文件描述符和重定向的部分,因此我特地写 ...

  6. linux文件描述符有什么用,linux上的文件描述符3有什么特别之处?

    我的工作,那将在Linux和Mac OS X上运行的服务器应用程序它是这样的:linux上的文件描述符3有什么特别之处? 启动主要应用 控制器进程的叉 调用lock_down()在控制过程中 再次叉终 ...

  7. linux虚拟文件系统-文件的打开

    本质上,一个文件打开的过程就是建立fd,file,dentry,inode,address_space的关联过程.关联过程中关键的一个过程是如何根据路径名寻找到对应的dentry,对于用户程序来说路径 ...

  8. IO那些事01-IO总述和文件描述符

    VFS 内核既管内存,又管磁盘IO. 作为LINUX内核来说,它在内存中构建了一个虚拟文件系统VFS,不同于windows上的物理文件系统结构,C盘代表的就是物理的C盘分区,D盘就是D盘的物理分区, ...

  9. Linux 基础I/O :文件描述符,重定向,文件系统,软链接和硬链接,动态库和静态库

    文件描述符 重定向 文件系统 软链接和硬链接 动态库和静态库 文件描述符 上面两个接口分别是c语言的fread接口和linux的read接口,当我们在使用的时,可能会有疑问,为什么linux的io接口 ...

  10. Linux下的文件描述符

    引文 在 Linux 的世界里,一切设备皆文件.对文件的操作都是通过文件描述符(fd)来进行的. Linux 中有7种文件类型: 文件类型 文件类型描述 符号 普通文件 最常使用的一类文件,其特点是不 ...

最新文章

  1. c语言计算日出日落时间_计算日出日落算法实现
  2. JAVA_Thread_interrupt
  3. android 第三方加密软件,Android实用图文教程之代码混淆、第三方平台加固加密、渠道分发...
  4. .NET Compact Framework 2.0 SP2 for Platform Builder (4.2, 5.0, 6.0)
  5. APUE学习笔记之UNIX系统概述(1)
  6. C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 ( (struct X*)0 ) -> Y)语法(匿名结构体)
  7. spark RDD详解及源码分析
  8. 剥开比原看代码09:通过dashboard创建密钥时,前端的数据是如何传到后端的?
  9. Linux redis配置服务,Linux 安装 redis 并配置成 service 系统服务
  10. 国内版Office 365和Azure AAD绑定的问题及解决方案
  11. 【C/C++】inline函数和static函数和宏定义的比较
  12. 遥感导论网课_甘肃农业大学2019年地理信息科学专业专升本招生 专业课考试大纲...
  13. 财务有必要学python吗-8年老财务:财务分析学python就能提高效率?一半人是骗子...
  14. ubuntu20.04 推荐翻译软件
  15. PB如何配置数据源及自带的PB系统
  16. SIM868——GPRS调试之公网IP端口无法映射的解决方法
  17. Jenkins build light on Windows, with Blinky
  18. Celery入门--定时任务的开发及运行
  19. 大学计算机基础实验实施,大学计算机基础实验实施的方案学生用.docx
  20. Silvaco TCAD仿真10——MOSFET结构仿真

热门文章

  1. POJ - 1091 跳蚤(容斥原理+数论)
  2. CodeForces - 432D Prefixes and Suffixes(KMP的next数组性质)
  3. python爬取下拉列表数据_Python+selenium之获取文本值和下拉框选择数据
  4. 如何产生高斯带限白噪声数据_车间噪声对我们的身体产生巨大影响,我们该如何解决?...
  5. Android开发笔记——Android 9发送通知
  6. EXE和SYS通信IOCTL方式
  7. cmake Debug模式和Release模式
  8. 内网突破SSL嗅探的探究
  9. 50 种不同编程语言的“Hello World”,你知多少?
  10. Kafka分区分配策略(4)——分配的实施