Presentation is loading. Please wait.

Presentation is loading. Please wait.

Interprocess Communication-1

Similar presentations


Presentation on theme: "Interprocess Communication-1"— Presentation transcript:

1 Interprocess Communication-1
Course code: 10CS62 Interprocess Communication-1 Engineered for Tomorrow Prepared by : M.Chandana Department of CSE

2 Contents Pipes Popen and pclose Functions Coprocesses FIFOs
System V IPC Message Queues Semaphores.

3 Pipes: pipe(2) #include <unistd.h> int pipe(int filedes[2]);
Engineered for Tomorrow Pipes: pipe(2) #include <unistd.h> int pipe(int filedes[2]); Returns: 0 if OK, -1 otherwise oldest and most common form of UNIX IPC half-duplex (on some versions full-duplex)

4 Engineered for Tomorrow
Pipes: pipe(2)

5 Engineered for Tomorrow
Pipes: pipe(2)

6 Engineered for Tomorrow
Pipes: pipe(2)

7 Pipes: pipe(2) $ cc -Wall pipe1.c; $ ./a.out
Engineered for Tomorrow Pipes: pipe(2) $ cc -Wall pipe1.c; $ ./a.out P=> Parent process with pid (and its ppid 7474). P=> Sending a message to the child process (pid 23989): C=> Child process with pid (and its ppid 23988). C=> Reading a message from the parent (pid 23988): Hello child! I’m your parent pid 23988! $

8 Pipes: pipe(2) $ cc -Wall pipe1.c; $ ./a.out
Engineered for Tomorrow Pipes: pipe(2) $ cc -Wall pipe1.c; $ ./a.out P=> Parent process with pid (and its ppid 7474). P=> Sending a message to the child process (pid 23987): C=> Child process with pid (and its ppid 23986). C=> Reading a message from the parent (pid 1): Hello child! I’m your parent pid 23986! $

9 Engineered for Tomorrow
Pipes: pipe(2) A more useful example: displaying some content using the user’s preferred pager. (Look, Ma, no temporary files!) $ cat pipe2.c | ${PAGER:-/usr/bin/more} $ cc -Wall pipe2.c $ echo $PAGER $ ./a.out pipe2.c [...] ^Z $ ps -o pid,ppid,command PID PPID COMMAND /a.out pipe2.c more ps -o pid,ppid,command ksh $ fg $ env PAGER=/bin/cat ./a.out pipe2.c

10 Pipes: pipe(2) #include <unistd.h> int pipe(int filedes[2]);
Engineered for Tomorrow Pipes: pipe(2) #include <unistd.h> int pipe(int filedes[2]); Returns: 0 if OK, -1 otherwise oldest and most common form of UNIX IPC half-duplex (on some versions full-duplex) can only be used between processes that have a common ancestor can have multiple readers/writers (PIPE BUF bytes are guaranteed to not be interleaved) Behavior after closing one end: read(2) from a pipe whose write end has been closed returns 0 after all data has been read write(2) to a pipe whose read end has been closed generates SIGPIPE signal. If caught or ignored, write(2) returns an error and sets errno to EPIPE.

11 Pipes: popen(3) and pclose(3)
Engineered for Tomorrow Pipes: popen(3) and pclose(3) Historically implemented using unidirectional pipe (nowadays frequently implemented using sockets or full-duplex pipes) Type one of “r” or “w” (or “r+” for bi-directional communication, if available) cmd passed to /bin/sh -c #include <stdio.h> FILE *popen(const char *cmd, const char *type); Returns: file pointer if OK, NULL otherwise int pclose(FILE *fp); Returns: termination status cmd or -1 on error

12 Pipes: popen(3) and pclose(3)
Engineered for Tomorrow Pipes: popen(3) and pclose(3) $ cc -Wall popen.c $ echo $PAGER $ ./a.out popen.c [...] $ env PAGER=/bin/cat ./a.out popen.c $

13 Pipes: popen(3) and pclose(3)
Engineered for Tomorrow Pipes: popen(3) and pclose(3) $ cc -Wall popen.c $ echo $PAGER $ ./a.out popen.c [...] $ env PAGER=/bin/cat ./a.out popen.c $ env PAGER=/bin/cat/foo ./a.out popen.c sh: /bin/cat/foo: Not a directory $ env PAGER="more; touch /tmp/boo" ./a.out popen.c $ env PAGER="more; rm /etc/passwd 2>/dev/null" ./a.out popen.c

