I'm probably wrong in my thinking but I always thought that semantically sending output with fprintf was the same as writing to a pipe. Otherwise, it seems silly to create a pipe and fork the program and write to it with fprintf - then it IS a pipe and yet the program has not changed (except for the fork.)syzygy wrote:Ok, that explains the 512. But note that this only applies to write()s to pipes and not to printf() (which is neither a write(), nor outputs to a pipe).Don wrote:You asked me where I got the 512 from. I found it from the PIPE man page, but presumably the posix standard does not impose this limit on printf statements for conforming C libraries. This applies to ALL writes, not just printf:
Code: Select all
PIPE_BUF POSIX.1-2001 says that write(2)s of less than PIPE_BUF bytes must be atomic: the output data is written to the pipe as a contiguous sequence. Writes of more than PIPE_BUF bytes may be nonatomic: the kernel may interleave the data with data written by other processes. POSIX.1-2001 requires PIPE_BUF to be at least 512 bytes. (On Linux, PIPE_BUF is 4096 bytes.)
I have no idea how Windows does this so unless I knew I would just go ahead and do the locks too.
Once you use (FILE *) objects, I/O is buffered by the C library and the connection with write() is lost. Conceivably, printf() could insert data into the buffer character by character interleaved with characters written by other threads. Or printf() could issue a separate write() for each 10 characters. It is only the atomicity guarantee for printf() mandated by POSIX that prevents this.
It might still be wise to use locks and not depend on printf() being atomic if you want to run on Windows.