2013-01-14 38 views
2

我寫了這個小代碼來確定讀取行爲。UNIX讀取行爲

#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 

爲什麼讀這樣的表現?

+1

您需要64位讀/寫I/O – wildplasser

回答

2

注意,通過lseek返回的值是一個off_t,而不是一個size_t。不同之處在於off_t被簽名。當您採用有符號值並使其無符號時,它看起來像一個很大的正數。我認爲「LONG_MAX」其實不是4294967295,而是2147483647(2^31-1)或者是一個更大的數字。所以4294967295來自-1 [它是2^32-1,這在32位數學中的確與-1相同]。

換句話說,你從lseek得到一個錯誤。

+0

'ssize_t'也被簽名,如'off_t'。它可能與'off_t'不一樣大,然而,它們可能都不同於'long'。 –

+0

在我的系統上,ssize_t和off_t都是8個字節長。 #define LONG_MAX 9223372036854775807L – Bruce

+1

這裏的關鍵點不是'off_t'的大小,但'off_t'有符號和'size_t'的事實不是。 –

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 

...這兩個看似合理的反應

+0

lseek的返回類型是off_t,在我的系統上是8個字節。 ret是int類型的。這就是它在lseek上輸出錯誤的原因。 lseek實際上沒有錯誤。 – Bruce

+0

我認爲在Linux上運行時,在第一種情況下寫入會成功。我想看看我是否想通過讀取和寫入時發生的最大文件大小。如果我尋找文件大小(不是最大文件大小),讀取返回0.我認爲它也應該返回-1。 – Bruce