一贿肩、I/O
- 對(duì)于Unix系統(tǒng)來說,所有IO設(shè)備龄寞,如磁盤汰规、鼠標(biāo)鍵盤、網(wǎng)卡物邑,一切皆文件溜哮。這樣的一個(gè)好處就是對(duì)于任何東西的輸入輸出,都可以抽象為對(duì)文件的讀和寫操作色解,即I/O茂嗓。
- 既然都可以抽象為對(duì)文件的IO操作,操作系統(tǒng)在Unix內(nèi)核上對(duì)外提供了一些Unix I/O調(diào)用科阎,包括open述吸、close、read锣笨、write蝌矛、lseek和stat。
- Unix I/O對(duì)于頻繁讀取某個(gè)IO設(shè)備一個(gè)字節(jié)的情景性能較低错英,因此大多數(shù)編程語言基于Unix IO提供了標(biāo)準(zhǔn)IO庫入撒,標(biāo)準(zhǔn)IO庫通過緩沖區(qū)的設(shè)計(jì)解決了頻繁讀取磁盤效率低下的問題。
二椭岩、文件
- 文件類型包含文本文件(linux以\n作為換行符)衅金、二進(jìn)制文件噪伊、目錄、套接字(socket)氮唯、命名管道鉴吹、符號(hào)鏈接、塊設(shè)備等惩琉。
- 當(dāng)進(jìn)程打開一個(gè)文件時(shí)豆励,如果調(diào)用成功,內(nèi)核返回一個(gè)描述符瞒渠,這個(gè)描述符是一個(gè)非負(fù)整數(shù)良蒸。linux shell創(chuàng)建的每個(gè)進(jìn)程開始時(shí)都有三個(gè)打開的文件:標(biāo)準(zhǔn)輸入(描述符0)、標(biāo)準(zhǔn)輸出(描述符1)伍玖、標(biāo)準(zhǔn)錯(cuò)誤(描述符2)嫩痰。
- 關(guān)閉文件時(shí),內(nèi)核會(huì)釋放在打開文件時(shí)創(chuàng)建的數(shù)據(jù)結(jié)構(gòu)窍箍,并將這個(gè)文件描述符恢復(fù)到可用的描述符池中串纺。
- 內(nèi)核用三個(gè)數(shù)據(jù)結(jié)構(gòu)表示打開的文件:
描述符表:每個(gè)進(jìn)程都有自己獨(dú)立的描述符表,表項(xiàng)的key是打開文件時(shí)內(nèi)核返回的描述符fd椰棘,value執(zhí)行文件表中的表項(xiàng)纺棺。
文件表:被所有進(jìn)程共享,表項(xiàng)中包含當(dāng)前文件位置(讀寫文件時(shí)用到)邪狞、引用計(jì)數(shù)(當(dāng)前被多少個(gè)描述符表引用)祷蝌、一個(gè)指向v-node表的指針。
v-node表:所有進(jìn)程共享帆卓,每個(gè)表項(xiàng)包含文件stat結(jié)構(gòu)中的大多數(shù)信息巨朦,比如文件大小、文件類型剑令、文件最近被訪問時(shí)間等糊啡。 - 一個(gè)進(jìn)程可以通過多個(gè)描述符訪問多個(gè)文件,也可以通過多個(gè)描述符訪問同一個(gè)文件尚洽,當(dāng)訪問同一個(gè)文件時(shí),由于不同文件表的文件位置不同靶累,因此不同文件描述符對(duì)同一個(gè)文件的讀寫互不影響腺毫。
- 文件共享:父子進(jìn)程共享文件,是因?yàn)樽舆M(jìn)程復(fù)制了父進(jìn)程的描述符表挣柬,所以父子進(jìn)程實(shí)際都指向了相同的文件表潮酒。
- I/O重定向:底層是通過dup2(oldFd, newFd)函數(shù)實(shí)現(xiàn),dup2函數(shù)會(huì)把oldFd表項(xiàng)復(fù)制到newFd表項(xiàng)邪蛔。
輸出重定向:dup(4, 1)急黎,會(huì)把原本要寫到標(biāo)準(zhǔn)輸出的描述符表項(xiàng)1指向4,因此后續(xù)輸出會(huì)寫到描述符4指向的文件。
輸入重定向:dup(4, 0)勃教,描述符4會(huì)覆蓋描述符0(標(biāo)準(zhǔn)輸入)淤击,因此原本從標(biāo)準(zhǔn)輸入讀取的操作會(huì)轉(zhuǎn)向從描述符4指向的文件讀取。