本節目標:
一,文件共享
1,一個進程打開兩個文件內核數據結構
說明:
文件描述符表:每個進程都有一張,彼此獨立,每個文件描述符表項都指向一個文件表,文件描述符0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO),默認已經打開,分別表示:標准輸入,標准輸出,標准錯誤設備。
文件表:每打開一個文件就對應一張文件表,文件表可以共享,當多個文件描述符指向同一個文件表時,文件表中的
refcnt字段會相應變化。文件狀態標識:文件的打開模式(R,W,RW,APPEND,NOBLOCK,等),當前文件偏移量,refcnt:被引用數量,
v節點指針:指向一個v節點表。
v節點表:每個文件對應一個,無論被被多少個進程打開都只有一個,它包括v節點信息(主要是stat結構體中的信息),i節點信息。
每個進程默認只能打開1024個文件描述符,當一個進程打開一個文件時,默認會從0開始查找未被使用的描述符,由於0,1,2默認被占用,所有一般從3開始使用。
2、一個進程兩次打開同一個文件
當一個進程多次打開同一個文件時,首先會在描述符表順序查找未被使用的描述符,然後每打開一次建立一張文件表,但各文件表中的v節點指針都指向同一個v節點表。
示例程序:
#include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) int main(int argc, char *argv[]) { int fd1; int fd2; char buf1[1024] = {0}; char buf2[1024] = {0}; fd1 = open("test.txt", O_RDONLY); if (fd1 == -1) ERR_EXIT("open error"); read(fd1, buf1, 5); printf("buf1=%s\n", buf1); fd2 = open("test.txt", O_RDWR); if (fd2 == -1) ERR_EXIT("open error"); read(fd2, buf2, 5); printf("buf2=%s\n", buf2); write(fd2, "AAAAA", 5); memset(buf1, 0, sizeof(buf1)); read(fd1, buf1, 5); printf("buf1=%s\n", buf1); close(fd1); close(fd2); return 0; }
運行結果:
說明:先創建test.txt文件寫入hello,再同一個進程兩次打開該文件,可見每打開一次文件就參數一張文件表,不共享偏移量,都開始位置讀取,之後利用第二個文件描述符寫入AAAAA,在利用第一個描述符可以讀取出,表明都指向同一個v節點表,操作同一個文件。
3,兩個不同進程打開同一個文件
當不同進程打開同一個文件時,每個進程首先在它們各自的文件描述符表中順序查找未被使用的描述符,最終獲得的文件描述符可能相同也可能不同,每個fd指向各自的文件表,但同樣,每個文件表中的v節點指針都指向同一個v節點表。