国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【看表情包學(xué)Linux】初識文件描述符 | 虛擬文件系統(tǒng) (VFS) 初探 | 系統(tǒng)傳遞標(biāo)記位 | O_TRUNC | O_APPEND

這篇具有很好參考價值的文章主要介紹了【看表情包學(xué)Linux】初識文件描述符 | 虛擬文件系統(tǒng) (VFS) 初探 | 系統(tǒng)傳遞標(biāo)記位 | O_TRUNC | O_APPEND。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符爆笑教程《看表情包學(xué)Linux》?? 猛戳訂閱!?????o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

?? 寫在前面:通過上一章節(jié)的講解,想必大家已對文件系統(tǒng)基本的接口有一個簡單的了解,本章我們將繼續(xù)深入講解,繼續(xù)學(xué)習(xí)系統(tǒng)傳遞標(biāo)志位,介紹 O_WRONLY, O_TRUNC, O_APPEND 和 O_RDONLY。之后我們就正是打開文件描述符 fd 的大門了,之前我們所探討講解的系統(tǒng)文件操作,都是為了給文件描述符做鋪墊的,可見這這一塊知識點是相當(dāng)?shù)闹匾T挷欢嗾f,讓我們正式開始本章的學(xué)習(xí)!

?? 本章目錄:

Ⅰ. 系統(tǒng)傳遞標(biāo)記位

0x00 引入:O_WRONLY 沒有像 w 那樣完全覆蓋?

0x01?O_TRUNC 截斷清空(對標(biāo) w)

0x02? O_APPEND 追加(對標(biāo) a)

0x03 O_REONLY 讀取

Ⅱ. 文件描述符(fd)

0x00 引入:open 參數(shù)的返回值

0x01 文件描述符的底層理解

0x02 理解:Linux 下一切皆文件

0x03 初識 VFS(虛擬文件系統(tǒng))

0x04 回頭看問題:fd 的 0,1,2,3...?

?o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符? 本篇博客全站熱榜排名:未上榜


Ⅰ. 系統(tǒng)傳遞標(biāo)記位

0x00 引入:O_WRONLY 沒有像 w 那樣完全覆蓋?

?語言在 ?模式打開文件時,文件內(nèi)容是會被清空的,但是 O_WRONLY 好像并非如此?

?? 代碼演示:當(dāng)前我們的 log.txt 內(nèi)有 5 行數(shù)據(jù),現(xiàn)在我們執(zhí)行下面的代碼:

int main(void)
{
    umask(0);
    // 當(dāng)我們只有 O_WRONLY 和 O_CREAT 時
    int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);
    if (fd < 0) {
        perror("open"); 
        return 1;
    }
    printf("fd: %d\n", fd); 
    
    // 修改:向文件寫入 2 行信息
    int cnt = 0;
    const char* str = "666\n";  // 修改:內(nèi)容改成666(方便辨識)
    while (cnt < 2) {
       write(fd, str, strlen(str));
       cnt++;
    }

    close(fd);

    return 0;
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

? 疑點:O_WRONLY?怎么沒有像 w 那樣完全覆蓋???

我們以前在 ?語言中,w 會覆蓋把全部數(shù)據(jù)覆蓋,每次執(zhí)行代碼可都是會清空文件內(nèi)容的。?

而我們的 O_WRONLY 似乎沒有全部覆蓋,曾經(jīng)的數(shù)據(jù)被保留了下來,并沒有清空!

其實,沒有清空根本就不是讀寫的問題,而是取決于有沒有加 O_TRUNC 選項!

因此,只有?O_WRONLY 和?O_CREAT 選項是不夠的:

  • 如果想要達到 w 的效果還需要增添 O_TRUNC
  • 如果想到達到 a 的效果還需要 O_APPEND

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?下面我們就來介紹一下這兩個選項!

0x01?O_TRUNC 截斷清空(對標(biāo) w)

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?在我們打開文件時,如果帶上 O_TRUNC 選項,那么它將會清空原始文件。

如果文件存在,并且打開是為了寫入,O_TRUNC 會將該文件長度縮短 (truncated) 為 0。

也就是所謂的 截斷清空 (Truncate Empty)?,我們默認(rèn)情況下文件系統(tǒng)調(diào)用接口不會清空文件的,

但如果你想清空,就需要給?open() 接口?帶上 O_TRUNC 選項:

