讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊、虛擬空間、營銷軟件、網(wǎng)站建設(shè)、江達(dá)網(wǎng)站維護(hù)、網(wǎng)站推廣。
1、文件共享的三種實(shí)現(xiàn)方式
1、什么是文件共享:
(1)文件共享就是同一個(gè)文件(同一個(gè)文件指的是同一個(gè)inode,同一個(gè)pathname)被多個(gè)獨(dú)立的讀寫體(幾乎可以理解為多個(gè)文件描述符)去同時(shí)(一個(gè)打開尚未關(guān)閉的同時(shí)另一個(gè)去操作)操作。
(2)文件共享的意義有很多:譬如我們可以通過文件共享來實(shí)現(xiàn)多線程同時(shí)操作同一個(gè)大文件,以減少文件讀寫時(shí)間,提升效率。
2、文件共享的核心就是怎么弄出來多個(gè)文件描述符指向同一個(gè)文件。
3、常見的三種文件共享情況:
1、是同一個(gè)進(jìn)程中多次使用open函數(shù)打開同一個(gè)文件。
2、不同進(jìn)程中分別使用open函數(shù)打開同一個(gè)文件(因?yàn)榇藭r(shí)兩個(gè)fd不在同意進(jìn)程中,所以兩個(gè)fd可能相同,也可能不同)。
3、linux提供的dup和dup2兩個(gè)API來讓進(jìn)程賦值文件描述符。
4、我們分析文件共享的核心關(guān)注點(diǎn)在于:分別寫、讀還是連續(xù)讀寫
補(bǔ)充:
再論文件描述符:
1、文件描述符的本質(zhì)是一個(gè)數(shù)字,這個(gè)數(shù)字本質(zhì)上是進(jìn)程表中文件描述符的一個(gè)表項(xiàng),進(jìn)程通過文件描述符作為index去索引查表得到文件表指針,再間接訪問得到這個(gè)文件對(duì)應(yīng)的文件表。
2、文件描述符這個(gè)數(shù)字是open系統(tǒng)調(diào)用內(nèi)部由操作系統(tǒng)自動(dòng)分配的,操作系統(tǒng)分配這個(gè)fd也不是隨機(jī)分配的,也會(huì)按照一定的規(guī)律。
3、操作系統(tǒng)規(guī)定,fd從0開始一次增加,fd也是有最大限制的,在linux的早期版本中fd最大只有20.linux中文件描述符表是一個(gè)數(shù)組(而不是鏈表),所以這個(gè)文件描述符表其實(shí)就是一個(gè)數(shù)組,fd是index,文件表指針是value
4、當(dāng)我們open時(shí),內(nèi)核會(huì)從文件描述符表中挑選一個(gè)最小的未被使用的數(shù)字給我們返回。
文件描述符的復(fù)制:
5、fd中0、1、2已經(jīng)默認(rèn)被系統(tǒng)占用了,當(dāng)我們運(yùn)行一個(gè)程序得到一個(gè)進(jìn)程時(shí),內(nèi)部就默認(rèn)已經(jīng)打開了3個(gè)文件,這三個(gè)文件對(duì)應(yīng)的fd就是0、1、2。這三個(gè)文件分別叫stdin、stdout、stderr。也就是標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤。因此用戶進(jìn)程得到的最小的fd就是3了。
6、標(biāo)準(zhǔn)輸入一般對(duì)應(yīng)的是鍵盤(可以理解為:0這個(gè)fd對(duì)應(yīng)的是鍵盤的設(shè)備文件),標(biāo)準(zhǔn)輸出一般是LCD顯示器(可以理解為:1對(duì)應(yīng)LCD的設(shè)備文件)
7、printf函數(shù)其實(shí)就是默認(rèn)輸出到標(biāo)準(zhǔn)輸出stdout上了。stdio中還有一個(gè)函數(shù)叫fpirntf,這個(gè)函數(shù)就可以指定輸出到哪個(gè)文件描述符中。
2、如何實(shí)現(xiàn)文件共享
1、同一個(gè)進(jìn)程中多次使用open函數(shù)打開同一個(gè)文件。同時(shí)打開同一個(gè)文件不難理解,關(guān)鍵在于打開同一個(gè)文件后,我們讀取寫入文件時(shí),是分別寫呢還是接續(xù)寫,簡單理解就是,覆蓋著寫呢?還是一個(gè)寫完了,文件指針自動(dòng)挪到后邊分開寫?我們不用去猜,記別人的理論,我們直接自己用代碼測試,只要代碼正確的情況測試的結(jié)果就是理論。下來我們來看測試代碼:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<errno.h> #include<fcntl.h> #include<string.h> typedef int file_t; #define MAXLENG 1024 int main(int argc,char *argv[]) { file_t fd1 = -1, fd2 = -1; fd1 = open("./1.txt",O_RDWR | O_TRUNC | O_CREAT,0644); if(fd1 < 0) { perror("fd1 :open file failed :"); _exit(-1); } fprintf(stdout,"fd1 = %d\n",fd1); //這里為了區(qū)別更明顯, fd2的open以及判斷完全可以放在fd1的判斷中去 fd2 = open("./1.txt",O_RDWR | O_TRUNC | O_CREAT,0644); if(fd2 < 0) { perror("fd2:open file fialed :"); _exit(-1); } fprintf(stdout,"fd2 = %d\n",fd2); while(1) { write(fd1,"aaaa",4); sleep(1); write(fd2,"bbbb",4); } return 0; }
這段代碼運(yùn)行完成以后,我們來看結(jié)果
[root@xiao_k filetest]# cat 1.txt bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaa[root@xiao_k filetest]#
這樣我們可以很容易看到,我們雖然是用兩個(gè)文件指針分別寫,但是fd1只有在最后一次寫進(jìn)去,對(duì)吧?這時(shí)我們看到的;但是這為什么會(huì)這樣呢?這里我們分析一下:其實(shí)fd1進(jìn)行了寫入操作,只是我們fd1和fd2兩個(gè)文件指針是不同的文件指針,當(dāng)fd1寫入以后,文件指針往后移動(dòng),但是fd2并沒有移動(dòng),當(dāng)fd2進(jìn)行寫入時(shí)就會(huì)覆蓋掉fd1寫入的內(nèi)容,并且這里與你兩次打開文件的屬性有關(guān),這里使用
O_RDWR | O_TRUNC | O_CREAT三個(gè)屬性打開,我們也可以自己測試其他屬性打開的結(jié)果。雖然不同屬性打開的結(jié)果可能造成的結(jié)果不同,但是我們這里是可以確定的,一個(gè)文件指針移動(dòng)后并不會(huì)造成另外一個(gè)文件指針移動(dòng)。
2、第二種方法用不同進(jìn)程中分別使用open函數(shù)打開同一個(gè)文件(因?yàn)榇藭r(shí)兩個(gè)fd不在同意進(jìn)程中,所以兩個(gè)fd可能相同,也可能不同)。這里還沒有總結(jié)fork函數(shù)產(chǎn)生新的進(jìn)程。所以先不總結(jié),博主后邊補(bǔ)充上去。
3、使用linux提供的dup和dup2兩個(gè)API來讓進(jìn)程賦值文件描述符。
1、使用dup進(jìn)行文件描述符復(fù)制
(1)dup系統(tǒng)調(diào)用對(duì)fd進(jìn)行復(fù)制,會(huì)返回一個(gè)新的文件描述符(譬如原來的fd是3,返回的就是4)
(2)dup系統(tǒng)調(diào)用有一個(gè)特點(diǎn),就是自己不能指定復(fù)制后得到的fd的數(shù)字是多少,而是由操作系統(tǒng)內(nèi)部自動(dòng)分配的,分配的原則遵守fd分配的原則。
(3)dup返回的fd和原來的oldfd都指向oldfd打開的那個(gè)動(dòng)態(tài)文件,操作這兩個(gè)fd實(shí)際操作的都是oldfd打開的那個(gè)文件。實(shí)際上構(gòu)成了文件共享。
(4)dup返回的fd和原來的oldfd同時(shí)向一個(gè)文件寫入時(shí),結(jié)果是分別寫還是接續(xù)寫?
使用dup的缺陷分析
(1)dup并不能指定分配的新的文件描述符的數(shù)字,dup2系統(tǒng)調(diào)用修復(fù)了這個(gè)缺陷,所以平時(shí)項(xiàng)目中實(shí)際使用時(shí)根據(jù)具體情況來決定用dup還是dup2.
2、使用dup2進(jìn)行文件描述符復(fù)制
(1)dup2和dup的作用是一樣的,都是復(fù)制一個(gè)新的文件描述符。但是dup2允許用戶指定新的文件描述符的數(shù)字。
(2)使用方法看man手冊函數(shù)原型即可。
測試使用dup和dup2共享文件操作:
1、dup共享文件的實(shí)現(xiàn)
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<errno.h> typedef int file_t; #define MAXSIZE 1024 int main(int argc,char *argv[]) { file_t fd1 = -1, fd2 = -1; fd1 = open("./3.txt",O_RDWR | O_CREAT | O_TRUNC,0644); if(fd1 < 0) { perror("open fiel error :"); _exit(-1); } fprintf(stdout,"fd1 = %d\n",fd1); fd2 = dup(fd1); if(-1 == fd2) { perror("dup error:"); _exit(-1); } fprintf(stdout,"fd2 = %d\n",fd2); while(1) { write(fd1,"aaaa",4); sleep(1); write(fd2,"bbbb",4); } return 0; }
我們繼續(xù)來看結(jié)果:
[root@xiao_k filetest]# cat 3.txt aaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaa aabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaabbbbaaaa [root@xiao_k filetest]#
從結(jié)果我們這次可以發(fā)現(xiàn)a和b是交替出現(xiàn)的,這也符合預(yù)期,dup雖然是產(chǎn)生了兩個(gè)文件描述符,但是共用同一個(gè)文件指針,當(dāng)一個(gè)寫入以后,文件指針已經(jīng)移動(dòng)到后邊去,自然不會(huì)覆蓋掉了。
2、dup2共享文件交叉寫入測試
1、對(duì)于dup2和dup寫入文件一樣,區(qū)別在于dup2可以自己指定文件描述符,所以這里就不給出dup2寫入文件的實(shí)例。
2、交叉寫入的時(shí)候,結(jié)果是接續(xù)寫
3、fcntl函數(shù)
1、fcntl函數(shù)是一個(gè)多功能文件管理的工具箱,可以接受2個(gè)參數(shù)+1個(gè)變參,第一個(gè)參數(shù)是fd表示喲啊操作那個(gè)文件,第二個(gè)參數(shù)是cmd表示要進(jìn)行那個(gè)命令操作。變參是用來傳遞參數(shù)的,要配合cmd命令使用
2、cmd的樣子類似于F_XXX,不同的cmd具有不同的功能。學(xué)習(xí)時(shí),沒有必要把所有的cmd含義弄清楚,只需要把一個(gè)弄明白就行,其他的查man手冊即可。
3、常用fcntl的cmd
1、F_DUPFD這個(gè)cmd的作用是復(fù)制文件描述符(作用類似于dup和dup2),這個(gè)命令的功能是從可用的fd數(shù)字列表中找一個(gè)比arg大或者和arg一樣大的數(shù)字作為oldfd的一個(gè)復(fù)制的fd,和dup2有點(diǎn)像但是不同。dup2返回的就是我們指定的那個(gè)newfd否則就會(huì)出錯(cuò),但是F_DUPFD命令返回的是>=arg的最小的那一個(gè)數(shù)字。
4、標(biāo)準(zhǔn)I/O庫
1、標(biāo)準(zhǔn)IO和文件IO有什么區(qū)別
1、最大的區(qū)別:標(biāo)準(zhǔn)I/O庫是C庫函數(shù),而文件I/O是linux系統(tǒng)調(diào)用的API
2、C語言庫函數(shù)是由API封裝起來的,庫函數(shù)內(nèi)部也是通過調(diào)用API來完成操作的,但是庫函數(shù)多了一層封裝,所以比API更加好用。
3、庫函數(shù)比API還有一個(gè)優(yōu)勢,API在不同的操作系統(tǒng)的接口是不一樣的是不能通用的,但是C庫函數(shù)在不同操作系統(tǒng)上幾乎是一樣的,所以C庫函數(shù)具有可移植性而API不具有可移植性。
2、常用標(biāo)準(zhǔn)IO函數(shù)介紹:
常見的標(biāo)準(zhǔn)IO庫函數(shù):fopen fclose fwrite fread ffulsh、fseek
以上文檔,本人學(xué)習(xí)參考了不同老師的文檔自己總結(jié)而來,代碼都是本人親自測試。關(guān)于文檔那塊有問題,請各位指正。
網(wǎng)站標(biāo)題:linux常用文件I/O操作之文件共享的實(shí)現(xiàn)方式
網(wǎng)頁網(wǎng)址:http://muchs.cn/article42/jpdjec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、網(wǎng)站建設(shè)、域名注冊、標(biāo)簽優(yōu)化、品牌網(wǎng)站建設(shè)、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)