Reputation: 5706
Let's say I am doing I/O on a synchronous I/O socket, which is ready for read
or write
operation. That means that calling thread wouldn't be blocked on the operation, irrespective of the non-blocking(SOCK_NONBLOCK
)/blocking nature of the socket. But following things are not clear to me -
read
command? Does it depend on the family of the socket?Update:
With socket hardware I was wrong, I was thinking about the actual data transfer underneath. I understand that a Socket is not a matter, just an entity in OS to denote a file descriptor fit for communication.
Follow up question - This also means during write
, a calling thread writes data into memory. Is there a kernel thread which will take care of transferring data on the other side of the socket? If yes, then how an asyncronous io for sockets is different than the synchronous io?
Upvotes: 2
Views: 201
Reputation: 37188
In general you can think of socket I/O as a two level buffering system. There is the buffer in your application, and then there are kernel buffers. So when you call read(), the kernel will copy data from the kernel buffer(s) to your application buffer. Correspondingly, when you call write(), you are copying data from your application buffer to the kernel buffer(s).
The kernel then tells the NIC to write incoming data to the kernel buffers, and read outgoing data from the kernel buffers. This I/O is AFAIK usually DMA-driven, meaning that the kernel just needs to tell the NIC what to do, and the NIC is responsible for the actual data transfer. And when the NIC is finished, it will raise an interrupt (or for high IO rates, interrupts are disabled and the kernel instead polls), causing the CPU core that received the interrupt to stop executing whatever it was executing (user code, kernel code (unless interrupts disabled in which case the interrupt will be queued)) and execute the interrupt handler which then takes care of other steps that need to be done.
So to answer your follow-up question, in general there isn't a separate kernel thread handling socket I/O on the kernel side, work is done by the NIC hardware and in interrupt context.
For asynchronous I/O, or rather non-blocking I/O, the only difference is how the copying from the user application buffer and the kernel buffer(s) is done. For a non-blocking read, only the data that is ready and waiting in the kernel buffers is copied to userspace (which can result in a short read), or if no data is ready the read() call returns immediately with EAGAIN. Similarly, for a non-blocking write(), it copies only as much data as there is available space for in the kernel buffers, which can cause a short write, or if no space is available at all, returning with EAGAIN. For blocking read(), if there is no data available the call will block until there is, whereas for a blocking write(), if the kernel buffer(s) are full, it will block until there is some space available.
Upvotes: 4