日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發布時間:2024/2/28 linux 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络与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:

上面這個測試說明了緩沖區的存在。在一段時間內,并沒有進行磁盤的刷寫。

總結

以上是生活随笔為你收集整理的网络与IO知识扫盲(一):Linux虚拟文件系统,文件描述符,IO重定向的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。