Exercises

  1. Modify the program in Example 63-2 (poll_pipes.c) to use select() instead of poll().

  2. Write an echo server (see An Iterative UDP echo Server and A Concurrent TCP echo Server) that handles both TCP and UDP clients. To do this, the server must create both a listening TCP socket and a UDP socket, and then monitor both sockets using one of the techniques described in this chapter.

  3. Section 63.5 noted that select() can’t be used to wait on both signals and file descriptors, and described a solution using a signal handler and a pipe. A related problem exists when a program needs to wait for input on both a file descriptor and a System V message queue (since System V message queues don’t use file descriptors). One solution is to fork a separate child process that copies each message from the queue to a pipe included among the file descriptors monitored by the parent. Write a program that uses this scheme with select() to monitor input from both the terminal and a message queue.

  4. The last step of the description of the self-pipe technique in The Self-Pipe Trick stated that the program should first drain the pipe, and then perform any actions that should be taken in response to the signal. What might happen if these substeps were reversed?

  5. Modify the program in Example 63-9 (self_pipe.c) to use poll() instead of select().

  6. Write a program that uses epoll_create() to create an epoll instance and then immediately waits on the returned file descriptor using epoll_wait(). When, as in this case, epoll_wait() is given an epoll file descriptor with an empty interest list, what happens? Why might this be useful?

  7. Suppose we have an epoll file descriptor that is monitoring multiple file descriptors, all of which are always ready. If we perform a series of epoll_wait() calls in which maxevents is much smaller than the number of ready file descriptors (e.g., maxevents is 1), without performing all possible I/O on the ready descriptors between calls, what descriptor(s) does epoll_wait() return in each call? Write a program to determine the answer. (For the purposes of this experiment, it suffices to perform no I/O between the epoll_wait() system calls.) Why might this behavior be useful?

  8. Modify the program in Example 63-3 (demo_sigio.c) to use a realtime signal instead of SIGIO. Modify the signal handler to accept a siginfo_t argument and display the values of the si_fd and si_code fields of this structure.