1. 程式人生 > >3.2Apue檔案IO——lseek以及檔案共享的概念

3.2Apue檔案IO——lseek以及檔案共享的概念

當前檔案偏移量

每個開啟檔案都有一個與其相關聯的當前檔案偏移量
它通常是一個非負的整數,用來度量從檔案開始處計算的位元組數
讀寫操作一般都從當前檔案偏移量處開始,並使偏移量增加所讀寫的位元組數
特例:除非在開啟檔案時指定O_APPEND可選項,否則當前檔案偏移量預設是0

lseek函式

原型:
在這裡插入圖片描述
它希望顯式地對檔案描述符fd相關聯的一個開啟檔案設定偏移量offset
對偏移量offset的解釋,與引數whence有關:

  1. whence=SEEK_SET,則將該檔案的偏移量設定為距檔案開始處offset個位元組offset只可為正
  2. whence=SEEK_CUR
    ,則將該檔案的偏移量設定為其當前值加上offsetoffset可正可負
  3. whence=SEEK_END,則將該檔案的偏移量設定為檔案長度加上offsetoffset可正可負

返回值:返回新的檔案偏移量

注意:不能對管道,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種資料結構表示開啟檔案:

  1. 每個程序在程序表中都有一個記錄項記錄項中包含一張開啟檔案描述符表。與每個檔案描述符相關聯的是:a.檔案描述符標誌b.指向一個檔案表項的指標
  2. 核心為所有開啟檔案維持一張檔案表,每個檔案表項包含:a.檔案狀態標誌b.當前檔案偏移量c.指向該檔案v節點表項的指標
  3. 每個開啟檔案都有一個v節點結構。v節點包含了檔案型別對此檔案進行各種操作函式的指標

圖示為一個程序兩個不同的開啟檔案的核心資料結構
在這裡插入圖片描述

圖示為兩個程序各自打開了同一個檔案的核心資料結構
可以看到,開啟該檔案的每個程序都將獲得各自的一個檔案表項,但對一個給定的檔案共享一個v節點表項(v節點包含了檔案型別對此檔案進行各種操作函式的指標
在這裡插入圖片描述

聰明的你可能從上圖意識到了,當多個程序去寫同一個檔案時,可能會產生自己沒辦法預料的結果
這樣說:假如open檔案時沒有使用可選項O_APPEND
① 程序A呼叫lseek,將檔案當前偏移量設定為1500位元組。
② 然後核心切換程序,B執行也執行lseek,也將檔案當前偏移量設定為1500位元組。然後呼叫write,寫入100位元組,此時檔案長度增加到1600位元組。
③ 程序A恢復執行,呼叫write又寫了100位元組資料,此時它將從1500位元組開始寫入,覆蓋了B寫入了100位元組