Suppose P1 & P2 start their I/O to the *same* I/O device
at 0 sec. My 'C' stdio library will buffer both I/O
ops to memory and then at a "suitable" time decide
to complete P1's I/O before starting P2's I/O.
The c stdio library does not do any such thing. Its output streams
can be in three modes: unbuffered, line buffered and fully buffered.
Unbuffered streams do not delay the delivery of data to the operating system.
Buffered streams accumulate a full buffer, and flush it out to the operating
system with it fills up. Line buffered streams automatically flush when
a complete line is accumulated. Buffered streams can be flushed at any time
with fflush.
There are no time-related rules.
If no language extensions are used in the C program, then it is not
a conforming implementation of stdio FILE * streams to have such a time-based
scheduling behavior. There can be such a behavior in the underlying operating
system, however.
For instance on many operating systems, the system call which outputs data to a
file can return before that data has been placed in the storage device.
Meanwhile, I/O to some other device might complete sooner. For instance,
suppose we write a block to disk, and then immediately print a message on a
serial console. The serial I/O to the UART might appear on the terminal before
the disk write is issued. Both write operations, the one to the disk and the
one to the serial device, can return to the caller before the data actually
goes out (i.e. without waiting for completion). Which one stays buffered longer
depends on the speed of the device and the strategy of the software management
layers above it.
There may be ways to wait for the completion of I/O if the program needs to be
sure; the C stdio library doesn't provide such a thing, however.
In the POSIX environment we can do fsync on a file descriptor. POSIX extends
FILE * streams with the fileno function, by which you can obtain a file
descriptor. fsync works for regular files. To wait for pending serial port
(tty) data to be written, there is another POSIX function: tcdrain.
These are all extensions to C, not part of standard C.
If you have multiple processes doing I/O on the same device, that may not even
be allowed, depending on the device. On Unix-like systems a "single open"
device will block or reject open calls if it is already open. On some devices,
concurrent I/O can do silly things, like interleaving the data in such a way
that it can't be unravelled: like if two processes both spew logging to a
console. Concurrent random access over record-structured files is possible, if
the processes agree on some sort of locking, to stay out of each other's way.