3.2Apue檔案IO——lseek以及檔案共享的概念
當前檔案偏移量
每個開啟檔案
都有一個與其相關聯的當前檔案偏移量
它通常是一個非負的整數
,用來度量從檔案開始處計算的位元組數
讀寫操作
一般都從當前檔案偏移量處開始,並使偏移量增加所讀寫的位元組數
特例
:除非在開啟檔案時指定O_APPEND可選項,否則當前檔案偏移量預設是0
lseek函式
原型:
它希望顯式地對檔案描述符fd相關聯的一個開啟檔案
設定偏移量offset
對偏移量offset的解釋,與引數whence有關:
whence=SEEK_SET
,則將該檔案的偏移量設定為距檔案開始處offset個位元組
(offset只可為正
)whence=SEEK_CUR
,則將該檔案的偏移量設定為其當前值加上offset
(offset可正可負
)whence=SEEK_END
,則將該檔案的偏移量設定為檔案長度加上offset
(offset可正可負
)
返回值
:返回新的檔案偏移量
注意
:不能對管道,FIFO或網路套接字
設定偏移量,否則lseek函式將返回-1
lseek函式使用示例
對於一個hello檔案
① 獲得其檔案大小
② 設定其檔案偏移量為6,則對該檔案呼叫read函式或write函式時,將會從字母l處開始讀取/寫入。
/// for read()
#include <unistd.h>
/// for open()
#include <sys/types.h> /// for lseek()
#include <sys/stat.h>
#include <fcntl.h>
/// for printf()
#include <stdio.h>
#define BUFFERSIZE 1024
int main(int argc, char *argv[]) {
int fd = open(argv[1], O_RDONLY);
char buf[BUFFERSIZE];
lseek(fd, 6, SEEK_SET);
int n = read(fd, buf, BUFFERSIZE);
buf[n] = '\0';
write(STDOUT_FILENO, buf, n);
return 0;
}
如果是對檔案進行寫操作,那麼在一次寫成功之後,檔案偏移量會增加實際寫的位元組數。
檔案共享
核心使用3種資料結構表示開啟檔案:
- 每個程序在程序表中都有一個
記錄項
,記錄項中包含一張開啟檔案描述符表
。與每個檔案描述符相關聯的是:a.檔案描述符標誌
,b.指向一個檔案表項的指標
- 核心為所有開啟檔案維持一張
檔案表
,每個檔案表項包含:a.檔案狀態標誌
,b.當前檔案偏移量
,c.指向該檔案v節點表項的指標
- 每個開啟檔案都有一個
v節點結構
。v節點包含了檔案型別
和對此檔案進行各種操作函式的指標
圖示為
一個程序
有兩個不同的開啟檔案
的核心資料結構
圖示為
兩個程序
各自打開了同一個檔案
的核心資料結構
可以看到,開啟該檔案的每個程序都將獲得各自的一個檔案表項,但對一個給定的檔案共享一個v節點表項
(v節點包含了檔案型別
和對此檔案進行各種操作函式的指標
)
聰明的你可能從上圖意識到了,
當多個程序去寫同一個檔案時,可能會產生自己沒辦法預料的結果
。
這樣說:假如open檔案時沒有使用可選項O_APPEND
① 程序A呼叫lseek,將檔案當前偏移量設定為1500位元組。
② 然後核心切換程序,B執行也執行lseek,也將檔案當前偏移量設定為1500位元組。然後呼叫write,寫入100位元組,此時檔案長度增加到1600位元組。
③ 程序A恢復執行,呼叫write又寫了100位元組資料,此時它將從1500位元組開始寫入,覆蓋了B寫入了100位元組