?? 代碼演示:open() 達到 fopen"w" 模式的效果

int main(void)
{
    umask(0);
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if (fd < 0) {
        perror("open"); 
        return 1;
    }
    printf("fd: %d\n", fd); 
    
    // 向文件寫入 2 行信息
    int cnt = 0;
    const char* str = "666\n";
    while (cnt < 2) {
       write(fd, str, strlen(str));
       cnt++;
    }

    close(fd);

    return 0;
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

然而??語言的 fopen 函數(shù),只需要淺淺地標(biāo)上一個 "w" 就能搞定了:

fopen("log.txt", "w");

調(diào)一個 w 就以寫的方式打開了,不存在會自動創(chuàng)建,并且會完全覆蓋原始內(nèi)容,是如此的簡單!

它對應(yīng)的底層 open 調(diào)用,調(diào)用接口所傳入的選項就是 O_WRONLY,?O_CREAT, O_TRUNC。

由此可見,?的 fopen?是多么的好用!open 不僅要傳這么多選項,而且屬性也要設(shè)置:

open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
fopen("log.txt", "w");

0x02? O_APPEND 追加(對標(biāo) a)

上一章我們復(fù)習(xí)了 a 模式,?語言中我們以 a 模式打開文件做到追加的效果。

現(xiàn)在我們用 open,追加是不清空原始內(nèi)容的,所以我們不能加 O_TRUNC,得加 O_APPEND

int fd = open("log.txt", O_WRONLY | O_CREATE | O_APPEND, 0666);

?? 代碼演示:open() 達到 fopen"a" 模式的效果

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
    umask(0);
    int fd = open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
    if (fd < 0) {
        perror("open"); 
        return 1;
    }
    printf("fd: %d\n", fd); 
    
    // 向文件寫入 2 行信息
    int cnt = 0;
    const char* str = "666\n";
    while (cnt < 2) {
       write(fd, str, strlen(str));
       cnt++;
    }

    close(fd);

    return 0;
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?我們再來對照 ?語言的 fopen,想做到這樣的效果只需要一個 "a"

open("log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
fopen("log.txt", "a");

實際上,系統(tǒng)級別的接口本來就是被文件接口封裝的,fopen 是系統(tǒng)級文件接口的底層實現(xiàn)。

我們的 a, w, r... 在底層上實際上就是這些 "O_" 組合而成的,使用系統(tǒng)接口麻煩嗎?

當(dāng)然麻煩!要記這么多東西,當(dāng)然還是 C 語言用的更爽了,一個字母標(biāo)明文件模式就行了。

0x03 O_REONLY 讀取

如果我們想讀取一個文件,那么這個文件肯定是存在的,我們傳 O_RDONLY 選項:

int main()
{
    umask(0);

    int fd = open("log.txt", O_RDONLY);
    if (fd < 0) {
        perror("open");
        return 1;
    }

    printf("fd: %d\n", fd);

    char buffer[128];
    ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
    if (s > 0) {
        buffer[s] = '\0';  // 最后字符串序列設(shè)置為 '\0' 
        printf("%s", buffer);
    }


    close(fd);   
    
    return 0;
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

Ⅱ. 文件描述符(fd)

0x00 引入:open 參數(shù)的返回值

int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);

我們使用 open 函數(shù)舉的例子中,一直是用一個叫做 fd?的變量去接收的。

fopen 中我們習(xí)慣使用 fp?/?pf?接收返回值,那是因為是 fopen 的返回值? FILE* 是文件指針,

file pointer 的縮寫即是?fp,所以我們就習(xí)慣將這個接收 fopen 返回值的變量取名為 fp?/?pf

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符那為什么接收 open 的返回值的變量要叫 fd 呢?

這個 fd 究竟是何方神圣?我們現(xiàn)在就揭開其神秘面紗,一睹芳容!它就是……

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

open 如果調(diào)用成功會返回一個新的 文件描述符 (file descriptor) ,如果失敗會返回 -1?。

  • ?:失敗 (success)
  • ?:成功 (failed)

?? 代碼演示:我們現(xiàn)在多打開幾個文件,觀察 fd 的返回值

int main(void)
{
    int fd_1 = open("log1.txt", O_WRONLY | O_CREAT, 0666);
    int fd_2 = open("log2.txt", O_WRONLY | O_CREAT, 0666);
    int fd_3 = open("log3.txt", O_WRONLY | O_CREAT, 0666);
    int fd_4 = open("log4.txt", O_WRONLY | O_CREAT, 0666);
    int fd_5 = open("log5.txt", O_WRONLY | O_CREAT, 0666);

    printf("fd_1: %d\n", fd_1); 
    printf("fd_2: %d\n", fd_2); 
    printf("fd_3: %d\n", fd_3); 
    printf("fd_4: %d\n", fd_4); 
    printf("fd_5: %d\n", fd_5); 
    
    close(fd_1);
    close(fd_2);
    close(fd_3);
    close(fd_4);
    close(fd_5);

    return 0;
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

我們發(fā)現(xiàn)這 open 的 5 個文件的??(返回值)?分別是 ?,那么問題了來了:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符? 為什么從 3 開始,而不是從 0 開始?0, 1, 2 去哪了?

  • 0標(biāo)準(zhǔn)輸入(鍵盤,stdin)
  • 1標(biāo)準(zhǔn)輸出(顯示器,stdout)
  • 2標(biāo)準(zhǔn)錯誤(顯示器,stderr)

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?系統(tǒng)接口認(rèn)的是外設(shè),而? 標(biāo)準(zhǔn)庫函數(shù)認(rèn)的是:

#include <stdio.h>

extern FILE* stdin;
extern FILE* stdout;
extern FILE* stderr;

系統(tǒng)調(diào)用接口!那么 stdin, stdout, stderr 和上面的 0,1,2 又有什么關(guān)系呢?

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?想解決這個問題,我們得先說說 :

我們知道,FILE* 是文件指針,那么? 是什么呢?它是 ?庫提供的結(jié)構(gòu)體。

只要是結(jié)構(gòu)體,它內(nèi)部一定封裝了多個成員!

雖然 ?用的是 FILE*,但是系統(tǒng)的底層文件接口只認(rèn) ,也就是說:

?標(biāo)準(zhǔn)庫調(diào)用的系統(tǒng)接口,對文件操作而言,系統(tǒng)接口只認(rèn)文件描述符。

" 文件操作的系統(tǒng)接口屬于是六親不認(rèn),只認(rèn) fd "

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?因此, 內(nèi)部必定封裝了文件操作符??!

下面我們來驗證一下,先驗證 0,1,2 就是標(biāo)準(zhǔn)

?? 代碼驗證:0 是標(biāo)準(zhǔn)輸入 (stdin)

int main(void)
{
    // 驗證 0,1,2 就是標(biāo)準(zhǔn) I/O
    char buffer[1024];
    ssize_t s = read(0, buffer, sizeof(buffer) - 1);

    if (s > 0) {
        buffer[s] = '\0';

        printf("echo: %s", buffer);
    }
}

?? 運行結(jié)果如下:

?o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

?? 代碼驗證:stdout?標(biāo)準(zhǔn)寫入(1) 和 stderr 錯誤寫入(2) :

int main(void)
{
    const char* s = "Hello, write something\n";
    write(1, s, strlen(s));  // 1:向標(biāo)準(zhǔn)輸入寫入
    write(2, s, strlen(s));  // 2:向標(biāo)準(zhǔn)錯誤寫入
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

(1 和 2 的區(qū)別我們放到后面再講)

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?至此,我們證明了 ——

每次我們打開文件雖然打開的是 3,但是可以像 3,4,5,6…… 去寫,默認(rèn)系統(tǒng)就會幫我們打開:

0 (標(biāo)準(zhǔn)輸入, stdin) ,1 (標(biāo)準(zhǔn)輸出, stdout),2 (錯誤輸出, stderr)?

下面我們要做的是,驗證一下 0,1,2 和 stdin, stdout 和 stderr 的對應(yīng)關(guān)系。

根據(jù)我們目前的分析, 本來就是一個結(jié)構(gòu)體, 因為系統(tǒng)只認(rèn)?,

所以??語言本身調(diào)用的一定是系統(tǒng)結(jié)構(gòu),這就直接決定了不管怎么封裝,底層必須有?!

?? 代碼驗證:下面我們就來證明??的存在,證明 stdin, stdout 和 stderr 的對應(yīng)關(guān)系

int main(void)
{
    printf("stdin: %d\n", stdin->_fileno);
    printf("stdout: %d\n", stdout->_fileno);
    printf("stderr: %d\n", stderr->_fileno);
}

?? 運行結(jié)果如下:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

" 這……就是透過現(xiàn)象看本質(zhì)!"

函數(shù)接口的對應(yīng):fopen / fclose / fread / fwrite? ? open / close / read / write

數(shù)據(jù)類型的對應(yīng):(FILE*FILE) →?

?? 結(jié)論:我們用的 ?語言接口一定封裝了系統(tǒng)調(diào)用接口!

? 這個 0, 1, 2, 3, 4, 5……,是不是有點像數(shù)組下標(biāo)?

" 咳咳……不是有點像,它就是數(shù)組下標(biāo)!"

剛才返回 ?的,用的都是系統(tǒng)接口,是操作系統(tǒng)提供的返回值。

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?既然操作系統(tǒng)能給你,那說明操作系統(tǒng)內(nèi)部是有的。

文件描述符的值為什么是 1,2,3,4,5... ?為了理解這個問題,我們需要做大量的鋪墊!

0x01 文件描述符的底層理解

?? 邏輯推導(dǎo):進程:內(nèi)存文件的關(guān)系 →?內(nèi)存 → 被打開的文件實在內(nèi)存里面的

一個進程可以打開多個文件,所以在內(nèi)核中,進程與打開的文件之比為:

所以系統(tǒng)在運行中,有可能會存在大量的被打開的文件 → OS 要對這些被打開的文件進行管理!

OS 如何管理這些被打開的文件呢?還是我們老生常談的那句話:

先描述,再組織!

所以對我們來說,一個文件被打開不要片面的認(rèn)為只是對文件內(nèi)容動動手腳!

它還要 在內(nèi)核中創(chuàng)建被打開文件的內(nèi)核數(shù)據(jù)結(jié)構(gòu)?—— 先描述

struct file {
    // 包含了你想看到的文件的所有大部分 內(nèi)容 + 屬性
    
    struct file* next;
    struct file* prev;
};

* 注:上面的代碼是便于理解的,可不是內(nèi)核真正的代碼,真的可遠比這復(fù)雜得多!

如果你在內(nèi)核中打開了多個的文件,那么系統(tǒng)會在內(nèi)核中為文件創(chuàng)建一個 struct file 結(jié)構(gòu)。

可以通過 next prev 將其前后關(guān)聯(lián)起來(內(nèi)核的鏈表結(jié)構(gòu)有它自己的設(shè)計,這里我們不關(guān)注)。

既然你打開了一個文件,就會創(chuàng)建一個 struct file,那么你打開多個文件,

系統(tǒng)中必然會存在大量的 struct file,并且該結(jié)構(gòu)我們用鏈表的形式鏈接起來:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?如此一來,對被打開的文件的管理,就轉(zhuǎn)化成為了對鏈表的增刪改查!

"這一幕怎么有些似曾相識?我們之前講進程好像就是這么講的!task_struct!"

進程與打開的文件之比為 ,進程能打開這么多文件,那么:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符進程如何和打開的文件建立映射關(guān)系?打開的文件哪一個屬于我的進程呢?

在內(nèi)核中,task_struct 在自己的數(shù)據(jù)結(jié)構(gòu)中包含了一個 struct files_struct *files?(結(jié)構(gòu)體指針):

struct files_struct *files;

而我們剛才提到的 "數(shù)組" 就在這個 file_struct 里面,該數(shù)組是在該結(jié)構(gòu)體內(nèi)部的一個數(shù)組。

struct file* fd_array[];

該數(shù)組類型為 struct file* 是一個 指針數(shù)組,里面存放的都是指向 struct file 的指針!

" 指向 struct file 的指針!是不是恍然大悟?這不就是文件的 stuct file 結(jié)構(gòu)么?沒錯!"

數(shù)組元素映射到各個被打開的文件,直接指向?qū)?yīng)的文件結(jié)構(gòu),若沒有指向就設(shè)為 NULL。

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?此時,我們就建立起了 "進程" 和 "文件" 之間映射關(guān)系的橋梁。

?? 看圖理解:在內(nèi)核中實現(xiàn)的映射關(guān)系

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

?如此一來,進程想訪問某一個文件,只需要知道該文件在這張映射表中的數(shù)組下標(biāo)。

上面這些就是在內(nèi)核中去實現(xiàn)的映射關(guān)系了!這個下標(biāo) 0,1,2,3,4 就是對應(yīng)的文件描述符 ?!

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符我們調(diào)用的 open / read / write / close 接口都需要?:

" 可以理解為買彩票,由于關(guān)系復(fù)雜就不給大家講故事了,自行理解"

?選號:當(dāng)我們 open 打開一個新的文件時,先創(chuàng)建 struct file,然后在當(dāng)前的文件描述表中分配一個沒有被使用的下標(biāo),把 stuct file 結(jié)構(gòu)體的地址填入?struct file* 中,然后通過 open 將對應(yīng)的??返回給用戶,比如?3,此時我們的 ?變量接收的 open 的返回值就是 3 了。

?兌獎:后續(xù)用戶再調(diào)用 read, write 這樣的接口一定傳入了對應(yīng)的?,找到了特定進程的 files,在根據(jù)對應(yīng)的??索引到指針數(shù)組,通過 sturct file* 中存儲的 struct file 結(jié)構(gòu)體地址,找到文件對象,之后就可以對相關(guān)的操作了。

?? 總結(jié):其本質(zhì)是因為它是一個數(shù)組下標(biāo),系統(tǒng)中使用指針數(shù)組的方式,建立進程和文件之間的關(guān)系。將 ?返回給上層用戶,上層用戶就可以調(diào)用后續(xù)接口 (read, write...) 來索引對應(yīng)的指針數(shù)組,找到對應(yīng)文件,這就是??為什么是 0,1,2... 的原因了!

0x02 理解:Linux 下一切皆文件

我們上面說的 0,1,2 → stdin, stdout, stderr → 鍵盤, 顯示器, 顯示器,這些都是硬件???

也用你上面講的 struct file 來標(biāo)識對應(yīng)的文件嗎?在解答這個問題之前,我們需要講清楚:

" Linux 下一切皆文件 "

一切皆文件這個話題在之前的章節(jié)我們已經(jīng)提過了,但是當(dāng)時由于知識點尚未展開,沒法講解。

現(xiàn)在我們到了去講解這個概念的時侯了,希望大家可以嘗試去理解 "Linux 下一切皆文件" 。

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?在這之前我們先說個題外話,其實 ?語言也是可以模擬面向?qū)ο蟮模?/p>

?? 代碼演示:在 ?中用 struct?模擬面向?qū)ο?/p>

