0% found this document useful (0 votes)
2 views

Chapter 5

The document outlines the implementation of a multi-process TCP server using forking techniques, detailing the process of creating child processes to handle client requests. It discusses signal handling, particularly the SIGCHLD signal, to manage child process termination and prevent zombie processes. Additionally, it provides examples of using system calls like wait() and waitpid() to manage process states effectively.

Uploaded by

ngominh9499
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Chapter 5

The document outlines the implementation of a multi-process TCP server using forking techniques, detailing the process of creating child processes to handle client requests. It discusses signal handling, particularly the SIGCHLD signal, to manage child process termination and prevent zombie processes. Additionally, it provides examples of using system calls like wait() and waitpid() to manage process states effectively.

Uploaded by

ngominh9499
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 28

Multi-Process TCP

Server
School of Information and Communication Technology,
Hanoi University of Science and Technology
References
[1] W.Richard Stevens, Unix Network Programming Vol.1, 3rd Ed., Prentice
Hall.
[2] Keir Davis, John W. Turner, and Nathan Yocom, The Definitive Guide to
Linux Network Programming, Apress.
[3] Michael Donahoo, Kenneth Calvert, TCP/IP Sockets in C: Practical Guide
for Programmers, Elsevier.

2
Content
• Forking Server
• Signaling
• Signal Handling

3
Single-client Server

4
Fork process
• fork is an operation where a process creates a
copy of itself
• Happen in multitask operating system when a
process launch another process  child process
• The parent process makes a copy of its memory
and gives to the child process
• Fork system call is first introduced in UNIX.
• First process in Linux is “init”
#include <unistd.h>

pid_t fork(void);

5
fork examples

6
fork examples

7
fork
pid_t pid;
int listenfd, connfd;
listenfd = socket( ... );
/* fill in sockaddr_in{} with server's well-known port */
bind(listenfd, ... );
listen(listenfd, 5);
for ( ; ; ) {
connfd = accept (listenfd, ... ); /* probably blocks */

if((pid = fork()) == 0) {
close(listenfd); /* child closes listening socket */
doit(connfd); /* process the request */
close(connfd); /* done with this client */
exit(0); /* child terminates */
}
close(connfd); /* parent closes connected socket */
}
8
Child Process Termination
• We use forking server, when a child process ends, it
sends the SIGCHLD signal to the parent
• Information about the child process is still maintained in “process
table” in order to allow its parent to read the child exit status
afterward.
• If SIGCHLD is ignored
• Child process will not running but still consumes system
resources (in process table)
•  it is in zombie state
• We need to handle SIGCHLD signal
• Make the child process to wait until the parent read its exit status
• once the exit status is read via “wait” system call, the zombie's
entry is removed from the process table


9
Signaling
• A signal is a notification to a process that an
event has occurred.
• Signals are sometimes called software
interrupts.
• Signals usually occur asynchronously.
• A process doesn't know ahead when a signal will
occur.
• Signals can be sent
• By one process to another process (or to itself)
• By the kernel to a process

10
Signaling
• Typing certain key combinations at the controlling
terminal of a running process causes the system to
send it certain signals:
• Ctrl-C sends an INT signal ("interrupt", SIGINT)
• Ctrl-Z sends a TSTP signal ("terminal stop", SIGTSTP)
• Ctrl-\ sends a QUIT signal (SIGQUIT)
• by default, this causes the process to terminate and dump core.
• SIGHUP is sent to a process when its controlling
terminal is closed (a hangup).
• SIGTERM is sent to a process to request its
termination.
• Unlike the SIGKILL signal, it can be caught and
interpreted or ignored by the process.
11
PARENT

C1 C2 C3

CHILD1 CHILD2 CHILD3


C1 C2 C3
Handle a signal using sigaction
• We set/change the disposition of a signal by
calling the sigaction function
• int sigaction(int signum, const struct sigaction *act, struct sigaction
*oldact);
• struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};

13
Handle a signal using sigaction
• Three choices for the disposition:
• We can provide in sigaction a function that is called
whenever a specific signal occurs (sa_handler)
Prototype: void handler (int signo);
• We can ignore a signal by setting sa_handler to
SIG_IGN
• We can set the default disposition for a signal by
setting sa_handler to SIG_DFL.

14
Example

