生活随笔
收集整理的這篇文章主要介紹了
共享文件的原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
內核用三個相關的數據結構來表示打開的文件:
描述符表:每個進程有它獨立的描述符表,表項由它打開的文件描述符來索引每個打開的描述符表項指向文件表中的一個表項
文件表:打開文件的集合是由一張文件表來表示的,所有進程共享這一張表
v-node 表:同文件表一樣,所有進程共享這一張v-node表。
如圖是兩種常見的引用方式,打開不同文件和同一文件。無論是哪一種描述符指向的文件表都是獨立的,互不干擾的。
dup2(fd1,fd2)常用函數:I/O重定向函數將fd2將指向fd1所指向的文件表
接下來看幾個例子
例1
#include "csapp.h"
int main(int argc
, char *argv
[])
{int fd1
, fd2
, fd3
;char c1
, c2
, c3
;char *fname
= argv
[1];fd1
= Open(fname
, O_RDONLY
, 0);fd2
= Open(fname
, O_RDONLY
, 0);fd3
= Open(fname
, O_RDONLY
, 0);dup2(fd2
, fd3
);Read(fd1
, &c1
, 1);Read(fd2
, &c2
, 1);Read(fd3
, &c3
, 1);printf("c1 = %c, c2 = %c, c3 = %c\n", c1
, c2
, c3
);Close(fd1
);Close(fd2
);Close(fd3
);return 0;
}
讀取的文件中假設內容為abcde
分析:fd1,fd2,fd3先后打開同一個文件,都從內容開頭讀。fd3與fd2共用fd2的文件表。fd1讀取第一個字節a(光標定位到a后),fd2讀取第一個字節a(fd2的光標定位到a后),fd3與fd2共用同一個文件表,所以此時fd3從a的后面開始讀,讀取到b,所以結果為c1=a,c2=a,c3=b
#include "csapp.h"
int main(int argc
, char *argv
[])
{int fd1
, fd2
, fd3
;char *fname
= argv
[1];fd1
= Open(fname
, O_CREAT
|O_TRUNC
|O_RDWR
, S_IRUSR
|S_IWUSR
);Write(fd1
, "pqrs", 4); fd3
= Open(fname
, O_APPEND
|O_WRONLY
, 0);Write(fd3
, "jklmn", 5);fd2
= dup(fd1
); Write(fd2
, "wxyz", 4);Write(fd3
, "ef", 2);Close(fd1
);Close(fd2
);Close(fd3
);return 0;
}
分析:首先fd1是打開(創建)一個空白文件,接著在fd1指向的文件中寫入“pqrs”,fd1光標移動到s后;fd3打開同一個文件(fd1寫入了pqrs的文件),并將光標移動到文件內容末端(O_APPEND),fd3再寫入”jklmn“,(此時文件中”pqrsjklmn“),fd3光標移動到n后;fd2指向fd1的文件表,也就是說fd2的光標在s后,接著寫入wxyz,(覆蓋了fd3寫入的jklm)fd2和fd1光標定位到z后;fd3在n后繼續寫入ef,關閉fd1,fd2,fd3。最后輸出pqrswxyznef
例3:
#include "csapp.h"
int main(int argc
, char *argv
[])
{int fd1
;int s
= getpid() & 0x1;char c1
, c2
;char *fname
= argv
[1];fd1
= Open(fname
, O_RDONLY
, 0);Read(fd1
, &c1
, 1);if (fork()) {sleep(s
);Read(fd1
, &c2
, 1);printf("Parent: c1 = %c, c2 = %c\n", c1
, c2
);} else {sleep(1-s
);Read(fd1
, &c2
, 1);printf("Child: c1 = %c, c2 = %c\n", c1
, c2
);}return 0;
}
父子進程共享相同的打開文件表集合
我
如上圖,父子進程共享同一個打開文件表集合,也就是說父進程對文件的操作會直接影響子進程。所以例3的運行結果是
總結
以上是生活随笔為你收集整理的共享文件的原理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。