當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > lseek()函數(shù)的原型及使用方法,超詳細(xì)
對于所有打開的文件都有一個(gè)當(dāng)前文件偏移量(current file offset),文件偏移量通常是一個(gè)非負(fù)整數(shù),用于表明文件開始處到文件當(dāng)前位置的字節(jié)數(shù)。讀寫操作通常開始于當(dāng)前文件偏移量的位置,并且使其增大,增量為讀寫的字節(jié)數(shù)。文件被打開時(shí),文件的偏移量會(huì)被初始化為 0,除非使用了O_APPEND 。
讀寫操作可以使文件的偏移量發(fā)生變化;而lseek 函數(shù)也可以改變文件的當(dāng)前位置。下面我們一塊來看一下關(guān)于lseek函數(shù)的原型及使用方法。
通過man手冊查看到lseek函數(shù)原型如下:需要的頭文件為
#include
#include
off_t lseek(int fd, off_t offset, int whence);
參數(shù):fd:文件描述符
offset:文件偏移量
whence:文件偏移相對位置
返回值:成功:返回文件新的偏移量(成功)
失敗:-1(失敗)
參數(shù) offset可正可負(fù),負(fù)數(shù)時(shí)向文件開頭偏移,正數(shù)相對于文件末尾偏移
參數(shù) offset 的含義取決于參數(shù) whence:
1. 如果 whence 是 SEEK_SET,offset相對于文件開頭進(jìn)行偏移
2. 如果 whence 是 SEEK_CUR,offset相對文件當(dāng)前位置進(jìn)行偏移
3. 如果 whence 是 SEEK_END,offset相對于文件末尾進(jìn)行偏移
對于whence參數(shù)的選項(xiàng)SEEK_SET、SEEK_CUR 和 SEEK_END 是 System V 引入的,在這之前使用的是 0、1 和 2。
lseek 的以下用法返回當(dāng)前的偏移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
這個(gè)技巧也可用于判斷我們是否可以改變某個(gè)文件的偏移量。如果參數(shù) fd(文件描述符)指定的是 pipe(管道)、FIFO 或者 socket,lseek 返回 -1 并且置 errno 為ESPIPE。
對于普通文件(regular file),文件偏移量是一個(gè)非負(fù)整數(shù)。但對于特殊設(shè)備,文件偏移量有可能是負(fù)數(shù)。因此,我們不能簡單地測試 lseek 的返回值是否小于 0 來判斷 lseek 成功與否,而應(yīng)該測試 lseek 的返回值是否等于 -1 來判斷 lseek 成功與否。
lseek 僅將文件偏移位置保存于內(nèi)核中,不會(huì)導(dǎo)致任何 I/O 操作。
如果 offset 比文件的當(dāng)前長度更大,下一個(gè)寫操作就會(huì)把文件“撐大(extend)”。這就是所謂的在文件里創(chuàng)造“空洞(hole)”。沒有被實(shí)際寫入文件的所有字節(jié)由重復(fù)的 0 表示。空洞是否占用硬盤空間是由文件系統(tǒng)(file system)決定的。
以下程序創(chuàng)建一個(gè)有空洞的文件:
#include
#include
#include
#include
char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";
int main(void)
{
int fd, size;
if ((fd = open("file.hole", O_RDONLY|O_CREATO_TRUNC, 0666)) < 0)
{
printf("open error\n");
return -1;
}
size = sizeof (buf1) - 1;
if (write(fd, buf1, size) != size)
{
printf("buf1 write error\n");
return -1;
}
/* offset now = 10 */
if (lseek(fd, 16384, SEEK_SET) == -1)
{
printf("lseek error\n");
return -1;
}
/* offset now = 16384 */
size = sizeof buf2 - 1;
if (write(fd, buf2, size) != size)
{
printf("buf2 write error\n");
return -1;
}
/* offset now = 16394 */
return 0;
}