14 Engineered for Tomorrow
Coprocesses A UNIX system filter is a program that reads from standard input and writes to standard output. Filters are normally connected linearly in shell pipelines. A filter becomes a coprocess when the same program generates the filter’s input and reads the filter ’s output. A coprocess normally runs in the background from a shell, and its standard input and standard output are connected to another program using a pipe.

15 one to its standard input and one from its standard output.
Engineered for Tomorrow popen gives us a one-way pipe to the standard input or from the standard output of another process, with a coprocess we have two one-way pipes to the other process: one to its standard input and one from its standard output. We want to write to its standard input, let it operate on the data, and then read from its standard output.

16 Engineered for Tomorrow

17 Simple filter to add two numbers
Engineered for Tomorrow Simple filter to add two numbers #include "apue.h" int main(void) { int n, int1, int2; char line[MAXLINE]; while ((n = read(STDIN_FILENO, line, MAXLINE)) > 0) { line[n] = 0; /* null terminate */ if (sscanf(line, "%d%d", &int1, &int2) == 2) { sprintf(line, "%d\n", int1 + int2); n = strlen(line); if (write(STDOUT_FILENO, line, n) != n) err_sys("write error"); } else { if (write(STDOUT_FILENO, "invalid args\n", 13) != 13) } exit(0);

18 FIFOs: mkfifo(2) #include <sys/stat.h>
Engineered for Tomorrow FIFOs: mkfifo(2) #include <sys/stat.h> int mkfifo(const char *path, mode t mode); Returns: 0 if OK, -1 otherwise Also called as “named pipes” Allows unrelated processes to communicate Just a type of file – test for using S ISFIFO(st mode) Mode same as for open(2) Use regular I/O operations (ie open(2), read(2), write(2), unlink(2) etc.) Used by shell commands to pass data from one shell pipeline to Another without creating intermediate temporary files

19 FIFOs: mkfifo(2) Example: split input into sets
Engineered for Tomorrow FIFOs: mkfifo(2) Example: split input into sets

20 FIFOs: mkfifo(2) Example: split input into sets $ mkfifo fifo
Engineered for Tomorrow FIFOs: mkfifo(2) Example: split input into sets $ mkfifo fifo $ grep pattern fifo > match & $ gzcat file.gz | tee fifo | grep -v pattern > nomatch

21 Client-server communication using FIFOs
Engineered for Tomorrow Client-server communication using FIFOs

22 XSI IPC Identifiers and Keys
Engineered for Tomorrow XSI IPC Identifiers and Keys Each IPC structure (message queue, semaphore, or shared memory segment) in the kernel is referred to by a non-negative integer identifier. The identifier is an internal name for an IPC object. Cooperating processes need an external naming scheme to be able to rendezvous using the same IPC object. For this purpose, an IPC object is associated with a key that acts as an external name. Whenever an IPC structure is being created, a key must be specified. The data type of this key is the primitive system data type key_t, which is often defined as a long integer in the header <sys/types.h>. This key is converted into an identifier by the kernel.

23 Engineered for Tomorrow
There are various ways for a client and a server to rendezvous at the same IPC structure. The server can create a new IPC structure by specifying a key of IPC_PRIVATE and store the returned identifier somewhere (such as a file) for the client to obtain. The key IPC_PRIVATE guarantees that the server creates a new IPC structure . The client and the server can agree on a key by defining the key in a common header, for example. The server then creates a new IPC structure specifying this key. The client and the server can agree on a pathname and project ID (the project ID is a character value between 0 and 255) and call the function ftok to convert these two values into a key. This key is then used in step 2. The only service provided by ftok is a way of generating a key from a pathname and project ID.

24 The path argument must refer to an existing file.
Engineered for Tomorrow #include <sys/ipc.h> key_t ftok(const char *path, int id); Returns: key if OK, (key_t)-1 on error The path argument must refer to an existing file. Only the lower 8 bits of id are used when generating the key. The key created by ftok is usually formed by taking parts of the st_dev and st_ino fields in the stat structure corresponding to the given pathname and combining them with the project ID. If two pathnames refer to two different files, then ftok usually returns two different keys for the two pathnames.

25 Engineered for Tomorrow
Permission Structure XSI IPC associates an ipc_perm structure with each IPC structure. This structure defines the permissions and owner and includes at least the following members: struct ipc_perm { uid_t uid; /* owner's effective user id */ gid_t gid; /* owner's effective group id */ uid_t cuid; /* creator's effective user id */ gid_t cgid; /* creator's effective group id */ mode_t mode; /* access modes */ . . . };

