爆笑教程《看表情包學(xué)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...?
?? 本篇博客全站熱榜排名:未上榜
Ⅰ. 系統(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_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
?下面我們就來介紹一下這兩個選項!
0x01?O_TRUNC 截斷清空(對標(biāo) w)
?在我們打開文件時,如果帶上 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é)果如下:
然而??語言的 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é)果如下:
?我們再來對照 ?語言的 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é)果如下:
Ⅱ. 文件描述符(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。
那為什么接收 open 的返回值的變量要叫 fd 呢?
這個 fd 究竟是何方神圣?我們現(xiàn)在就揭開其神秘面紗,一睹芳容!它就是……
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é)果如下:
我們發(fā)現(xiàn)這 open 的 5 個文件的??(返回值)?分別是 ?,那么問題了來了:
?① 為什么從 3 開始,而不是從 0 開始?0, 1, 2 去哪了?
- 0:標(biāo)準(zhǔn)輸入(鍵盤,stdin)
- 1:標(biāo)準(zhǔn)輸出(顯示器,stdout)
- 2:標(biāo)準(zhǔn)錯誤(顯示器,stderr)
?系統(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)系呢?
?想解決這個問題,我們得先說說 :
我們知道,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 "
?因此, 內(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é)果如下:
?
?? 代碼驗證: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é)果如下:
(1 和 2 的區(qū)別我們放到后面再講)
?至此,我們證明了 ——
每次我們打開文件雖然打開的是 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é)果如下:
" 這……就是透過現(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)提供的返回值。
?既然操作系統(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)我們用鏈表的形式鏈接起來:
?如此一來,對被打開的文件的管理,就轉(zhuǎn)化成為了對鏈表的增刪改查!
"這一幕怎么有些似曾相識?我們之前講進程好像就是這么講的!task_struct!"
進程與打開的文件之比為 ,進程能打開這么多文件,那么:
進程如何和打開的文件建立映射關(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。
?此時,我們就建立起了 "進程" 和 "文件" 之間映射關(guān)系的橋梁。
?? 看圖理解:在內(nèi)核中實現(xiàn)的映射關(guān)系
?如此一來,進程想訪問某一個文件,只需要知道該文件在這張映射表中的數(shù)組下標(biāo)。
上面這些就是在內(nèi)核中去實現(xiàn)的映射關(guān)系了!這個下標(biāo) 0,1,2,3,4 就是對應(yīng)的文件描述符 ?!
我們調(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 下一切皆文件" 。
?在這之前我們先說個題外話,其實 ?語言也是可以模擬面向?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...) {
// 代碼
}
C++ 本身就是從 C 語言衍生出來的,并不是 "萬丈高樓平地起" 的。
是大量工程實戰(zhàn)后不斷積累的產(chǎn)物,所以 C++ 的面向?qū)ο髮嶋H上在 C 中也能實現(xiàn)。
我們舉個例子:我們在計算機中,有各種硬件:鍵盤、顯示器、磁盤、網(wǎng)卡、其他硬件...
對我們現(xiàn)階段而言,這些設(shè)備我們統(tǒng)一稱之為 "外設(shè)",下面我們來看圖。
?? 看圖理解:注意,下圖的 "上層" 是剛才演示的 "映射關(guān)系圖"?
深灰色層:對應(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è)備,往上我們就看作 "一切皆文件" !
也就是說:如果想打開一個文件,打開之后把讀寫方法屬性交給 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)的讀寫方法指向的是什么方法!
?這操作是不是感覺很熟悉!?
多態(tài)?C++ 中運行時多態(tài)用的虛表和虛函數(shù)指針,那不就是函數(shù)指針么?
"上層使用同一對象,指針指向不同的對象,最終就可以調(diào)用不同的方法"
這令人拍手叫絕的操作,你可以理解為:多態(tài)的前身
?? 補充:上面畫的圖,在往上走,就回到了內(nèi)核的映射關(guān)系了:
?這里的?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)之間提供了一個交換層。
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ū)等) 。
?? [ 筆者 ]? ?王亦優(yōu)
?? [ 更新 ]? ?2023.3.24
? [ 勘誤 ]?? /* 暫無 */
?? [ 聲明 ]? ?由于作者水平有限,本文有錯誤和不準(zhǔn)確之處在所難免,
本人也很想知道這些錯誤,懇望讀者批評指正!
?? 參考資料? C++reference[EB/OL]. []. http://www.cplusplus.com/reference/. Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .文章來源:http://www.zghlxwxcb.cn/news/detail-782348.html 百度百科[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)!