Answers
《Linux程序设计》(Beginning Linux Programming)有介绍到这个问题,直接将原文拷贝过来了。
When you’re using locking on regions of a file, it’s very important to use the lower-level read and write calls to access the data in the file, rather than the higher-level fread and fwrite. This is necessary
because fread and fwrite perform buffering of data read or written inside the library
, so executing an fread call to read the first 100 bytes of a file may (in fact almost certainly will)
read more than
100 bytes and buffer the additional data
inside the library. If the program then uses fread to read the next 100 bytes, it will actually read data already buffered inside the library and not allow a low-level
read to
pull more data from the file
.
To see
why
this is a problem, consider two programs that wish to update the same file. Suppose the file consists of 200 bytes of data, all zeros. The first program starts first and obtains a write lock on the first 100
bytes of the file. It then uses fread to read in those 100 bytes. However, as shown in an earlier chapter, fread will read ahead by up to BUFSIZ(默认是4096字节) bytes at a time, so it actually reads the entire file into memory, but only passes the first 100 bytes back to the program.
The second program then starts. It obtains a write lock on the second 100 bytes of the program. This is successful because the first program locked only the first 100 bytes. The second program writes twos to bytes 100 to 199, closes the file, unlocks it, and exits. The first program then locks the second 100 bytes of the file and calls fread to read them in. As that data was already buffered in memory by the library, what the program actually sees is 100 bytes of zeros, not the 100 twos that actually exist in the file on the hard disk. This problem doesn’t occur when you’re using read and write.