15
Handle a signal using signal function
• An alternative to use sigaction.
• <signal.h>
• void (*signal(int sig, void (*func)(int)))(int)
• Sig: signal to be handled
• func: a pointer to a function that handle the signal
• Meaning: registration of a function for handling a signal.

16
Example

17
Handling SIGCHLD Signals
• The purpose of the zombie state is to maintain information
about the child in “process table” for the parent to fetch at
some later time.
• This information includes the process ID of the child, its
termination status, and information on the resource utilization
of the child (CPU time, memory, etc.).
• They take up space in the kernel and eventually we can run
out of processes
Whenever we fork children, parent must wait (read exit status)
for them to prevent them from becoming zombies
 establish a signal handler to catch SIGCHLD, and within the handler, we
call wait
 Add into server: signal (SIGCHLD, handler);

18
wait() and waitpid()
#include <sys/wait.h>

pid_t wait (int *statloc);


pid_t waitpid (pid_t pid, int *statloc, int options);

• Wait for the status change of a process. Status changes are:


• the child terminated;
• the child was stopped by a signal; or
• the child was resumed by a signal.
• Use to handle the terminated child
• Both return two values:
• The return value of the function
• is the process ID of the terminated child if OK
• 0 or -1 if error
• The termination status of the child (an integer) is returned
through the statloc pointer.

19
wait()
• wait for state changes in a child of the calling
process
• In the case of a terminated child, performing a wait
allows the system to release the resources
associated with the child;
• if a wait is not performed, then the terminated child
remains in a "zombie" state

20
wait() vs waitpid()

• Create 5 connections from a client to a forking


server
• When the client terminates, all open descriptors
are closed automatically by the kernel
•  five connections ended simultaneous

21
wait() vs waitpid()

•  five SIGCHILD is sent


• The signal is handled once with wait () in the
server
•  four children are zombies
• It can happen when many users connect to a server
•  we have to use waitpid()

22
waitpid()
pid_t waitpid (pid_t pid, int *statloc, int options);
• pid < 0: wait for status change of any child process whose
process group ID is equal to the absolute value of pid.
• pid = -1: wait for for status change of any child process.
• pid = 0: wait for any child process whose process group ID is
equal to that of the calling process
• pid > 0: wait for the child whose process ID is equal to the value of
pid
• Without option WNOHANG, waitpid blocks until the status
change
• With option WNOHANG, waitpid returns immediately
• Return
• Pid of the child whose state has changed
• With option WNOHANG, return 0 if the specified process has not
changed status.
23
Forking server
pid_t pid;
int listenfd, connfd;
signal(SIGCHLD,sig_chld);
listenfd = socket( ... );
bind(listenfd, ... );
listen(listenfd, 5);
for ( ; ; ) {
connfd = accept (listenfd, ... ); /* probably blocks */
if( (pid = fork()) == 0) {
close(listenfd); /* child closes listening socket */
doit(connfd); /* process the request */
close(connfd); /* done with this client */
exit(0); /* child terminates */
}else
close(connfd); /* parent closes connected socket */
}

24
sig_chld: SIGCHLD handler

void sig_chld(int signo)


{
pid_t pid;
int stat;
while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);
return;
}
/*
WNOHANG: waitpid does not block
while loop: waitpid repeatedly until there is no child process
change status, i.e until waitpid returns 0.
*/
25
Exercise
1) Make your TCP EchoServer be able to work with
multiple client in the same time
• Use forking process
• Handle the SIGCHLD signal in server
2) Write a “chat room” forking server
• Accept connection from multiple clients
• Receive a message from one client then forward to all
the others.

26
File Sharing
• Viết một chương trình server và 1 client
• Server:
• Fork để tạo 1 tiến trình con chuyên recvfrom (6000) từ các
client broadcast <TÊN> và lưu thông tin <IP> <TÊN> vào 1 file
dùng chung.
• Fork để tạo 1 tiến trình con chuyên đợi TCP 5000 và accept:
Mỗi lần accept tạo một kết nối và trả về danh sách các <IP> và
<TÊN> cho client rồi đóng luôn kết nối.
• Client:
• Fork để tạo 1 tiến trình con chuyên broadcast tên (nhập từ bàn
phím) đến cổng 6000 (toàn mạng)
• Fork để tạo 1 tiến trình con chuyên hỏi danh sách từ
server:5000

27
Q&A

28

You might also like