230 likes | 422 Vues
Inter Process Communication. Introduction. Traditionally describe mechanism for message passing between different processes that are running on some operating system. IPC. Mechanism for processes to communicate and to synchronize their actions.
E N D
Introduction • Traditionally describe mechanism for message passing between different processes that are running on some operating system.
IPC • Mechanism for processes to communicate and to synchronize their actions. • Message system – processes communicate with each other without resorting to shared variables. • IPC facility provides two operations: • send(message) – message size fixed (signals) or variable (sockets) • receive(message) • If P and Q wish to communicate, they need to: • establish a communicationlink between them (connection oriented e.g. TCP/IP, pipe) • exchange messages via send/receive (e.g. UDP/IP) • Implementation of communication link • physical (e.g., shared memory, hardware bus, network) • logical (e.g., logical properties: FIFO, error free)
Direct Communication • Processes must name each other explicitly: • send (P, message) – send a message to process P • receive(Q, message) – receive a message from process Q • Properties of communication link • Links are established automatically. • A link is associated with exactly one pair of communicating processes. • The link may be unidirectional (e.g. signaling), but is usually bi-directional (e.g. sockets).
Indirect Communication • Messages are directed and received from mailboxes (also referred to as ports). • Each mailbox has a unique id. (e.g. shared memory, shared file, message Q) • Processes can communicate only if they share a mailbox. • Properties of communication link • A link may be associated with many processes. • Each pair of processes may share several communication links. • Link may be unidirectional or bi-directional.
Indirect Communication • Operations • create a new mailbox • send and receive messages through mailbox • destroy a mailbox • Primitives are defined as: send(A, message) – send a message to mailbox A receive(A, message) – receive a message from mailbox A
Synchronization • Message passing may be either blocking or non-blocking. • Blocking is considered synchronous • Non-blocking is considered asynchronous • send and receive primitives may be either blocking or non-blocking. • Buffering: Queue of messages attached to the link; implemented usually with bounded capacity. finite length of n messages. Sender must wait if link full.
Persistence • Persistence: How long an IPC object of that type remains in existence. • Process persistence IPC (socket) • Kernel persistence IPC (message Q) • File-System persistence IPC (shared file)
Signals • The source process can "raise" a signal and have it delivered to destination process. The destination process' signal handler is invoked and the process can handle it. • A direct communication • Unidirectional channel is established automatically. • Processes must name each other explicitly using the process ID in order to send messages of fixed size. • Asynchronous. • Kernel persistence (e.g. SIGCHILD).
Pipes • There is no form of IPC that is simpler than pipes. • A direct communication in which unidirectional channels are established between “related” processes. • Basically, a call to the int pipe(int fd[2]) function returns a pair of file descriptors. • One of these descriptors is connected to the write end of the pipe, and the other is connected to the read end. • On many systems, pipes will fill up after you write about 10K to them without reading anything out.
Example #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { int pfds[2]; char buf[30]; pipe(pfds); if (fork()==0) { printf(" CHILD: writing to the pipe\n"); write(pfds[1], "test", 5); //close pfds[0] printf(" CHILD: exiting\n"); exit(0); } else { printf("PARENT: reading from pipe\n"); read(pfds[0], buf, 5); //close pfds[1] printf("PARENT: read \"%s\"\n", buf); wait(NULL); } }
"ls | wc –l” #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int pfds[2]; pipe(pfds); if (!fork()) { close(1); /* close normal stdout */ dup(pfds[1]); /* make stdout same as pfds[1] */ close(pfds[0]); /* we don't need this */ execlp("ls", "ls", NULL); } else { close(0); /* close normal stdin */ dup(pfds[0]); /* make stdin same as pfds[0] */ close(pfds[1]); /* we don't need this */ execlp("wc", "wc", "-l", NULL); } return 0; }
FIFO • A FIFO is sometimes known as a named pipe. That is, it's like a pipe, except that it has a name! • In this case, the name is that of a file that multiple processes can open andread and write to. • Has to be open at both ends simultaneously before you can proceed to do any input or output operations on it . • Would you like to know more? • int mkfifo(const char *path, mode_t mode); • mkfifo("/tmp/namedpipe" , 0666); • SIGPIPE
Producer int main(void) { char s[300]; int num, fd; mkfifo("/tmp/namedpipe" , 0666); printf("waiting for readers...\n"); fd = open("/tmp/namedpipe", O_WRONLY); //blocked printf("got a reader--type some stuff\n"); while (gets(s), !feof(stdin)) { if ((num = write(fd, s, strlen(s))) == -1) perror("write"); else printf(“producer: wrote %d bytes\n", num); } return 0; }
Consumer int main(void) { char s[300]; int num, fd; mkfifo ("/tmp/namedpipe", 0666); printf("waiting for writers...\n"); fd = open("/tmp/namedpipe", O_RDONLY); printf("got a writer\n"); do { if ((num = read(fd, s, 300)) == -1) perror("read"); else { s[num] = '\0'; printf(“consumer: read %d bytes: \"%s\"\n", num, s); } } while (num > 0); return 0; }
Message Queues • Create: int msgget(key_t key, int msgflg); key_t ftok(const char *path, int id); key = ftok(“somefile", 'b'); msqid = msgget(key, 0666 | IPC_CREAT); • Send int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg =0); • Receive: int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); • Destroy: int msgctl(int msqid, int cmd, struct msqid_ds *buf); msgctl(msqid, IPC_RMID, NULL);
Example #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> struct my_msgbuf { long mtype; char mtext[200]; };
Producer int main(void) { struct my_msgbuf buf; int msqid; key_t key; key = ftok("ipc_example.c", 'B'); msqid = msgget(key, 0644 | IPC_CREAT); printf("Enter lines of text, ^D to quit:\n"); buf.mtype = 1; while(gets(buf.mtext), !feof(stdin)) { msgsnd(msqid, (struct msgbuf *)&buf, strlen(buf.mtext)+1, 0); } msgctl(msqid, IPC_RMID, NULL); return 0; }
Consumer int main(void) { struct my_msgbuf buf; int msqid; key_t key; key = ftok("ipc_example.c", 'B'); msqid = msgget(key, 0644); for(;;) { msgrcv(msqid, (struct msgbuf *)&buf, sizeof(buf.mtext), 0, 0); printf("consumer: \"%s\"\n", buf.mtext); } return 0; }
Shared Memory Segments • Create: intshmget(key_t key, size_t size, intshmflg); key = ftok(“somefile", ‘b'); shmid = shmget(key, 1024, 0644 | IPC_CREAT); • Use: void *shmat(intshmid, void *shmaddr, intshmflg); intshmdt(void *shmaddr); • Destroy: shmctl(shmid, IPC_RMID, NULL); For synchronization use UNIX semaphores.