Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do system calls like select() or poll() work under the hood?

Tags:

I understand that async I/O ops via select() and poll() do not use processor time i.e its not a busy loop but then how are these really implemented under the hood ? Is it supported in hardware somehow and is that why there is not much apparent processor cost for using these ?

like image 207
nisah Avatar asked Jul 15 '12 22:07

nisah


People also ask

How does a poll system call work?

The poll() feature allows programs to multiplex input and output through a series of file descriptors. In other words, the poll() system call is analogous to select() system call in working as it holds its fire for one of several file descriptors by becoming available for I/O.

What is select and poll?

With select( ), the file descriptor sets are reconstructed on return, so each subsequent call must reinitialize them. The poll( ) system call separates the input (events field) from the output (revents field), allowing the array to be reused without change.

How does poll work in Linux?

poll and select have essentially the same functionality: both allow a process to determine whether it can read from or write to one or more open files without blocking. They are thus often used in applications that must use multiple input or output streams without blocking on any one of them.

Is poll or select better?

poll offers somewhat more flavors of events to wait for, and to receive, although for most common networked cases they don't add a lot of value. Different timeout values. poll takes milliseconds, select takes a struct timeval pointer that offers microsecond resolution.


2 Answers

It depends on what the select/poll is waiting for. Let's consider a few cases; I'm going to assume a single-core machine for simplification.

First, consider the case where the select is waiting on another process (for example, the other process might be carrying out some computation and then outputs the result through a pipeline). In this case the kernel will mark your process as waiting for input, and so it will not provide any CPU time to your process. When the other process outputs data, the kernel will wake up your process (give it time on the CPU) so that it can deal with the input. This will happen even if the other process is still running, because modern OSes use preemptive multitasking, which means that the kernel will periodically interrupt processes to give other processes a chance to use the CPU ("time-slicing").

The picture changes when the select is waiting on I/O; network data, for example, or keyboard input. In this case, while archaic hardware would have to spin the CPU waiting for input, all modern hardware can put the CPU itself into a low-power "wait" state until the hardware provides an interrupt - a specially handled event that the kernel handles. In the interrupt handler the CPU will record the incoming data and after returning from the interrupt will wake up your process to allow it to handle the data.

like image 71
ecatmur Avatar answered Sep 21 '22 20:09

ecatmur


There is no hardware support. Well, there is... but is nothing special and it depends on what kind of file descriptor are you watching. If there is a device driver involved, the implementation depends on the driver and/or the device. For example, sockets. If you wait for some data to read, there are a sequence of events:

  1. Some process calls poll()/select()/epoll() system call to wait for data in a socket. There is a context switch from the user mode to the kernel.
  2. The NIC interrupts the processor when some packet arrives. The interrupt routine in the driver push the packet in the back of a queue.
  3. There is a kernel thread that takes data from that queue and wakes up the network code inside the kernel to process that packet.
  4. When the packet is processed, the kernel determines the socket that was expecting for it, saves the data in the socket buffer and returns the system call back to user space.

This is just a very brief description, there are a lot of details missing but I think that is enough to get the point.

Another example where no drivers are involved is a unix socket. If you wait for data from one of them, the process that waits is added to a list. When other process on the other side of the socket writes data, the kernel checks that list and the point 4 is applied again.

I hope it helps. I think that examples are the best to undertand it.

like image 25
Diego Woitasen Avatar answered Sep 23 '22 20:09

Diego Woitasen