struct file {
    // 對象的是屬性
    // 函數(shù)指針
    void *(readp)(struct file* filep, int fd ...);
    void *(writep)(struct file* filep, int fd...);
};

void read(struct file* filep, int fd...) {
    // 邏輯代碼
}

void write(struct file* filep, int fd...) {
    // 代碼
}

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符C++ 本身就是從 C 語言衍生出來的,并不是 "萬丈高樓平地起" 的。

是大量工程實戰(zhàn)后不斷積累的產(chǎn)物,所以 C++ 的面向?qū)ο髮嶋H上在 C 中也能實現(xiàn)。

我們舉個例子:我們在計算機中,有各種硬件:鍵盤、顯示器、磁盤、網(wǎng)卡、其他硬件...

對我們現(xiàn)階段而言,這些設(shè)備我們統(tǒng)一稱之為 "外設(shè)",下面我們來看圖。

?? 看圖理解:注意,下圖的 "上層" 是剛才演示的 "映射關(guān)系圖"?

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

深灰色層:對應(yīng)的設(shè)備和對應(yīng)的讀寫方法一定是不一樣的。

黑色層:看見的都是 struct file 文件(包含文件屬性, 文件方法),OS 內(nèi)的內(nèi)存文件系統(tǒng)。

紅色箭頭:再往上就是進程,如果想指向磁盤,通過 ?找到對應(yīng)的 struct file,根據(jù)對應(yīng)的 file 結(jié)構(gòu)調(diào)用讀寫方法,就可以對磁盤進行操作了。如果想指向?qū)?yīng)的顯示器,通過 fd 找到 struct file……最后調(diào)用讀寫,就可以對顯示器操作了…… 以此類推。