26 Engineered for Tomorrow

27 Engineered for Tomorrow
A fundamental problem with XSI IPC is that the IPC structures are systemwide and do not have a reference count. For example, if we create a message queue, place some messages on the queue, and then terminate, the message queue and its contents are not deleted. They remain in the system until specifically read or deleted by some process calling msgrcv or msgctl, by someone executing the ipcrm(1) command, or by the system being rebooted. Another problem with XSI IPC is that these IPC structures are not known by names in the file system. We can't access them and modify their properties with the functions. Since these forms of IPC don't use file descriptors, we can't use the multiplexed I/O functions (select and poll) with them.

28 System V IPC Three types of IPC originating from System V: Semaphores
Engineered for Tomorrow System V IPC Three types of IPC originating from System V: Semaphores Shared Memory Message Queues All three use IPC structures, referred to by an identifier and a key; all three are (necessarily) limited to communication between processes on one and the same host. Since these structures are not known by name, special system calls (msgget(2), semop(2), shmat(2), etc.) and special userland commands (ipcrm(1), ipcs(1), etc.) are necessary.

29 System V IPC: Semaphores
Engineered for Tomorrow System V IPC: Semaphores A semaphore is a counter used to provide access to a shared data object for multiple processes. To obtain a shared resource a process needs to do the following: 1. Test semaphore that controls the resource. 2. If value of semaphore > 0, decrement semaphore and use resource; increment semaphore when done 3. If value == 0 sleep until value > 0 Semaphores are obtained using semget(2), properties controlled using semctl(2), operations on a semaphore performed using semop(2).

30 unsigned short semval; /* semaphore value, always >= 0 */
Engineered for Tomorrow Each semaphore is represented by an anonymous structure containing at least the following members: struct { unsigned short semval; /* semaphore value, always >= 0 */ pid_t sempid; /* pid for last operation */ unsigned short semncnt; /* # processes awaiting semval>curval */ unsigned short semzcnt; /* # processes awaiting semval==0 */ . . . };

31 The kernel maintains a semid_ds structure for each semaphore set:
Engineered for Tomorrow The kernel maintains a semid_ds structure for each semaphore set: struct semid_ds { struct ipc_perm sem_perm; unsigned short sem_nsems; time_t sem_otime; /* last-semop() time */ time_t sem_ctime; /* last-change time */ };

32 The first function to call is semget to obtain a semaphore ID.
Engineered for Tomorrow The first function to call is semget to obtain a semaphore ID. #include <sys/sem.h> int semget(key_t key, int nsems, int flag); Returns: semaphore ID if OK, 1 on error When a new set is created, the following members of the semid_ds structure are initialized. The ipc_perm structure is initialized. The mode member of this structure is set to the corresponding permission bits of flag. sem_otime is set to 0. sem_ctime is set to the current time. sem_nsems is set to nsems. The number of semaphores in the set is nsems. If a new set is being created (typically in the server), we must specify nsems. If we are referencing an existing set (a client), we can specify nsems as 0.

33 The semctl function is the catchall for various semaphore operations.
Engineered for Tomorrow The semctl function is the catchall for various semaphore operations. #include <sys/sem.h> int semctl(int semid, int semnum, int cmd,... /* union semun arg */); The fourth argument is optional, depending on the command requested, and if present, is of type semun, a union of various command-specific arguments: union semun { int val; /* for SETVAL */ struct semid_ds *buf; /* for IPC_STAT and IPC_SET */ unsigned short *array; /* for GETALL and SETALL */ };

34 Engineered for Tomorrow

35 Engineered for Tomorrow
The function semop atomically performs an array of operations on a semaphore set. #include <sys/sem.h> int semop(int semid, struct sembuf semoparray[], size_t nops); Returns: 0 if OK, 1 on error. The semoparray argument is a pointer to an array of semaphore operations, represented by sembuf structures: struct sembuf { unsigned short sem_num; /* member # in set (0, 1, ..., nsems-1) */ short sem_op; /* operation (negative, 0, or positive) */ short sem_flg; /* IPC_NOWAIT, SEM_UNDO */ }; The nops argument specifies the number of operations (elements) in the array.

