檔案I O(不帶緩衝)之lseek函式

2022-05-04 20:33:11 字數 2980 閱讀 8213

每個開啟的檔案都有乙個與其相關聯的「當前檔案偏移量」(current file offset)。它通常是乙個非負整數,用以度量從檔案開始處計算的位元組數

可以呼叫lseek顯示地為乙個開啟的檔案設定其偏移量:

#include off_t lseek( 

int filedes, off_t offset, int whence );

返回值:若成功則返回新的檔案偏移量,若出錯則返回-1。

對引數offset的解釋與引數whence的值有關。(注意:當前檔案偏移量和引數offset是完全不同的概念。)

若whence是seek_set,則將該檔案的偏移量設定為距檔案開始處offset個位元組。

若whence是seek_cur,則將該檔案的偏移量設定為其當前位置加offset,offset可為正或負。

若whence是seek_end,則將新檔案的偏移量設定為檔案長度加上offset,offset可為正或負。

若lseek成功執行,則返回新的檔案偏移量,為此可以用下列方式確定開啟檔案的當前偏移量:

off_t currpos;

currpos = lseek( fd, 0, seek_cur );

這種方法也可用來確定所涉及的檔案是否可以設定偏移量。如果檔案描述符引用的是乙個管道、fifo或網路套接字,則lseek返回-1,並將errno設定為espipe。

三個符號常量seek_set、seek_cur和seek_end是由系統v引入的。在系統v之前,whence被指定為0(絕對偏移量)、1(相對於當前位置的偏移量)或2(相對於檔案尾端的偏移量)。現在的很多軟體仍然把這些數字直接寫在**裡。

lseek中的字元l表示長整型。在引入off_t資料型別之前,offset引數和返回值是長整型。lseek是由v7引入的,當時c語言中增加的長整型(在v6中,用函式seek和tell提供類似的功能)。

程式清單3-1 測試能否對標準輸入設定偏移量

[root@localhost apue]# cat prog3-1

.c#include

"apue.h

"int

main(

void

)

呼叫此程式,可得:

[root@localhost apue]# ./prog3-1

< /etc/motd

seek ok

[root@localhost apue]# ./prog3-1

< /etc/issue

seek ok

關於/etc/motd和/etc/issue的問題可參考:

通常,檔案的當前偏移量應當是乙個非負整數,但是,某些裝置也可能允許負的偏移量。但對於普通檔案,則其偏移量必須是非負值。因為偏移量可能是負值,所以在比較lseek的返回值時應當謹慎,不要測試它是否小於0,而要測試它是否等於-1。

在intel x86處理器上執行的freebsd上的/dev/kmem裝置支援負的偏移量。

因為偏移量(off_t)是帶符號資料型別,所以檔案最大長度會減少一半。例如,若off_t是32位整型,則檔案最大長度是2^31-1個位元組。

lseek僅將當前的檔案偏移量記錄在核心中,它並不引起任何i/o操作。然後,該偏移量用於下乙個讀或寫操作。

檔案偏移量可以大於檔案的當前長度,在這種情況下,對該檔案的下一次寫將加長該檔案,並在檔案中構成乙個空洞,這一點是允許的。位於檔案中但沒有寫過的位元組都被讀為0。

檔案中的空洞並不要求在磁碟上占用儲存區。具體處理方式與檔案系統的實現有關,當定位到超出檔案尾端之後寫時,對於新寫的資料需要分配磁碟塊,但是對於原檔案尾端和新開始寫位置之間的部分則不需要分配磁碟塊。

程式清單3-2 建立乙個具有空洞的檔案

[root@localhost apue]# cat prog3-2

.c#include

"apue.h

"#include

char buf1 = "

abcdefghij";

char buf2 = "

abcdefghij";

intmain(

void

)

執行該程式得到:

[root@localhost apue]# ./prog3-2

[root@localhost apue]# ls -l file.hole

-rw-r--r-- 1 root root 16394

12-30

00:38

file.hole

[root@localhost apue]# od -c file.hole

0000000 a b c d e f g h i j \0 \0 \0 \0 \0 \0

0000020 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0

*0040000

a b c d e f g h i j

0040012

使用od(1)命令觀察該檔案的實際內容。命令中的-c標誌表示以字元方式列印檔案內容。從中可以看到,檔案中間的未寫位元組都被讀成為0。每一行的開始的乙個7位數是以八進位制形式表示的位元組偏移量。

因為lseek使用的偏移量是用off_t型別表示的,所以允許具體實現根據各自特定的平台自行選擇大小合適的資料型別。現今大多數平台提供兩組介面以處理檔案偏移量:一組使用32位檔案偏移量,另一組則使用64位檔案偏移量。

注意:儘管可以支援64位檔案偏移量,但是否能建立乙個大於2gb(2^31-1個位元組)的檔案則依賴於底層檔案系統的型別。

本篇博文內容摘自《unix環境高階程式設計》(第二版),僅作個人學習記錄所用。關於本書可參考:

檔案I O(不帶緩衝)之I O的效率

程式清單3 3中的程式使用read和write函式複製檔案。關於該程式應注意下列各點 它從標準輸入讀,寫至標準輸出,這就假定在執行本程式之前,這些標準輸入 輸出已由shell安排好。確實,所有常用的unix系統shell都提供一種方法,它在標準輸入上開啟乙個檔案用於讀,在標準輸出上建立 或重寫 乙個...

linux不帶緩衝檔案IO

本博文設計的io不屬於ansi c的檔案io,所涉及的每乙個函式都是乙個系統呼叫。主要涉及posix.1的不帶快取的io操作的基礎部分。在linux核心中,對於乙個檔案的描述只需要乙個標示符即可。而不是乙個複雜的指標,僅僅是乙個int型的整數,有檔案描述符可以直接通過系統api直接操作核心資源,換句...

檔案I O(不帶緩衝)概述

unix系統中大多數檔案i o只需用到5個函式 open read write lseek以及close。這些函式經常被稱為不帶緩衝的i o unbuffered i o 術語不帶緩衝指的是每個read和write都呼叫核心中的乙個系統呼叫。這些不帶緩衝的i o函式不是iso c的組成部分,但是,它...