is ok to open fifo with one FD and share it with multiple threads?
or is it better to have multiple fds opened for the same fifo and share these fds with the threads?
BTW, I'll be doing write and read.

2 Answers
2

Depends on what exactly you are going to do. Usually if you stick to the syscall-level interface (int-typed descriptors, methods read and write), one descriptor is ok, except if you want to have different settings (some blocking, some not and such).

Remember, that when there are multiple readers on fifo, random one of them will get the data and the switch from one reader to another may happen after any byte (because it depends on write granularity and internal implementation of the buffer in kernel), so you either need one fifo for each intended recipient or use single-byte messages.

Are you sure about the swapping out during the middle of reads? Posix linux guarantees a minimum of PIPE_BUF (or whatever) to be written atomically. It seems ludicrous that the readers wouldn't be guaranteed the same - an atomic read of up to the PIPE_BUF amount. For amounts larger than PIPE_BUF, yes another signaling mechanism is required.
–
GlenH7Sep 6 '12 at 11:15

1

@GlenH7: Quoting POSIX 1:2008, description of read: "The standard developers considered adding atomicity requirements to a pipe or FIFO, but recognized that due to the nature of pipes and FIFOs there could be no guarantee of atomicity of reads of {PIPE_BUF} or any other size that would be an aid to applications portability." Also the rationale in description of write function only mentions multiple writes and single reader case. So one can rely on writes shorter than PIPE_BUF not getting interleaved, but probably not rely on one reader getting all of each in case of multiple readers.
–
Jan HudecSep 6 '12 at 11:50

Great reference to read there. A few paragraphs down though, we have "I/O is intended to be atomic to ordinary files and pipes and FIFOs." So the intent is there, but not the guarantee of atomicity with the FIFO.
–
GlenH7Sep 6 '12 at 13:30

3.289 Process
An address space with one or more threads executing within that address space,
and the required system resources for those threads.
Note:
Many of the system resources defined by POSIX.1-2008 are shared among all of the
threads within a process. These include the process ID, the parent process ID, process
group ID, session membership, real, effective, and saved set-user-ID, real, effective,
and saved set-group-ID, supplementary group IDs, current working directory, root
directory, file mode creation mask, and file descriptors.

So, if all of your threads are in the same process, they'll end up using the same file descriptor anyway. But this is something I would let the OS manage for you as it will be one less headache to worry about.

(Same reference as above, under File Offset) Since you're dealing with FIFOs, you don't have to worry about the file offset being stored along with the file descriptor. If you were dealing with regular files, then this could be an issue to be aware of.

Revised Answer

There are two cases to consider:
1. One process with multiple threads
2. two (or more) processes with one or more threads.

In the first case, all of the threads will have the same file descriptor for the FIFO because that's how the OS manages that for you.

In the second case, if you share the file descriptor between the various threads processes then you will likely have to manage the concurrency of access.

I'm pretty certain you're in the first case, not the second.

As Jan pointed out the read calls are not guaranteed to be atomic. But the intent is for them to be that way. See paragraphs 2 and 4 under Input and Output from the Rationale section of the manual. Sharing file descriptors across processes can only make those concurrency issues more convoluted.

All else being equal, since the OS manages a lot of this for you I'd go with the multiple descriptors approach, even though it will likely result in the same file descriptor value being used. My primary reasoning is that it is less code you have to write and maintain. You can have a single routine that's called by each thread to get the descriptor. An additional benefit is that it sets you up well in case you need to fork to new processes instead of spawning child threads.

in C a file descriptor already only allows one thread to write at a time and will not allow multiple threads to write data causing interleaving of the data? If 2 threads tried to write to their respective FD's at once Thread1:"Hello" and Thread2:"World" the fifo couldn't possibly recieve "HWeolrldo" ?
–
Jimmy HoffaSep 5 '12 at 3:24

I agree with Jimmy, I think it's better to have multiple FDs so fcntl used by one thread on one FD won't affect the other FD.
–
polySep 5 '12 at 19:41

@poly I was saying to have a shared fd, but in my comment I was asking about the behavior of fd and concurrency in C, I don't know enough about it all
–
Jimmy HoffaSep 6 '12 at 1:50

@JimmyHoffa - he's using posix / linux with the OS supplied FIFO structure, so the OS provides the concurrency control on access.
–
GlenH7Sep 6 '12 at 2:44