雖然指針指向的是差異化的代碼,但是在 深灰色層,我們看到的都是 struct file 文件對象!

在這一層我們 以統(tǒng)一的視角看待所有的設(shè)備,往上我們就看作 "一切皆文件" !

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符也就是說:如果想打開一個文件,打開之后把讀寫方法屬性交給 OS,

在內(nèi)核里給該硬件創(chuàng)建 stuct file,初始化時把對應(yīng)的函數(shù)指針指向具體的設(shè)備,

在內(nèi)核中存在的永遠都是 struct file,然后將 struct file 互相之間用鏈表關(guān)聯(lián)起來。

站在用戶的角度看,一個進程看待所有的文件都是以統(tǒng)一的視角看待的,

所以當(dāng)我們訪問一個 file 的時候,這個 file 具體指向底層的哪個文件或設(shè)備,

這完全取決于其底層對應(yīng)的讀寫方法指向的是什么方法!

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?這操作是不是感覺很熟悉!?

多態(tài)?C++ 中運行時多態(tài)用的虛表和虛函數(shù)指針,那不就是函數(shù)指針么?

"上層使用同一對象,指針指向不同的對象,最終就可以調(diào)用不同的方法"

這令人拍手叫絕的操作,你可以理解為:多態(tài)的前身

?? 補充:上面畫的圖,在往上走,就回到了內(nèi)核的映射關(guān)系了:

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符?這里的?struct file 指向的硬件設(shè)備是誰,就取決于底層的硬件是怎么設(shè)計的了。

