Search code examples
cbufferzos

Blocked vs unblocked I/O buffering?


I was reading a bit about z/OS's concepts of blocked IO. It states:

Blocked I/O is an extension to the ISO standard. For files opened in block format, z/OS® XL C/C++ reads and writes one block at a time. If you try to write more data to a block than the block can hold, the data is truncated. For blocked I/O, z/OS XL C/C++ allows only the use of fread() and fwrite() to read and write to files.

Then it goes to say:

The fflush() function has no effect for blocked I/O files.

However, in another article, it says:

For terminals, because I/O is always unblocked, line buffering is equivalent to full buffering.

For record I/O files, buffering is meaningful only for blocked files or for record I/O files in z/OS UNIX file system using full buffering. For unblocked files, the buffer is full after every write and is therefore written immediately, leaving nothing to flush. For blocked files or fully-buffered UNIX file system files, however, the buffer can contain one or more records that have not been flushed and that require a flush operation for them to go to the system.

For blocked I/O files, buffering is always meaningless.

I'm extremely confused by all this. If I/O is unblocked, how would line buffering be equivalent to full buffering? Why wouldn't flush make a difference in block I/O? In addition, what does it mean that blocked I/O cause buffering to be always meaningless? Any intuition regarding what's happening here with blocked vs unblocked I/O and how it plays into the effects of buffering would be much appreciated.


Solution

  • My take on what you provided is that this is referring to Blocked I/O for MVS datasets. These would be different than files stored in Unix System Services HFS / ZFS. And different than terminal I/O.

    I'm extremely confused by all this. If I/O is unblocked, how would line buffering be equivalent to full buffering?

    I think your referring to the reference to terminal I/O which indicates that a line is a record and is the same as block size so every record is a full block of data. Which is to say an LRECL = BLKSIZE == 1 record per block so its not buffered, or, the buffer is the record.

    Why wouldn't flush make a difference in block I/O?

    Where there is more than one record per block fflush will not write a block until the block is full. I suspect it has to do with the I/O implementation in z/OS wich predated C on the platform so they made a design decision to no cause different behaviours for different languages in how I/O is conducted.

    In addition, what does it mean that blocked I/O cause buffering to be always meaningless?

    Again, z/OS writes full blocks except for the last block in a file which may be short because it does not contain enough records for a full block.

    There was a lot of history in z/OS before C came to the platform and z/OS goes to great lengths to provide consistency.