文件系統(tǒng)之文件描述符

Linux文件系統(tǒng)結(jié)構(gòu)

調(diào)用Open函數(shù)會發(fā)生什么

對同一個文件打開多次會怎樣

父子進程的文件關(guān)系

重定向的實現(xiàn)

管道的實現(xiàn)


概述

int fd = open(pathname, flags, mode);

關(guān)于文件讀取與寫入,我們總是能用到open函數(shù),返回一個文件描述符,然后就可以對fd進行操作。同樣,調(diào)用socket accept函數(shù)也會返回一個fd。所以問題在于Linux是如何處理fd,使得我們可以處理真正的磁盤IO。



Linux文件系統(tǒng)結(jié)構(gòu)


Linux文件系統(tǒng)表


1)進程級文件描述符表 Process File Table

2)系統(tǒng)級打開文件表 System File Table

3)系統(tǒng)i-Node表


調(diào)用Open函數(shù)會發(fā)生什么

每次open時,會在進程文件描述符表新增數(shù)據(jù)(一個int型fd 和一個指針),指針指向系統(tǒng)打開文件表。系統(tǒng)文件表會表明這個打開文件的權(quán)限(status 讀、寫等),當(dāng)前打開文件的偏移量(offset 即下次讀取時的位置),指向系統(tǒng)i-Node表的指針等。因此我們可以知道,fd是針對進程的概念,不同進程的相同fd很大可能并沒有任何關(guān)系



對同一個文件打開多次會怎樣

Process A:?

fd1 = open("/var/file1", O_RDONLY);?

fd2 = open("/var/file2", O_RDWR);?

fd3 = open("/var/file1", O_WRONLY);

Process B:?

fd1 = open("/var/file1", O_RDONLY);?

fd2 = open("/var/file3", O_RDONLY);


A/B兩個進程調(diào)用多次open后

不管是相同進程還是不同進程,只要調(diào)用open就會有一個新的fd和一個新的系統(tǒng)打開文件表的對應(yīng)項,所以對這些fd進行讀取操作并不會造成相互影響。因為系統(tǒng)文件表是獨立的,offset也是獨立的



父子進程的文件關(guān)系


調(diào)用fork()后

調(diào)用fork后,雖然父子進程都有獨立的進程文件描述符表,但所有fd所對應(yīng)的文件表都會保持完全一致,因此當(dāng)我們在子進程讀取fd1時,父進程的file offset也會同時變化,也就造成了一些奇怪的現(xiàn)象,所以對待fd的讀寫要謹慎處理



重定向的實現(xiàn)


重定向調(diào)用dup后

dup2(close_this_fd = open("my.txt", O_WRONLY), 1);

程序的輸出會直接輸出到標(biāo)準(zhǔn)輸出,但以上語句會將現(xiàn)有進程的標(biāo)準(zhǔn)輸出(fd = 1)重定向到my.txt對應(yīng)的文件表。因此輸出后,my.txt將會展示剛才程序的輸出。這也就是 out > my.txt的實現(xiàn)



管道的實現(xiàn)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void){
????int pfds[2];
? ? pipe(pfds);
? ? ?if (!fork()) {
? ? ????????close(1); /* close normal stdout */
?????????????dup(pfds[1]); /* make stdout same as pfds[1] */
?????????????close(pfds[0]); /* we don't need this */
?????????????execlp("ls", "ls", NULL);
????} else {
?????????close(0); /* close normal stdin */
?????????dup(pfds[0]); /* make stdin same as pfds[0] */
?????????close(pfds[1]); /* we don't need this */
?????????execlp("grep", "SOMETHING", NULL);
????}
????return 0;

}


pipe管道

管道的總體原理就是(ls | grep)

1)A/B兩個進程,B進程是A的子進程,A進程執(zhí)行l(wèi)s?,B進程執(zhí)行g(shù)rep

2)將A進程的標(biāo)準(zhǔn)輸出通過dup2命令重定向到一個buffer區(qū)

3)B進程的標(biāo)準(zhǔn)輸入通過dup2重定向到同一個buffer區(qū)

4)B進程獲取到A進程的輸出并執(zhí)行自己的邏輯

參考文章

File System, Kernel Data Structures, and Open Files

inode and file descriptor table Interaction

Linux文件描述符

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.文件描述符 所有執(zhí)行I/O操作的系統(tǒng)調(diào)用都以文件描述符(一個非負整數(shù))來指代打開的文件。文件描述符用以表示所有...
    666真666閱讀 1,223評論 0 2
  • 系統(tǒng)管理與維護命令 date date(選項)(參數(shù)) | 選項 | 說明 | | :-------- | ...
    蓓蓓的萬能男友閱讀 4,180評論 0 5
  • 第三章 文件i/o 3.1引言 不帶緩沖的io(unix系統(tǒng)在內(nèi)核中設(shè)有緩沖區(qū),這個不帶緩沖意思是用戶不自己緩沖)...
    m風(fēng)滿樓閱讀 1,072評論 0 0
  • 再怎么不承認,自己都像是怎么壓都注定沒結(jié)果的干枯的水井,腦子潛移默化的被僵尸吃掉了。慢慢的變俗
    嘎嘎嘎嘎鴨閱讀 302評論 0 0
  • 我曾經(jīng)是一個討厭飯局的人。但飯局無時不刻占據(jù)著我們的日常。約飯的難題在于勇氣,作為一個疏于經(jīng)營人際關(guān)系的我,鎖定了...
    壹婉閱讀 463評論 2 3

友情鏈接更多精彩內(nèi)容