If I have the following code with select call and suppose the socket fds are not ready for I/O for most of the time, will the thread take CPU or will it sleep and let the other thread do the job. Is select() a CPU intensive call?
while(1)
{
select(maxfd, &rfds, NULL, NULL, NULL);
}
Will the behaviour be same it the timeout = 0 (kind of polling ) instead of NULL.
If the timeout value is NULL, select will block indefinitely until data is available on the sockets and file descriptors in rfds. However, as soon as data is available on any file descriptor in that set, the code you have will consume the entire CPU since you don't show any thing that suggests draining the data off the socket. (The second call to select will return immediately indicating there is still data on the socket).
If you pass in a zero'd out timeval to select, it will be a non-blocking poll. It's equivalent to calling send() or recv() with the MSG_DONTWAIT flag (but without data being copied).
Related
Usually we use select() for waiting the socket which is ready to read. However, if writefds is also passed into select, then it will immediately return when fds are either readable or writable. The problem is that sockets are writable at most of the time. Won't this cause a busy loop?
You should only wait on writable when you have something to write. The same for the read - you wait for readable only when you're ready to receive data. After each successful writable check there should be write() and after each successful readable check there should be read().
Meeting these criteria you can't introduce busy wait loop as either your stream is not infinite or the socket buffer is not infinite.
From the manpage, select() is synchronous I/O multiplexing which means that only when some file descriptors are ready to read or write, the procedure keeps going next for further operations. This means that read()ing data from that fd will not be blocked, and the total bytes read will be returned. However, we can also set an O_NONBLOCK flag with fcntl() function for non-blocking I/O. What is the main difference between using select() and O_NONBLOCK?
select allows you to monitor multiple descriptors with a timeout for different events.
O_NONBLOCK is used in a situation when the current thread should not wait for I/O to complete. This is desirable when you are doing more things in the same thread, like updating the UI. In that case, you don't want the thread to pause waiting for the I/O to complete.
I've a non-blocking socket used for writing operations (send).
I would like to know if the select() is the only way to detect if:
- the socket connect completed successfully when connect returns EINPROGRESS
- the availability of socket for write operations when send return EWOULDBLOCK or EGAIN
Is polling an alternative to select()? In my application I've already a thread that wakes up each 1 second that can check cyclically if connect() returns with 0 (connection is OK) and send returns with 0 (sending is OK) if some bytes have to be sent.
Is polling an alternative to select()?
It's an alternative, but not a good one. You don't know how long to sleep for. select() does. On average a manual poll must sleep for double the required time per attempt, and waste CPU cycles while looping until success. select() doesn't have any of those issues.
I am in a gaming scenario. Both the server and clients exchange messages through non-blocking UDP in a high rate.
(Maybe odd here...) The legacy code also uses select() with timeout value set to 0, which means select() does not block. select() is within a forever while loop. Upon select() returns a number greater than 0, following code goes receive message through recvfrom(). If it returns 0, following code does not try receiving.
From print-out info, I saw select() sometimes returns 1 (greater than 0). I am confused that since timeout is set to 0, how does select() have time to check if a message is ready to read from any of readfds? Thanks.
According to the spec:
Upon successful completion, the pselect() or select() function shall
modify the objects pointed to by the readfds, writefds, and errorfds
arguments to indicate which file descriptors are ready for reading,
ready for writing, or have an error condition pending, respectively,
and shall return the total number of ready descriptors in all the
output sets. For each file descriptor less than nfds, the
corresponding bit shall be set upon successful completion if it was
set on input and the associated condition is true for that file
descriptor.
If none of the selected descriptors are ready for the requested operation, the pselect() or select() function shall block until at least one of the requested operations becomes ready, until the timeout occurs, or until interrupted by a signal. The timeout parameter controls how long the pselect() or select() function shall take before timing out. If the timeout parameter is not a null pointer, it specifies a maximum interval to wait for the selection to complete. If the specified time interval expires without any requested operation becoming ready, the function shall return. If the timeout parameter is a null pointer, then the call to pselect() or select() shall block indefinitely until at least one descriptor meets the specified criteria. To effect a poll, the timeout parameter should not be a null pointer, and should point to a zero-valued timespec structure.
In short, checking the descriptors happens before checking the timeout. If the socket already has data ready when select() is called, the timeout is ignored and select() exits immediately.
I have a list of nonblocking sockets.
I could call recv in each one (in this case, some calls shall fail) or poll the list and later call recv on ready sockets.
Is there a performance difference between these approaches?
Thanks!
Unless the rate of data on the sockets is quite high (eg: recv() will fail <25% of the time), using poll() or select() is almost always the better choice.
Modern operating system will intelligent block a poll() operation until one of fds in the set is ready (the kernel will block the thread on a set of fds, awaking it only when that fd has been accessed... ultimately, this happens far more than necessary, resulting in some busy-waiting, but it's better than nothing), while a recv() loop will always result in busy waiting.