Friday, September 2, 2011

Using fork to Service Multiple Clients

The server that was developed in previous posting Using Standard I/O on Sockets has been modified in this section to handle multiple clients by means of a fork(2) system call. Listing 11.2 shows the listing of the modified rpnsrv.c module. All other source modules remain the same as they appeared in the previous post.

The following session shows how to compile and to start the server in the background:

[sgupta@rhel54x64 rpn-main-server]$ 
[sgupta@rhel54x64 rpn-main-server]$ gcc -c -D_GNU_SOURCE -Wall -Wreturn-type rpnsrv.c [sgupta@rhel54x64 rpn-main-server]$ gcc -c -D_GNU_SOURCE -Wall -Wreturn-type rpneng.c [sgupta@rhel54x64 rpn-main-server]$ gcc -c -D_GNU_SOURCE -Wall -Wreturn-type mkaddr.c gcc [sgupta@rhel54x64 rpn-main-server]$ rpnsrv.o rpneng.o mkaddr.o -o rpnsrv -Igmp 
[sgupta@rhel54x64 rpn-main-server]$ ./rpnsrv '*:9090' & [2] 915 
[sgupta@rhel54x64 rpn-main-server]$ 

After the server has been started, you can use telnet from multiple xterm windows to try out the server simultaneously. If you are not running the X Window system, you can use various virtual console sessions to accomplish the same effect.

The principle changes to the module are as follows:
• The and include files. 
• A signal handler for SIGCHLD. 
• A process ID variable PID was declared. 
• The SIGCHLD signal handler was installed. 
• A call to fork(2) was added. 
• A call to exit(2) was added. 

Understanding the Overall Server Process The basic main program of the server now functions as follows: 
1. A signal handler for SIGCHLD is installed. This will play a role for terminated processes, which will be discussed later. 
2. A server address and socket are created. 
3. The socket is converted to a listening socket. 
4. The main loop begins. 
5. The server blocks its execution until a client connects. 
6. The fork(2) function is called. 
7. If step 6 fails, the value -1 is returned by fork(2) and the server closes the connected socket c. Then the loop repeats with step 5. 
8. If step 6 succeeds, then PID will contain the process ID of the child process in the parent process. The parent process simply closes the accepted connection c and repeats step 5. 

The parent process loops between steps 5 to 8 until the server is killed off. Effectively, the parent process only accepts connections. It does no other work.

Understanding Process Termination Processing

The one complication that the fork(2) function call inflicts upon the design of the server is that it must process information about terminated processes. This is very important, because when a child process terminates, most of its resources are released. The rest of its resources are released only when the parent process obtains the child process termination status information.

The parent process is notified of a child process termination by means of the signal SIGCHLD. Now examine the steps that the parent server process uses when a child process terminates:
  1. The signal SIGCHLD is raised by the kernel to indicate that the child process has terminated.
  2. The function sigchld_handler() is called (line 35), because the function was registered for the SIGCHLD signal.
  3. The sigchld_handler() executes a loop calling waitpid(2) until no more exit status information is available.
  4. The SIGCHLD handler is re-instated. This was necessary because the reliable signals interface was not used in order to keep the example program simple.

In a production mode server, only the reliable signal functions such as sigaction (2) should be used. This was avoided in the example program to keep the source code simple.

Failure to call wait(2) or waitpid(2) by the parent process after a fork(2) and the child process's subsequent termination will result in zombie processes being left around until the parent process terminates. This can tie up valuable system resources.

The reader is encouraged to review the functions fork(2),  waitpid(2), and signal(2), if necessary. These are important aspects of this server design.

No comments:

Post a Comment