當對同一文件句柄(在Windows下)或是文件描述符(在Linux下)進行隨機讀寫操作時,會存在文件指針的定位與讀/寫倆個步驟,但由於這不是一個原子操作,就可能產生如下問題:進程A對某文件先定位到 f1 處,然后被中斷,然后進程B對同一文件定位到 f2 處,然后被中斷,進程A再次執行,從文件的當前指針處開始讀或是寫,於是這便產生了不是期望的結果了。(這里要注意,對同一文件的倆次打開,得到的將是倆個不同的句柄或是描述符,所以不用擔心這種情況會出問題)
解決辦法:
在Linux下,pread函數就好像是專門為上面的問題服務的,它本身就是原子性的操作,定位文件指針與讀操作一氣呵成,而且讀操作並不改變文件指針。
下面是pread和pwrite的手冊:
NAME
pread, pwrite - read from or write to a file descriptor at a given offset
SYNOPSIS
#define _XOPEN_SOURCE 500
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
DESCRIPTION
pread() reads up to count bytes from file descriptor fd at offset offset (from the start of the file) into the buffer starting at buf. The file offset is not changed.
pwrite() writes up to count bytes from the buffer starting at buf to the file descriptor fd at offset offset. The file offset is not changed.
The file referenced by fd must be capable of seeking.
RETURN VALUE
On success, the number of bytes read or written is returned (zero indicates that nothing was written, in the case of pwrite, or end of file, in the case of pread), or -1 on error, in which caseerrno is set to indicate the error.
ERRORS
pread can fail and set errno to any error specified for read(2) or lseek(2). pwrite can fail and set errno to any error specified for write(2) or lseek(2).
CONFORMING TO
NOTES
The pread() and pwrite() system calls are especially useful in multithreaded applications. They allow multiple threads to perform I/O on the same file descriptor without being affected by changes to the file offset by other threads. On Linux, the underlying system calls were renamed in kernel 2.6: pread() became pread64(), and pwrite() became pwrite64(). The system call numbers remained the same. The glibc pread() and pwrite() wrapper functions transparently deal with the change. On some 32-bit architectures, the calling signature for these system calls differ, for the reasons described in syscall(2).
BUGS
POSIX requires that opening a file with the O_APPEND flag should have no affect on the location at which pwrite() writes data. However, on Linux, if a file is opened with O_APPEND, pwrite() appends data to the end of the file, regardless of the value of offset.