通過操作系統(tǒng)層做了一層軟件封裝,達到了這樣的效果。

底層叫硬件,而 具體的硬件讀寫方法是驅(qū)動干的,具體的硬件讀寫是驅(qū)動程序要做的,

OS 只管跟外設(shè)要求其提供讀寫方法,最終 OS 在內(nèi)核中給它們抽象成 struct file,

把它們都看作文件,然后通過函數(shù)指針指向具體的文件對應(yīng)的設(shè)備,就完成了 "一切皆文件" !

0x03 初識 VFS(虛擬文件系統(tǒng))

上面說的這種設(shè)置一套 struct file 來表示文件的內(nèi)存文件系統(tǒng)的操作,

我們稱之為??(virtual file system) ,即 虛擬文件系統(tǒng) 。?

虛擬文件系統(tǒng)(VFS)是 Linux 內(nèi)核中非常有用的一個方面,因為它為文件系統(tǒng)提供了一個通用的接口抽象。VFS 在 SCI 和內(nèi)核所支持的文件系統(tǒng)之間提供了一個交換層。

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

0x04 回頭看問題:fd 的 0,1,2,3...?

至此,我們梳理完了?,F(xiàn)在我們再回過頭看 fd 的 1,2,3,4... 就能有一個清楚的認(rèn)識了。