36 Engineered for Tomorrow
The sem_op element operations are values specifying the amount by which the semaphore value is to be changed. If sem_op is an integer greater than zero, semop adds the value to the corresponding semaphore element value and awakens all processes that are waiting for the element to increase. If sem_op is 0 and the semaphore element value is not 0, semop blocks the calling process (waiting for 0) and increments the count of processes waiting for a zero value of that element. If sem_op is a negative number, semop adds the sem_op value to the corresponding semaphore element value provided that the result would not be negative. If the operation would make the element value negative, semop blocks the process on the event that the semaphore element value increases. If the resulting value is 0, semop wakes the processes waiting for 0.

37 System V IPC: Semaphores
Engineered for Tomorrow System V IPC: Semaphores $ cc -Wall semdemo.c 1$ ./a.out 2$ ./a.out $ ipcs -s

38 System V IPC: Shared Memory
Engineered for Tomorrow System V IPC: Shared Memory Fastest form of IPC Access to shared region of memory often controlled using semaphores Obtain a shared memory identifier using shmget(2) Catchall for shared memory operations: shmctl(2) Attach shared memory segment to a processes address space by calling shmat(2) Detach it using shmdt(2)

39 System V IPC: Shared Memory
Engineered for Tomorrow System V IPC: Shared Memory $ cc -Wall shmdemo.c $ ./a.out "Cow says: ’Moo!’" $ ./a.out $ ipcs -m

40 System V IPC: Shared Memory
Engineered for Tomorrow System V IPC: Shared Memory $ cc -Wall memory-layout.c $ ./a.out array[] from 804a080 to 8053cc0 stack around bffff9e4 malloced from 8053cc8 to 806c368 shared memory attached from to 4017a6a0

41 System V IPC: Message Queues
Engineered for Tomorrow System V IPC: Message Queues Linked list of messages stored in the kernel Create or open existing queue using msgget(2) Add message at end of queue using msgsnd(2) Control queue properties using msgctl(2) Receive messages from queue using msgrcv(2) The message itself is contained in a user-defined structure such as Struct mymsg { Long mtype; /* message type */ Char mtext[512]; /* body of message */ };

42 Each queue has the following msqid_ds structure associated with it:
Engineered for Tomorrow Each queue has the following msqid_ds structure associated with it: struct msqid_ds { struct ipc_perm msg_perm; /* see Section */ msgqnum_t msg_qnum; /* # of messages on queue */ msglen_t msg_qbytes; /* max # of bytes on queue */ pid_t msg_lspid; /* pid of last msgsnd() */ pid_t msg_lrpid; /* pid of last msgrcv() */ time_t msg_stime; /* last-msgsnd() time */ time_t msg_rtime; /*last-msgrcv() time */ time_t msg_ctime; /* last-change time */ . . . };

43 System V IPC: Message Queues
Engineered for Tomorrow System V IPC: Message Queues $ cc -Wall msgsend.c -o msgsend $ cc -Wall msgrecv.c -o msgrecv $ ipcs -q $ ./msgsend 1 $ ./msgrecv 1 ^C $ ./msgsend 2 $ ipcrm -q <msqid>

44 . #include <sys/msg.h> int msgget(key_t key, int flag);
Engineered for Tomorrow This structure defines the current status of the queue. The first function normally called is msgget to either open an existing queue or create a new queue . #include <sys/msg.h> int msgget(key_t key, int flag); Returns: message queue ID if OK, 1 on error. When a new queue is created, the following members of the msqid_ds structure are initialized: The ipc_perm structure is initialized. The mode member of this structure is set to the corresponding permission bits of flag. msg_qnum, msg_lspid, msg_lrpid, msg_stime, and msg_rtime are all set to 0. msg_ctime is set to the current time. msg_qbytes is set to the system limit. On success, msgget returns the non-negative queue ID. This value is then used with the other three message queue functions.

45 The msgctl function performs various operations on a queue.
Engineered for Tomorrow The msgctl function performs various operations on a queue. #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf ); Returns: 0 if OK, 1 on error. The cmd argument specifies the command to be performed on the queue specified by msqid.

46 Data is placed onto a message queue by calling msgsnd.
Engineered for Tomorrow Data is placed onto a message queue by calling msgsnd. #include <sys/msg.h> int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag); Returns: 0 if OK, 1 on error. Each message is composed of a positive long integer type field, a non-negative length (nbytes), and the actual data bytes (corresponding to the length). Messages are always placed at the end of the queue.

47 Messages are retrieved from a queue by msgrcv
Engineered for Tomorrow Messages are retrieved from a queue by msgrcv . #include <sys/msg.h> ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag); Returns: size of data portion of message if OK, 1 on error. The type argument lets us specify which message we want.


Download ppt "Interprocess Communication-1"

Similar presentations


Ads by Google