How can I synchronize — make atomic — writes on on

2019-02-22 06:16发布

问题:

I have two process each writing large buffer of data, and I want to control synchronize those processes' writes to one file.

process 1 writing buffer A including (A1, A2, A3) and process 2 writing buffer B including (B1, B2, B3). when we use write() system call to write these buffers to disk to the same file(whole buffer at one time: write(fd, A, sizeof(A))) , How is the file schema?

  • Is it like this: A, B or B, A maybe?
  • or it could be like this: A1, A2, B1, A3, ...

I'm asking this because system calls are atomic. what happens if the data buffer we are writing is too large. Is it like pipes for regular disk files?

回答1:

If you want the contents of both buffers to be present, you have to open the files with the O_APPEND flag set. The append flag seeks to the end of the file before writing. Without this set, it's possible that both processes will be pointing to the same or overlapping areas of the file and whoever writes last will overwrite what the other has written.

Each call to write will write up to the number of bytes requested. If your process is interrupted by a signal, then you can end up with a partial write -- the actual number of bytes written is returned. Whether you get all of your bytes written or not, you'll have written one contiguous section of the file. You don't get the interleaving effect you mentioned as your second possibility (e.g. A1,B1,A2,B2,...).

If you only get a partial write, how you proceed is up to you. You can either continue writing (offset from the buffer start by the number of bytes previously written), or you can abandon the rest of your write. Only in this way could you potentially get the interleaving effect.

If it's important to have the contents of one write complete before the other process writes, then you should look into locking the file for exclusive write access (which both processes will have to check for) before attempting to write any data.



回答2:

Assuming that the buffers are of equal size, the result will be either A or B, depending on which process was scheduled last.

The write system call is atomic, yes, meaning that the result will be either A or B, not a mixture of both.

Assuming that you want both A and B in the file, you can open the file with O_APPEND; note that this won't work over NFS, though.

Another option is that each process keeps track of which file offset it should use, and uses lseek() or pwrite()



回答3:

You definitely need some form of synchronization for your programs that access the file, or you end up with messed up file contents. The write system call may write less bytes than you requested, so your blocks A1, A2 or B1, B2 may only be written partially. This might happen often, or rarely, depending on many conditions. If it only happens once in a week, you will have a bug that may be very hard to detect.

As a solution, you can use file locking (man 2 flock or man fcntl and search for locking). Another possibility is to use semaphores (man -k semaphore) to synchronize your programs writes, or some other forms of IPC.



标签: c atomic