之前知道lseek這個系統調用可以改變文件的偏移量,或者叫偏移量或指針。
文件偏移量是指執行下一個read或者write操作的文件起始位置,會以相對於文件頭部起始點的文件當前位置來表示。
除非指定了O_APPEND選項。
文件第一個字節的偏移量爲0。
文件打開時,會將文件偏移量設置爲指向文件的開始,以後每次read或write調用將自動對其進行調整,以指向已讀或已寫數據後的下一字節。因此連續的read和write調用將按順序遞進,對文件進行操作。
lseek會根據offset和whence參數值來調整文件的偏移量。
off_t lseek(int fd, off_t offset, int whence)
offset 指定了一個以字節爲單位的數值
whence 表明應參照哪個基點來解釋offset參數,應爲下列其中之一:
SEEK_SET 將文件偏移量設置爲文件頭部起始點開始的offset字節
SEEK_CUR 相對於當前文件偏移量,將文件偏移量調整offset個字節
SEEK_END 將文件偏移量設置爲起始於文件尾部的offset個字節,也就是offset應該從文件最後一個字節之後的下一個字節算起。
早期的UNIX實現中,whence參數用整數0,1,2來表示的。
如果whence參數值爲SEEK_CUR或者SEEK_END,那麼offset參數可以爲正數也可以爲負數;如果whence參數值爲SEEK_SET,offset參數值必須爲非負數。
lseek調用成功會返回新的文件偏移量,下面調用只是獲取文件偏移量的當前位置,並沒有修改它。
curr = lseek(fd, 0, SEEK_CUR);
lseek(fd, 0, SEEK_SET); start of file
lseek(fd, 0, SEEK_END); Next byte after the end of the file
lseek(fd, –1, SEEK_END); Last byte of file
lseek(fd, –10, SEEK_CUR); Ten bytes prior to current location
lseek(fd, 10000, SEEK_END); 10001 bytes past last byte of file
lseek調用只是調整內核中與文件描述符相關的文件偏移量記錄,並沒有引起對任何物理設備的訪問。
文件偏移量,文件描述符和已打開文件的關係還需要進一步釐清。
lseek並不適用於所有類型的文件,不允許將lseek應用於管道、FIFO、socket或者終端。
一旦如此,調用將會失敗,並將errno置爲ESPIPE。
另一方面,只要合情合理,也可以將lseek應用於設備,例如磁盤或者磁帶上的某一具體位置。
lseek的l來源於long。
lseek和文件空洞。
文件偏移量可以大於文件的當前長度的,在這種情況下,該文件的下一次寫將加長該文件,並在文件中構成一個空洞,這一點是允許的。位於文件中但沒有寫過的字節都被讀爲0。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";
int main(int argc, char * argv[]) {
int fd;
if( (fd = creat("file.hole", FILE_MODE)) < 0)
fprintf(stderr, "creat error\n");
if( write(fd, buf1, 10) != 10)
fprintf(stderr, "buf1 write error\n");
if( lseek(fd, 16384, SEEK_SET) == -1)
fprintf(stderr, "lseek error\n");
if( write(fd, buf2, 10) != 10)
fprintf(stderr, "buf2 write error\n");
exit(0);
}
文件中的空洞並不要求在磁盤上佔用存儲區。