大家好。
今天的話主要和大家聊一聊,在Linux系統中如果一個檔案被打開多次會出現什麼情況。
目錄
第一:多次打開同一個檔案
第二:一個檔案被打開多次,在記憶體中不會存在多份動态檔案
第三:多次open打開同一個檔案,不同檔案描述符對應的讀寫位置偏移量是互相獨立的
第一:多次打開同一個檔案
大家看到這個标題可能會有疑問,同一個檔案還能被多次打開?事實确實如此,同一個檔案可以被 多次打開,譬如在一個程序中多次打開同一個檔案、在多個不同的程序中打開同一個檔案,那麼這些操作都 是被允許的。本小節就來探讨下多次打開同一個檔案會有一些什麼現象以及相應的細節問題?
當一個程序内多次open打開同一個檔案,那麼會得到多個不同的檔案描述符fd,同理在關閉檔案的時候也需要調用close依次關閉檔案描述符。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int fd1, fd2, fd3;
int ret;
/* 第一次打開檔案 */
fd1 = open("./test_file", O_RDWR);
if (-1 == fd1) {
perror("open error");
exit(-1);
}
/* 第二次打開檔案 */
fd2 = open("./test_file", O_RDWR);
if (-1 == fd2) {
perror("open error");
ret = -1;
goto err1;
}
/* 第三次打開檔案 */
fd3 = open("./test_file", O_RDWR);
if (-1 == fd3) {
perror("open error");
ret = -1;
goto err2;
}
/* 列印出 3 個檔案描述符 */
printf("%d %d %d\n", fd1, fd2, fd3);
close(fd3);
ret = 0;
err2:
close(fd2);
err1:
/* 關閉檔案 */
close(fd1);
exit(ret);
}
在上述代碼中,通過3次調用open函數對test_file檔案打開了3次,最後将3次得到的檔案描述符列印出來,在目前目錄下存在test_file檔案,接下來編譯測試:
從列印結果可知,三次調用 open 函數得到的檔案描述符分别為 6、7、8,通過任何一個檔案描述符對檔案進行 IO 操作都是可以的,但是需要注意是,調用 open 函數打開檔案使用的是什麼權限,則傳回的檔案描述符就擁有什麼權限,檔案 IO 操作完成之後,在結束程序之前需要使用 close 關閉各個檔案描述符。
第二:一個檔案被打開多次,在記憶體中不會存在多份動态檔案
如果同一個檔案被多次打開,那麼該檔案所對應的動态檔案是否在記憶體中也存在多份?也就是說,多次打開同一個檔案是否會将其檔案資料多次拷貝到記憶體中進行維護?
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[4];
int fd1, fd2;
int ret;
/* 建立新檔案 test_file 并打開 */
fd1 = open("./test_file", O_RDWR | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (-1 == fd1) {
perror("open error");
exit(-1);
}
/* 再次打開 test_file 檔案 */
fd2 = open("./test_file", O_RDWR);
if (-1 == fd2) {
perror("open error");
ret = -1;
goto err1;
}
/* 通過 fd1 檔案描述符寫入 4 個位元組資料 */
buffer[0] = 0x11;
buffer[1] = 0x22;
buffer[2] = 0x33;
buffer[3] = 0x44;
ret = write(fd1, buffer, 4);
if (-1 == ret) {
perror("write error");
goto err2;
}
/* 将讀寫位置偏移量移動到檔案頭 */
ret = lseek(fd2, 0, SEEK_SET);
if (-1 == ret) {
perror("lseek error");
goto err2;
}
/* 讀取資料 */
memset(buffer, 0x00, sizeof(buffer));
ret = read(fd2, buffer, 4);
if (-1 == ret) {
perror("read error");
goto err2;
}
printf("0x%x 0x%x 0x%x 0x%x\n", buffer[0], buffer[1],
buffer[2], buffer[3]);
ret = 0;
err2:
close(fd2);
err1:
/* 關閉檔案 */
close(fd1);
exit(ret);
}
目前目錄下不存在test_file檔案,代碼中,第一次調用open函數建立并打開test_file檔案,第二次調用open函數再次打開它,建立檔案時,檔案大小為0;首先通過檔案描述符 fd1 寫入4 個位元組資料(0x11/0x22/0x33/0x44),從檔案頭開始寫;然後再通過檔案描述符 fd2 讀取 4 個位元組資料,也是從檔案頭開始讀取。假如,記憶體中隻有一份動态檔案,那麼讀取得到的資料應該就是 0x11、0x22、0x33、0x44,如果存在多份動态檔案,那麼通過 fd2 讀取的是與它對應的動态檔案中的資料,那就不是 0x11、0x22、0x33、0x44,而是讀取出 0 個位元組資料,因為它的檔案大小是 0。
根據以上列印結果,列印顯示出來的資料是0x11/0x22/0x33/0x44,是以由此可知,即使多次打開同一個檔案,記憶體中也隻有一份動态檔案。