我写了这个小代码来确定阅读行为。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
int main ()
{
ssize_t ret;
int fd;
char str[30] = {0};
off_t lret
fd = open("./sample", O_RDWR);
printf("File descriptor = %d\n",fd);
lret = lseek(fd,LONG_MAX,SEEK_SET);
printf("%ld\n",lseek(fd, 0, SEEK_CUR));
ret = read(fd, str, 20);
if (ret == -1) {
perror("read error");
}
else {
printf("%ld\n",ret);
printf("%s\n",str);
}
ret = write(fd, "bye", 3);
if (ret == -1) {
perror("write error");
}
else
printf("%ld\n",ret);
printf("%ld\n",lseek(fd, 0, SEEK_CUR));
close (fd);
return 0;
}
这是输出:
$ cat sample
HELLO$ ./a.out
File descriptor = 3
4294967295
read error: Invalid argument
write error: Invalid argument
4294967295
$ ll sample
-rw-r--r--. 1 bruce stud 5 Jan 14 17:25 sample
但如果我将lseek语句更改为
ret = lseek(fd,5,SEEK_SET);
读取返回0
$ ./a.out
File descriptor = 3
5
0
3
8
$ cat sample
HELLObye$ ll sample
-rw-r--r--. 1 bruce stud 8 Jan 14 17:26 sample
为什么读取的行为如此?
答案 0 :(得分:2)
请注意,lseek
返回的值为off_t
,而不是size_t
。区别在于off_t已签名。当您使用有符号值并使其无符号时,它看起来像一个大的正数。
我希望“LONG_MAX”实际上不是4294967295
,而是2147483647
(2 ^ 31-1)或更大的数字。所以4294967295
来自-1 [它是2 ^ 32-1,它确实与32位数学中的-1相同]。
换句话说,您从lseek
收到错误。
答案 1 :(得分:1)
奇怪的错误结果。您使用的实际操作系统是什么?我在第一个lseek之后添加了一个检查if (ret == -1) perror("lseek error");
,以便更好地检查错误。
在linux上我看到:
File descriptor = 3
lseek error: Invalid argument
0
5
HELLO
3
8
在OpenBSD上,我看到:
File descriptor = 3
9223372036854775807
read error: File too large
write error: File too large
9223372036854775807
......这两者似乎都是合理的回应