0
votes

I am currently developing a forking server, which gives clients block-level (there is a defined blocksize and the boundary is checked) read- and write-access to a file.

I'm creating a fork for each client-connection. I know that file handles are copied, so both the parent and the child-process can access the file. I also know that seeking in one process will affect the other processes, too.

So here are my questions:

  1. How to lock seeking in the forks against the other forks? Mutex?
  2. Can a fork write to some blocks while the other forks are reading different block?
  3. If 2 is possible, how can I prevent forks from reading blocks that are currently being written?

Thank you for your help :)

1
Why not open the file separately in each process, instead of sharing the same file handle?Barmar
I would still need some kind of locking the blocks that are being written. Also, wouldn't this degrade performance?LittleFox
I don't think there would be any performance degradation. Yes, you'll still need a mutex to keep from writing to the same blocks, but you don't have to worry about seeking affecting the other processes.Barmar
You can use lockf() to lock the section of the file that you're writing to. This provides fine-grained locking.Barmar
Opening the file in each process would be ok. How could I do block-level locking instead of file-based? Will look into it, thank you (:LittleFox

1 Answers

0
votes

Use lockf() to lock the block of the file that you're writing to in each process.

Since the section to lock starts at the current file offset, I think it would be best to open the file separately in each process, rather than sharing the same file handle. This way, you can seek in each process without affecting the others. Otherwise, in addition to the file locks, you'll need mutual exclusion around the lseek().

So the code to write to a block would look something like:

lseek(fd, block_pos, SEEK_SET);
lockf(fd, F_LOCK, block_size);
write(fd, buf, block_size);
lseek(fd, block_pos, SEEK_SET);
lockf(fd, F_ULOCK, block_size);

If you do use shared file handles, you could use fcntl() to set locks at an offset that you specify in the call, and pwrite() to write to a location in the file without affecting the file pointer.