Download - Concurrent Servers

Transcript
Page 1: Concurrent Servers

Concurrent Servers

Page 2: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

X

Page 3: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

Page 4: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

Client 2

Page 5: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

Client 2Server 2

Page 6: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

Client 2Server 2

Page 7: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

Client 2Server 2

X

Page 8: Concurrent Servers

Idea Behind Concurrent Servers

Server

Client 1Server 1

Client 2Server 2

Page 9: Concurrent Servers

Creating a New Server - fork()listenfd = Socket( … )Initialize server addressBind( listenfd, … )

for ( ;; ) {/* wait for client connection */connfd = Accept(listenfd,…);

if( (pid = Fork() ) = = 0) { /*I am the child */Close(listenfd);service_client(connfd);Close(connfd);exit(0);

} else /* I am the parent */Close(connfd);

}

Page 10: Concurrent Servers

Points to Note

• fork() is called once …

• …but it returns twice!!– Once in the parent server and – Once in the child server

• How to distinguish parent and child??

Page 11: Concurrent Servers

Points to Note

• fork() is called once …

• …but it returns twice!!– Once in the parent server and – Once in the child server

• How to distinguish parent and child??– Return value in child = 0– Return value in parent = process id of child

Page 12: Concurrent Servers

Points to Note

• fork() is called once …• …but it returns twice!!

– Once in the parent server and – Once in the child server

• How to distinguish parent and child??– Return value in child = 0– Return value in parent = process id of child

• Child server exits after servicing the client.

Page 13: Concurrent Servers

Running another program in child – exec()

Page 14: Concurrent Servers

Running another program in child – exec()

listenfd = Socket(…)Connfd = Accept(…)

Inetd daemon

Page 15: Concurrent Servers

Running another program in child – exec()

listenfd = Socket(…)Connfd = Accept(…)

Inetd daemon

Close(listenfd)Fork(…)

Inetd child

Page 16: Concurrent Servers

Running another program in child – exec()

listenfd = Socket(…)Connfd = Accept(…)

Inetd daemon

Close(listenfd)Fork(…)

Exec(…)

Service telnet clientClose(connfd)

Inetd child

Telnet server

Page 17: Concurrent Servers

Different Types of exec()• int execl(char * pathname, char * arg0, … , (char *)0);

• int execv(char * pathname, char * argv[]);

• int execle(char * pathname, char * arg0, … , (char *)0, char envp[]);

• int execve(char * pathname, char * argv[], char envp[]);

• int execlp(char * filename, char * arg0, … , (char *)0);

• int execvp(char * filename, char * argv[]);

Page 18: Concurrent Servers

Properties of exec()

• Replaces current process image with new program image.– E.g. inetd image replaced by telnet image

• All descriptors open before exec remain open after exec.

Page 19: Concurrent Servers

Getting IP address/port from socket

• int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen)

– Get the local IP/port bound to socket

• int getpeername(int sockfd, struct sockaddr *remoteaddr, socklen_t *addrlen)

– Get the IP/port of remote endpoint

• Why do we need these?

Page 20: Concurrent Servers

Two other useful functions• struct hostent *gethostbyaddr (void *addr,

size_t len, int type);

– Converts from IP addr to domain name

• struct hostent *gethostbyname (char *name);

– Converts from domain name to IP address

• struct hostent {char *h_name;/* official name of host

*/ char **h_aliases; /* alias list */

int h_addrtype; /* address type */ int h_length; /* address length*/ char **h_addr_list; /* address list */

}

Page 21: Concurrent Servers

Signals

• Signal is a notification to process (from OS or from another process) that an event has occurred.

• Type of event determined by type of signal

• Try listing all signal types using % kill –l

• Some interesting signals– SIGCHLD, SIGTERM, SIGKILL, SIGSTOP

Page 22: Concurrent Servers

Handling Signals

• Signals can be caught – i.e. an action associated with them– SIGKILL and SIGSTOP cannot be caught.

• Actions can be customized using sigaction(…) which associates a signal handler with the signal.Details in page 120 of Steven’s book

• Default action for most signals is to terminate the process– SIGCHLD and SIGURG are ignored by default.

• Unwanted signals can be ignored – except SIGKILL or SIGSTOP

Page 23: Concurrent Servers

Zombie Processes

• When a child server dies, a SIGCHLD is sent to the parent server.

• If parent doesn’t wait()on the child, child becomes a zombie (status “Z” seen with ps).

• Zombies hang around forever.

Page 24: Concurrent Servers

How to avoid zombies?

• Parent should install a signal handler for SIGCHLD

• Call wait(…)/waitpid(…)inside the signal handler

void handle_sigchld(int signo) {pid_t pid;int stat;

pid = wait(&stat);printf(“child %d terminated\n”, pid);

}