lseek - 重定位读/写文件偏移量
所需头文件
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
The lseek() function repositions the offset of the open file associated with the file descriptor fd to the argument offset according to the directive whence as follows:
lseek函数重定位文件描述符fd关联的文件的偏移量,偏移参数whence有如下指令
SEEK_SET The offset is set to offset bytes.
设置偏移字节
SEEK_CUR The offset is set to its current location plus offset bytes.
当前位置加上偏移字节
SEEK_END The offset is set to the size of the file plus offset bytes.
文件尾部加上偏移字节
The lseek() function allows the file offset to be set beyond the end of the file (but this does not change the size of the file). If data is later written at this point, subsequent reads of the data in the gap (a "hole") return null bytes ('\0') until data is actually written into the gap.
lseek函数允许文件偏移量越过文件尾部(但是这样并不改变文件的大小),如果文件后面在这个偏移点上写数据,后续读空隙中的数据(一个空洞)会返回空字节,直到文件实际上写入这个空隙中
Seeking file data and holes Since version 3.1, Linux supports the following additional values for whence:
自从kernel3.1之后,查找文件数据和空洞支持下面whence参数
SEEK_DATA Adjust the file offset to the next location in the file greater than or equal to offset containing data. If offset points to data, then the file offset is set to offset.
调整文件偏移量到下一个大于或者等于文件数据大小的地方,如果偏移指向数据,当前的偏移量就是文件的偏移量
SEEK_HOLE Adjust the file offset to the next hole in the file greater than or equal to offset. If offset points into the middle of a hole, then the file offset is set to offset. If there is no hole past offset, then the file offset is adjusted to the end of the file (i.e., there is an implicit hole at the end of any file).
调整文件的偏移量到下一个大于或等于偏移量的空洞,如果偏移量指向空洞的中间,当前偏移量就是文件的偏移量,如果文件中没有空洞,文件的偏移量就是文件的尾部
In both of the above cases, lseek() fails if offset points past the end of the file.
上面的两种情况,lseek会失败,如果偏移量指向文件尾部
These operations allow applications to map holes in a sparsely allocated file. This can be useful for applications such as file backup tools, which can save space when creating backups and preserve holes, if they have a mechanism for discovering holes.
这些操作允许应用程序在一个分配的文件中定位空洞,这对应用程序很有用,例如文件备份工具,在创建备份和保护空洞的时候能够节省空间,如果需要查询空洞机制。
For the purposes of these operations, a hole is a sequence of zeros that (normally) has not been allocated in the underlying file storage.
这些操作的目的,空洞是一序列0(正常情况下),在文件存储下没有分配空间
However, a file system is not obliged to report holes, so these operations are not a guaranteed mechanism for mapping the storage space actually allocated to a file. (Furthermore, a sequence of zeros that actually has been written to the underlying storage may not be reported as a hole.) In the simplest implementation, a file system can support the operations by making SEEK_HOLE always return the offset of the end of the file, and making SEEK_DATA always return offset (i.e., even if the location referred to by offset is a hole, it can be considered to consist of data that is a sequence of zeros).
然而,文件系统并不记录空洞,所以这些操作并不保证已分配文件的空洞定位机制(更多的是,一序列0实际上已经写入了文件系统中,所以并不记录成一个空洞),在最简单的实现中,文件系统可以支持SEEK_HOLE操作经常返回文件的尾部,SEEK_DATA经常返回文件的偏移量(即使是指向空洞的位置,它认为组成空洞的数据是一序列0)
Upon successful completion, lseek() returns the resulting offset location as measured in bytes from the beginning of the file. On error, the value (off_t) -1 is returned and errno is set to indicate the error.
调用成功的话,lseek返回从文件头开始计算的偏移字节结果,错误的时候,返回-1,errno被设置成表示error的值
EBADF fd is not an open file descriptor.
fd不是一个打开文件的描述符
EINVAL whence is not valid. Or: the resulting file offset would be negative, or beyond the end of a seekable device.
whence是非法的,文件偏移量的结果是否定的,或者超出可查找设备的范围
EOVERFLOW The resulting file offset cannot be represented in an off_t.
偏移结果不能用off_t表示
ESPIPE fd is associated with a pipe, socket, or FIFO.
fd关联到管道,socket或者FIFO
ENXIO whence is SEEK_DATA or SEEK_HOLE, and the current file offset is beyond the end of the file.
whence是SEEK_DATA或者SEEK_HOLE,当前文件偏移量超出了文件的尾部
SEEK_DATA and SEEK_HOLE are nonstandard extensions also present in Solaris, FreeBSD, and DragonFly BSD; they are proposed for inclusion in the next POSIX revision (Issue 8).
SEEK_DATA和SEEK_HOLE是存在于solaris, freebsd中的非标准的实现,它们在下一版POSIX中被提议
Some devices are incapable of seeking and POSIX does not specify which devices must support lseek().
有些设备不能被查找,POSIX也没有定义哪些设备必须支持lseek
On Linux, using lseek() on a tty device returns ESPIPE.
在linux中,对tty设备使用lseek会返回ESPIPE
When converting old code, substitute values for whence with the following macros:
在转换旧的code中,whence的值用下面的宏代替
old new
0 SEEK_SET
1 SEEK_CUR
2 SEEK_END
L_SET SEEK_SET
L_INCR SEEK_CUR
L_XTND SEEK_END
Note that file descriptors created by dup(2) or fork(2) share the current file position pointer, so seeking on such files may be subject to race conditions.
通过fork或者dup产生的文件描述符共享当前文件位置指针,所以查找这些文件可能会产生竞争
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
int fd;
char buf[100];
if ((fd = open("1.txt", O_RDWR)) == -1) {
fprintf(stderr, "open error: %s\n", strerror(errno));
}
lseek(fd, 10, SEEK_END);
write(fd, "end\n", 4);
fsync(fd);
close(fd);
fd = open("1.txt", O_RDWR);
read(fd, buf, 100);
printf("buf = %s", buf);
return 0;
}
我是ubuntu 12.04,就看不到空洞,取而代之的是一序列的0,同样也会占用文件的空间,如下:
cheny@cheny-ThinkPad-T410:~/testCode$ ls -l 1.txt
-rw-rw-r-- 1 cheny cheny 80 2月 15 13:50 1.txt
cheny@cheny-ThinkPad-T410:~/testCode$ ./a.out
buf = heend
end
cheny@cheny-ThinkPad-T410:~/testCode$ ls -l 1.txt
-rw-rw-r-- 1 cheny cheny 94 2月 15 13:51 1.txt
cheny@cheny-ThinkPad-T410:~/testCode$ ./a.out
buf = heend
end
cheny@cheny-ThinkPad-T410:~/testCode$ ls -l 1.txt
-rw-rw-r-- 1 cheny cheny 108 2月 15 13:51 1.txt
可以看到文件逐次增加14个字节,这就是说空洞是有占空间的,跟man里面说的“this does not change the size of the file”还是有一些不一样的,主要原因是不同的系统对空洞的实现有些差异,另外一个就是空洞无法打印,是一序列0(0是字符串结束符哈)。