現(xiàn)在我們再我們最開始的問題,想必大家已經(jīng)做到 "知其然知其所以然" 了!

為什么從 3 開始,而不是從 0 開始?0, 1, 2 去哪了?

?? stdin,stdout,stderr 和 0,1,2 是對應(yīng)關(guān)系,因為 open 時默認(rèn)就打開了,這也是為什么我們默認(rèn)打開一個新的文件,fd 是從 3 開始的而不是 0 開始的真正原因!

"突然茅塞頓開,上一章打印出 fd 是 3 的疑惑終于解決了!"

? 0, 1, 2, 3, 4……,是不是有點像數(shù)組下標(biāo)?

?? 不是有點像,它其實上就是數(shù)組下標(biāo)!fd 0,1,2,3,4...??在內(nèi)核中屬于進程和文件的對應(yīng)關(guān)系,是用數(shù)組來完成映射的,這些數(shù)字就是數(shù)組的下標(biāo)。read, write, close 這些接口都必須用 0,1,2,3,4?來找到底層對應(yīng)的 struct file 結(jié)構(gòu),進而訪問到底層對應(yīng)的讀寫方法 (包括相關(guān)的屬性,緩沖區(qū)等) 。

o_trunc,看表情包學(xué)Linux,服務(wù)器,linux,運維,文件描述符

?? [ 筆者 ]? ?王亦優(yōu)
?? [ 更新 ]? ?2023.3.24
? [ 勘誤 ]?? /* 暫無 */
?? [ 聲明 ]? ?由于作者水平有限,本文有錯誤和不準(zhǔn)確之處在所難免,
              本人也很想知道這些錯誤,懇望讀者批評指正!

?? 參考資料?

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.文章來源地址http://www.zghlxwxcb.cn/news/detail-782348.html

到了這里,關(guān)于【看表情包學(xué)Linux】初識文件描述符 | 虛擬文件系統(tǒng) (VFS) 初探 | 系統(tǒng)傳遞標(biāo)記位 | O_TRUNC | O_APPEND的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包