170 likes | 355 Views
Inter-process Communication. Chung-Ta King Department of Computer Science National Tsing Hua University. Signals for IPC. kill(): send any signal to any process group or process If pid is positive, then signal sig is sent to pid
E N D
Inter-process Communication Chung-Ta King Department of Computer Science National Tsing Hua University
Signals for IPC • kill(): send any signal to any process group or process • If pid is positive, then signal sig is sent to pid • If pid equals -1, then sig is sent to every process except for the first one, from higher numbers in the proc table to lower • pause(): causes the process to sleep until a signal is received
Signals: Example /* “timeout prog” run prog and abort it after 3600 sec */ main() { if ((pid=fork()) == 0) execvp(argv[1], &argv[1]); signal(SIGALRM, onalarm); alarm(3600); if (wait(&status) == -1 || status & 0177) != 0) error(“%s killed”,argv[1]); } onalarm() /* kill child when alarm arrives */ { kill(pid, SIGKILL); /* send pid the signal */ }
Pipes for IPC • Unidirectional byte stream communication mechanism e.g., ls | pr -2 | lpr • int sk[2]; /* sk[0]: read-end; sk[1]: write-end */ pipe(sk); /* create a pipe */ if (fork()) { /* the parent */ close(sk[1]); while(read(sk[0],buf,SIZE) > 0) printf("%s",buf); } else { /* the child */ close(sk[0]); fd=popen("ps -l","r"); while((s=read(fd,buf,SIZE)) > 0) write(sk[1],buf,s); }
3 ex2 3 ex2 4 3 (a) ex2 4 3 ex2 csh fork() 0 ex2 4 ps 1 (b) (c)
Sockets • Endpoints for communication and for IPC references; treated like files • Socket type: stream (TCP), datagram (UDP), raw • Socket domain: • UNIX: socket name = path name • Internet: socket name = Internet addr + port #e.g., 140.114.77.100 and 1800 • struct sockaddr_in { short sin_family; /* domain name */ u_short sin_port; /* port address */ struct in_addr sin_addr; /* Internet address */ char sin_zero[8]; /* padding bytes */ };
Socketpair for IPC • Two-way stream communication under UNIX domain • int sk[2]; socketpair(AF_UNIX,SOCK_STREAM,0,sk); for (i=0; i<nchild; i++) if (fork() == 0) { close(sk[0]); while (read(sk[1],&num,4) > 0) { num = num*num; write(sk[1],&num,4); } exit(0); } close(sk[1]); for (i=0, pt=a; i<n; i++, pt++) write(sk[0],pt,4); for (i=0, pt=a; i<n; i++, pt++) read(sk[0],pt,4);
3 ex3 4 3 (a) ex3 ex3 ex3 ex3 4 4 4 (b)
Datagram: Unix Domain • struct sockaddr_un { short sun_family; char sun_path[109]; } • The sender:#include <sys/socket.h>#include <sys/un.h>#define NAME "/tmp/socket”struct sockaddr_un remote;sk = socket(AF_UNIX,SOCK_DGRAM,0);remote.sun_family = AF_UNIX;strcpy(remote.sun_path,NAME);sendto(sk,MSG,strlen(MSG),0,&remote,strlen(NAME)+2);
Datagram: Unix Domain (cont.) • The receiver:#define NAME "/tmp/socket”struct sockaddr_un local;sk = socket(AF_UNIX,SOCK_DGRAM,0);local.sun_family = AF_UNIX;strcpy(local.sun_path,NAME);bind(sk,&local,strlen(NAME)+2); /* bind the name to sk */read(sk,buf,BUFSIZ);unlink(NAME); /* delete the bound i-node */
Datagram: Internet Domain • The sender: struct sockaddr_in remote; struct hostent *hp,*gethostbyname(); sk = socket(AF_INET,SOCK_DGRAM,0); remote.sin_family = AF_INET; /* wild-card NW addr */ hp = gethostbyname(”cs20"); /* get NW addr of cs20 */ bcopy(hp->h_addr,&remote.sin_addr.s_addr,hp->h_length); remote.sin_port = port_no; /* got from receiver */ sendto(sk,MSG,strlen(MSG),0,&remote,sizeof(remote)); read(sk,buf,BUFSIZ);
Datagram: Internet Domain (cont.) • The receiver: struct sockaddr_in local,remote; sk = socket(AF_INET,SOCK_DGRAM,0); local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; local.sin_port = 0; /* let system assign a port */ bind(sk,&local,sizeof(local)); getsockname(sk,&local,&len); /* get the assigned port */ printf("Port number = %d",local.sin_port); /* publish it */ recvfrom(sk,buf,BUFSIZ,0,&remote,&rlen); sendto(sk,MSG,strlen(MSG),0,&remote,sizeof(remote));
Virtual Circuit: Internet Domain • The server: sk = socket(AF_INET,SOCK_STREAM,0); local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; local.sin_port = 0; bind(sk,&local,sizeof(local)); listen(sk,5); /* will accept 5 connections */ while (1) { rsk = accept(sk,0,0); if (fork() == 0) { /* fork one child for one request */ dup2(rsk,0); execlp("recho","recho",0); } else close(rsk); }
Virtual Circuit: Internet Domain (cont.) • The child server: (the “recho” process) while (read(0,buf,BUFSIZ) > 0) printf("%s",buf); • The client: sk = socket(AF_INET,SOCK_STREAM,0); remote.sin_family = AF_INET; hp = gethostbyname(”cs20"); bcopy(hp->h_addr,&remote.sin_addr.s_addr,hp->h_length); remote.sin_port = port_no; /* got from receiver */ connect(sk,&remote,sizeof(remote)); while(read(0,buf,BUFSIZ) > 0) write(sk,buf,strlen(buf);
Non-blocking Receive • Receive will not block the process if no data arrived sk = socket(sk,AF_UNIX,SOCK_DGRAM,0); fcntl(sk,F_SETFL,FNDELAY); /* work on descriptor to set (F_SETFL) the status flag to non-blocking */ /* Bind socket “local” */ while(read(sk,buf,BUFSIZ) < 0) /* return immediately */ if(errno == EWOULDBLOCK) sleep(5); /* if no data arrived => sleep 5 seconds */ printf("%s",buf);
I/O Multiplexing • Listen to several events and respond sk = socket(AF_INET,SOCK_DGRAM,0); /* Bind sockets “local” and “remote” */ while(1) { mask = 1 << sk | 1; /* poll stdin and sk for input */ select(20,&mask,0,0,0); /* return if any one input */ if ((mask & 1) > 0) { /* stdin has input: send */ c=read(0,buf,BUFSIZ); sendto(sk,buf,c,0,&remote,rlen); } if ((mask & (1 << sk)) > 0) /* sk has input: receive */ c=recv(sk,buf,BUFSIZ,0); }
Broadcasting • Use datagram communication to broadcast to all hosts in a particular sub-network • The remote or destination host network address must be INADDR_ANY #define NET "140.114.77" sk = socket(AF_INET,SOCK_DGRAM,0); /* do binding for socket “local” */ remote.sin_family = AF_INET; remote.sin_addr = inet_makeaddr( inet_network(NET),INADDR_ANY); remote.sin_port = portn;