# Linux虛擬文件系統
虛擬文件系統 VFS,使得Linux“一切皆文件”的哲學得以實現。虛擬文件系統位于頂層應用軟件和底層具體IO設備的中間一層。
:-: 
虛擬文件系統是抽象的一層,對用戶提供了統一的訪問不同文件系統的接口。其使用面向對象的方式抽象出了四種類型的數據結構:
* 超級塊對象:代表一個已安裝的文件系統,該文件系統才會真正的和IO設備交互。
* 索引節點對象 inode:代表具體的文件。其結構可如下
:-: 
* 目錄項對象 :代表一個目錄項,是文件路徑的一個組成部分。存在內存中。
* 文件對象FD:表示進程打開的一個文件,**也稱文件描述符**,每個進程的文件描述符相互獨立。當兩個進程打開同一個文件的時候,文件描述符會維護獨立的指針(seek)。
其中文件描述符、文件句柄、inode之間的關系如下:
:-: 
目錄項、inode之間的關系(inode和超級快都在磁盤中 ):
:-: 
**Linux系統分區**
~~~bash
df -h
~~~
~~~
分區 大小 使用 可用 使用百分比 掛載目錄
udev 1.9G 0 1.9G 0% /dev
tmpfs 376M 4.7M 372M 2% /run
/dev/vda1 79G 6.4G 69G 9% /
tmpfs 1.9G 7.7M 1.9G 1% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
tmpfs 376M 0 376M 0% /run/user/0
~~~
具體的IO設備在進行掛載的時候會先掛載root目錄,接著才會掛載其他的目錄。與掛載相關的操作如下:
~~~
umount 分區 # 取消該分區與該目錄的掛載
mount 分區 目錄 # 將該分區與該目錄進行掛載
~~~
**文件類型**
Linux將系統中的一切都抽象成文件,可以具體區分出多種不同類型的文件。
:-: 
使用`ll`命令第一個字段的第一列可以查看文件的類型:
-:表示普通文件。
d:表示目錄。
b:表示塊設備,例如硬盤,可以移動字節位置。
c:表示字符設備,例如鍵盤。
s:表示socket。
p:表示pipeline,管道。
l:鏈接,可以分為軟硬鏈接,上圖的數字就表示被硬鏈接引用的次數。
使用命令
~~~
stat 文件名
~~~
可以查看文件的元數據信息
:-: 
Linux系統有個/proc目錄,里面存放著打開進程的信息,每個數字文件夾標識著一個進程pid號。Linux也將進程也映射成一個文件,同時在任何的進程中都有文件描述符為:
- 0:標準輸入。
- 1:標準輸出。
- 2:報錯輸出。
采用如下命令可以查看一個進程打開的文件
~~~
lsof -p pid
~~~
輸出結果的一部分如下:
~~~
bash 162968 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 162968 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 162968 root 2u CHR 136,0 0t0 3 /dev/pts/0
~~~
例如使用如下命令可以用標準輸入將內容輸入到文件中
~~~
ls ./ 1> ls.out
~~~
可以將當前的ls命令的輸出內容輸出到ls.out文件中。
又例如在運行jar包的時候
~~~
nohup java -jar *.jar >server.log 2>&1
~~~
即表示將輸出重定向到server.log文件中,同時將報錯輸出重定向到標準輸出文件描述符1中。這樣報錯輸出也會輸出到server.log中。
**管道**
管道就是在命令行中用符號【|】表示,例如:
~~~
ps -ef | grep java
~~~
表示將左邊的命令的輸出作為右邊命令的輸入。
管道是進程間通信的一種方式,并且是單向通信的。可以分為**匿名管道**和**命名管道**,上面的 “|” 就是匿名管道,命令管道可以使用命令`mkfifo`創建。
~~~
[root@iZwz9243apyfnh4y2y36scZ test]# mkfifo mypipe
[root@iZwz9243apyfnh4y2y36scZ test]# ll
total 0
prw-r--r-- 1 root root 0 Feb 24 21:11 mypipe
~~~
p就是表示命名管道類型的文件。
往命令管道存入的數據之后被讀出之后程序才會退出,不然會一直阻塞住。注意**管道就是內核中的一串緩存數據**。
原理:
當我們在shell使用匿名管道時,會fork兩個子進程,其父進程是shell這個客戶端,并復制命令的文件文件描述符,這樣文件描述符就可以通過管道進行數據交互了。
其他:
【$$】和【$BASHPID】都能表示當前進程的PID號,但是$$的優先級要比管道符號的要高。
## pageCache
磁盤高速緩存,pageCache是內核的內存空間中對磁盤讀寫數據的一塊緩存空間,系統內核對磁盤數據的讀寫會先經過pageCache,然后再從pageCache中復制到用戶空間中(直接io的方式不用使用pageCache)。使用pageCache有如下的特點:
1. 跟計算機中大多數的緩存層的作用類似,符合“程序的局部性原理”,可以減少對磁盤的訪問。
2. 當pageCache中的數據被修改過后,需要設置成臟頁標志,操作系統會根據一定的策略將臟頁的數據寫回到磁盤中。但是并不一定會立刻寫出,所以可能造成數據丟失不能持久化的問題。
3. 當pageCache滿的時候會通過LRU算法將某些頁寫回磁盤。
4. 具備**預讀**的功能,能夠在一次磁盤讀取數據的時候,額外的讀取更多的數據(受局部性原理的指導)。
圖示pageCache的位置:
:-: 
現在都是由DMA將磁盤中的數據放到pageCache中
:-: 
**查看系統臟頁大小**
1. 查看系統配置
~~~
sysctl -a | grep dirty
~~~
:-: 
其中:
* vm.dirty_background_ratio:是內存可以填充臟數據的百分比。超過這個比例,這些臟數據稍后會寫入磁盤,由后臺進程執行,不會阻塞。比如,我有32G內存,那么有3.2G的臟數據可以待著內存里,超過3.2G的話就會有后臺進程來清理。
* vm.dirty_ratio:是可以用臟數據填充的絕對最大系統內存量,當系統到達此點時,必須將所有臟數據提交到磁盤,同時所有新的`I/O`塊都會被阻塞,直到臟數據被寫入磁盤。這通常是長`I/O`卡頓的原因,但這也是保證內存中不會存在過量臟數據的保護機制。
* `vm.dirty_background_bytes`和`vm.dirty_bytes`是另一種指定這些參數的方法。如果設置`_bytes`版本,則`_ratio`版本將變為0,反之亦然。
* vm.dirty_expire_centisecs:指定臟數據能存活的時間。在這里它的值是30秒。當后臺進程在運行的時候,他們會檢查是否有數據超過這個時限,如果有則會把它異步地寫到磁盤中。
* vm.dirty_writeback_centisecs:指定多長時間后臺進程會喚醒一次,然后檢查是否有緩存需要清理。
**修改系統配置**
~~~
vim /etc/sysctl.conf
~~~
重新生效
~~~
sysctl -p
~~~
2. 查看臟頁數據:
~~~
cat /proc/vmstat | egrep "dirty|writeback"
~~~
或者使用`pcstat`查看,
### 安裝pcstat
1. 如果沒有go環境需要先安裝golang環境
官網下載安裝包:[Downloads - The Go Programming Language](https://go.dev/dl/),解壓
~~~
tar -zxvf goxxx.tar.gz
~~~
2. 添加環境變量
~~~
vim /etc/profile
~~~
~~~
export GO_HOME=go的解壓地址/go
export PATH=$PATH:$GO_HOME/bin
# 國內
export GOPROXY=https://goproxy.io
export GO111MODULE=on
~~~
~~~
source /etc/profile
~~~
3. 安裝pcstat
官方地址:[tobert/pcsta(github.com)](https://github.com/tobert/pcstat),閱讀一下Readmd.md安裝即可。
4. 使用
注意`pcstat`命令需要放于環境變量中,這里我放到了go的bin目錄下。
:-: 
- 第一章 Java基礎
- ThreadLocal
- Java異常體系
- Java集合框架
- List接口及其實現類
- Queue接口及其實現類
- Set接口及其實現類
- Map接口及其實現類
- JDK1.8新特性
- Lambda表達式
- 常用函數式接口
- stream流
- 面試
- 第二章 Java虛擬機
- 第一節、運行時數據區
- 第二節、垃圾回收
- 第三節、類加載機制
- 第四節、類文件與字節碼指令
- 第五節、語法糖
- 第六節、運行期優化
- 面試常見問題
- 第三章 并發編程
- 第一節、Java中的線程
- 第二節、Java中的鎖
- 第三節、線程池
- 第四節、并發工具類
- AQS
- 第四章 網絡編程
- WebSocket協議
- Netty
- Netty入門
- Netty-自定義協議
- 面試題
- IO
- 網絡IO模型
- 第五章 操作系統
- IO
- 文件系統的相關概念
- Java幾種文件讀寫方式性能對比
- Socket
- 內存管理
- 進程、線程、協程
- IO模型的演化過程
- 第六章 計算機網絡
- 第七章 消息隊列
- RabbitMQ
- 第八章 開發框架
- Spring
- Spring事務
- Spring MVC
- Spring Boot
- Mybatis
- Mybatis-Plus
- Shiro
- 第九章 數據庫
- Mysql
- Mysql中的索引
- Mysql中的鎖
- 面試常見問題
- Mysql中的日志
- InnoDB存儲引擎
- 事務
- Redis
- redis的數據類型
- redis數據結構
- Redis主從復制
- 哨兵模式
- 面試題
- Spring Boot整合Lettuce+Redisson實現布隆過濾器
- 集群
- Redis網絡IO模型
- 第十章 設計模式
- 設計模式-七大原則
- 設計模式-單例模式
- 設計模式-備忘錄模式
- 設計模式-原型模式
- 設計模式-責任鏈模式
- 設計模式-過濾模式
- 設計模式-觀察者模式
- 設計模式-工廠方法模式
- 設計模式-抽象工廠模式
- 設計模式-代理模式
- 第十一章 后端開發常用工具、庫
- Docker
- Docker安裝Mysql
- 第十二章 中間件
- ZooKeeper