We use cookies to give you the best experience possible. By continuing we’ll assume you’re on board with our cookie policy

See Pricing

What's Your Topic?

Hire a Professional Writer Now

The input space is limited by 250 symbols

What's Your Deadline?

Choose 3 Hours or More.
Back
2/4 steps

How Many Pages?

Back
3/4 steps

Sign Up and See Pricing

"You must agree to out terms of services and privacy policy"
Back
Get Offer

Inter Process Communication

Hire a Professional Writer Now

The input space is limited by 250 symbols

Deadline:2 days left
"You must agree to out terms of services and privacy policy"
Write my paper

Baghdad University Collage of Science Computer Science Department InterProcess Communication Mechanisms In Linux 2009-2010 1. Introduction A modern Multiprogramming Operating Systems like Linux supports the creation and concurrent execution of multiple processes or threads.

Some will act independently of others, but most will need to cooperate with each other. There are several reasons for providing an environment that allows process cooperation[1]: • Information sharing.

Don't use plagiarized sources. Get Your Custom Essay on
Inter Process Communication
Just from $13,9/Page
Get custom paper

Since several users may be interested in the same piece of information (for instance, a shared file), we must provide an environment to allow concurrent access to such information.

• Computation speedup. If we want a particular task to run faster, we must break it into subtasks, each of which will be executing in parallel with the others. Notice that such a speedup can be achieved only if the computer has multiple processing elements (such as CPUs or I/O channels). • Modularity. We may want to construct the system in a modular fashion, dividing the system functions into separate processes or threads. Convenience. Even an individual user may work on many tasks at the same time. For instance, a user may be editing, printing, and compiling in parallel. Cooperation between processes/threads includes making sure that processes/threads do not interfere with each other, i. e. they must synchronize their access to shared resources. And includes passing information between processes/threads, i. e. provide communication mechanism. Process cooperation can be achieved by interprocess communication mechanisms. 2. InterProcess Communication

InterProcess Communication, which in short is known as IPC, deals mainly with the techniques and mechanisms that facilitate communications between processes, these communications preferably in a well-structured way not using interrupts, because interrupts decrease system performance[2]. IPC was introduced in a development UNIX variant called “Columbus Unix” and later adopted by AT&T’s System III. It is now commonly found in most UNIX systems, including GNU/Linux. IPC denotes a set of system calls that allows a User Mode process to[3]: 1.

Synchronize itself with other processes by means of pipes and semaphores. 2. Send messages to other processes or receive messages from them. 3. Share a memory area with other processes. Some of the basic mechanisms that Linux systems has to offer are: 2. 1. Shared Memory Amongst all the IPC mechanisms, the most useful is the shared memory segment. Shared memory allows two or more processes within the same system to access some common data structures by placing them in a shared memory segment(see figure 1).

This is by far the fastest form of IPC, because there is no intermediation (i. e. a pipe, a message queue, etc). Instead, information is mapped directly from a memory segment, and into the addressing space of the calling process. A segment can be created by one process, and subsequently written to and read from by any number of processes[3,4]. [pic] Figure 1:Shared Memory Mechanism The shmget() function is invoked to get the IPC Identifier of a shared memory segment, optionally creating it if it does not already exist.

Then, shmat() function is invoked to “attach” a shared memory segment to a process, it then receives as its parameter the identifier of the IPC shared memory resource and tries to add a shared memory region to the address space of the calling process. The calling process can require a specific starting linear address for the memory region. The function shmat() however, leaves the process’s page tables unchanged. Another function, shmdt() is invoked to “detach” a shared memory segment specified by its IPC Identifier, that is, to remove the corresponding memory region from the process’s address space(see table 1).

Detaching a shared memory segment using shmdt() function does not delete the shared memory segment, It just makes it unavailable for the current process. By itself, shared memory does not provide any sort of synchronization facilities. In other words, there are no automatic facilities to prevent a second process starting to read the shared memory before the first process has finished writing to it. It’s the responsibility of the programmer to synchronize access to a shared memory segment. Kernel shmid_ds structure is a special internal data structure for each shared memory segment which exists within its addressing space.

This structure is of type shmid_ds, and is defined in Linux/shm. h as follows: /* One shmid data structure for each shared memory segment in the system. */ struct shmid_ds { struct ipc_perm shm_perm; /* operation permissions */ int shm_segsz; /* size of segment (bytes) */ time_t shm_atime; /* Time the last process attached the segment */ time_t shm_dtime; /* last detach time */ time_t shm_ctime; /* Time of the last change to this structure (mode change, etc). / unsigned short shm_cpid; /* pid of creator */ unsigned short shm_lpid; /* The PID of the last process to operate on the segment */ short shm_nattch; /* Number of processes currently attached to the segment */ /* the following are private */ nsigned short shm_npages; /* size of segment (pages) */ unsigned long *shm_pages; /* array of ptrs to frames */ struct vm_area_struct *attaches; /* descriptors for attaches */ }; Table 1: Systemcalls invoked with Shared Memory |System call |Prototype |Return | |shmget() |int shmget ( key_t key, int size, int shmflg ); shared memory segment identifier on success | | | |-1 on error: errno = | | | |EINVAL (Invalid segment size specified) | | | |EEXIST (Segment exists, cannot create) | | | |EIDRM (Segment is marked for deletion, or was | | | |removed) | | | |ENOENT (Segment does not exist) | | | |EACCES (Permission denied) | | | |ENOMEM (Not enough memory to create segment) | |shmat() |int shmat ( int shmid, char *shmaddr, int shmflg); |address at which segment was attached to the process, or | | | |-1 on error: errno = | | | |EINVAL (Invalid IPC ID value or attach address ENOMEM (Not enough memory to | | | |attach segment) | | | |EACCES (Permission denied) | |shmdt(); |int shmdt ( char *shmaddr ); |-1 on error: errno = | | | |EINVAL (Invalid attach address passed) | |shmctl() |int shmctl ( int shmqid, int cmd, struct shmid_ds *buf ); |0 on success | | |-1 on error: errno = | | | |EACCES (No read permission and cmd is IPC_STAT) | | | |EFAULT (Address pointed to by buf is invalid with | | | |IPC_STAT commands) | | | |EIDRM (Segment was removed during retrieval) | | | |EINVAL (shmqid invalid) | | | |EPERM (IPC_SET or IPC_RMID command was issued, | | | |calling process does not have write (alter) | | | |access to the segment) | IPC_CREAT Create the segment if it doesn’t already exist in the kernel. IPC_EXCL When used with IPC_CREAT, fail if segment already exists. IPC_STAT Retrieves the shmid_ds structure for a segment, and stores it in the address of the buf Argument. IPC_SET Sets the value of the ipc_ perm member of the shmid_ds structure for a segment. Takes the values from the buf argument. IPC_RMID Marks a segment for removal. *************************************************************************** MODULE: shrdmem. c ************************************************************************** #include #include #include #include #define SEGSIZE 100 /*size in bytes*/ main(int argc, char *argv[]) { key_t key; int shmid, cntr; char *segptr; if(argc == 1) usage(); /* Create unique key via call to ftok() */ key = ftok(“. “, ’S’); /* Open the shared memory segment – create if necessary */ if((shmid = shmget(key, SEGSIZE, IPC_CREAT|IPC_EXCL|0666)) == -1) { printf(“Shared memory segment exists – opening as client
“); /* Segment probably already exists – try as a client */ if((shmid = shmget(key, SEGSIZE, 0)) == -1) { perror(“shmget”); exit(1); } } else { printf(“Creating new shared memory segment
“); } * Attach (map) the shared memory segment into the current process */ if((segptr = shmat(shmid, 0, 0)) == -1) { perror(“shmat”); exit(1); } switch(tolower(argv[1][0])) { case ’w’: writeshm(shmid, segptr, argv[2]); break; case ’r’: readshm(shmid, segptr); break; case ’d’: removeshm(shmid); break; case ’m’: changemode(shmid, argv[2]); break; default: usage(); } } writeshm(int shmid, char *segptr, char *text){ strcpy(segptr, text); printf(“Done…
“); } readshm(int shmid, char *segptr) { printf(“segptr: %s
“, segptr); } removeshm(int shmid) { shmctl(shmid, IPC_RMID, 0); printf(“Shared memory segment marked for deletion
“); } changemode(int shmid, char *mode) { struct shmid_ds myshmds; * Get current values for internal data structure */ shmctl(shmid, IPC_STAT, &myshmds); /* Display old permissions */ printf(“Old permissions were: %o
“, myshmds. shm_perm. mode); /* Convert and load the mode */ sscanf(mode, “%o”, &myshmds. shm_perm. mode); /* Update the mode */ shmctl(shmid, IPC_SET, &myshmds); printf(“New permissions are : %o
“, myshmds. shm_perm. mode); } usage() { fprintf(stderr, “shmtool – A utility for tinkering with shared memory
“); fprintf(stderr, ”
USAGE: shmtool (w)rite
“); fprintf(stderr, ” (r)ead
“); fprintf(stderr, ” (d)elete
“); fprintf(stderr, ” (m)ode change
“); exit(1); } 2. 2. Pipes and FIFO mechanism

Pipes are an interprocess communication mechanism that is provided in Linux operating systems. They provide unidirectional flow of communication between processes within the same system. In other words, they are half-duplex, that is, data flows in only one direction. All data written to a pipe by a program is routed by the Kernel to another process, which can then access it and read the data[2,3]. Typically, a pipe is used to communicate between two threads in a single process or between parent and child processes. A pipe is created by invoking the pipe() system call, which creates a pair of file descriptors. These descriptors point to a pipe Inode and the file descriptors are returned through the filedes argument.

In the file descriptor pair, file_des[0] is used for reading whereas file_des[1] is used for writing. SYSTEM CALL: pipe(); PROTOTYPE: int pipe( int file_des[2] ); RETURNS: 0 on success -1 on error : errno = EMFILE (system file table is full) EFAULT (file_des array is not valid) The process can read from the pipe by using read() system call with the first file descriptor, and write into the pipe by using the write() system call with the second file descriptor. write(file_des[1], string, string_size); read(file_des[0], string, string_size); In the program given below the program creates a pipe using the pipe() system call. It then uses fork() call to create a new process.

If the fork call is successful, the parent writes data into the pipe, while the child reads data from the pipe. Both parent and child processes exit after a single write and read(see figure 2). /************************************************************************** MODULE: pipe. c ***************************************************************************/ #include #include #include int main(void) { int file_des[2], nbytes; pid_t childpid; char string[] = “Hello, world!
“; char readbuffer[80]; pipe(file_des); if((childpid = fork()) == -1) { perror(“fork”); exit(1); } if(childpid == 0) { /* Child process closes up input side of pipe */ close(file_des[0]); /* Send “string” through the output side of pipe */ rite(file_des[1], string, strlen(string)); exit(0); } else { /* Parent process closes up output side of pipe */ close(file_des[1]); /* Read in a string from the pipe */ nbytes = read(file_des[0], readbuffer, sizeof(readbuffer)); printf(“Received string: %s”, readbuffer); } return(0);} [pic] Figure 2: Pipe between Process and its Child A major feature of pipe is that the data flowing through the communication medium is transient, that is, data once read from the read descriptor cannot be read again, and pipe’s data capacity is limited[2]. Also pipes suffer from a major drawback, they only been able to pass data between programs that are related( i. e. rograms that have been started from a common ancestor process),and it is impossible for two arbitrary processes to share the same pipe. If two unrelated processes want to be able to exchange data it is done by using “named pipes”. or called FIFOs (i. e. “first in, first out”; the first byte written into the special file is also the first byte that will be read)[3]. FIFO works much like a regular pipe, but does have some noticeable differences[5]:. • FIFO exist as a device special file in the file system. • Processes of different ancestry can share data through a FIFO. • When all I/O is done by sharing processes, the FIFO remains in the file system for later use. To create a filesystem node (file, device file, or FIFO): SYSTEMCALL: mknod();

PROTOTYPE: int mknod( char *pathname, mode_t mode, dev_t dev); RETURNS: 0 on success, -1 on error: errno = EFAULT (pathname invalid) EACCES (permission denied) ENAMETOOLONG (pathname too long) ENOENT (invalid pathname) ENOTDIR (invalid pathname) I/O operations on a FIFO are essentially the same as for normal pipes, with once major exception. An “open” system call or library function should be used to physically open up a channel to the pipe.

With half-duplex pipes, this is unnecessary, since the pipe resides in the kernel and not on a physical filesystem. In our examples, we will treat the pipe as a stream, opening it up with fopen(), and closing it with fclose(). *************************************************************************** MODULE: fifoserver. c ***************************************************************************/ #include #include #include #include #include #define FIFO_FILE “MYFIFO” int main(void) { FILE *fp; char readbuf[80]; /* Create the FIFO if it does not exist */ umask(0); mknod(FIFO_FILE, S_IFIFO|0666, 0); while(1) { fp = fopen(FIFO_FILE, “r”); fgets(readbuf, 80, fp); printf(“Received string: %s
“, readbuf); fclose(fp); } return(0); }

Since a FIFO blocks by default, run the server in the background after you compile it: $ fifoserver& *************************************************************************** MODULE: fifoclient. c ***************************************************************************/ #include #include #define FIFO_FILE “MYFIFO” int main(int argc, char *argv[]) { FILE *fp; if ( argc ! = 2 ) { printf(“USAGE: fifoclient [string]
“); exit(1); } if((fp = fopen(FIFO_FILE, “w”)) == NULL) { perror(“fopen”); exit(1); } fputs(argv[1], fp); fclose(fp); return(0); } 2. 3. Semaphore mechanism Semaphores can be described as counters used to control access to shared resources by multiple processes within the same system.

They are most often used as a locking mechanism to prevent processes from accessing a particular resource while another process is performing operations on it[5]. So it is useful for solving a variety of synchronization problems. Each IPC semaphore is a set of one or more semaphore values. This means that the same IPC resource can protect several independent shared data structures(see figure 3)[3]. [pic] Figure 3 : Data Structure for a Set of Semaphores The calls semget() and semctl() allocate and deallocate semaphores, which is analogous to shmget() and shmctl() for shared memory. Invoke semget() with a key specifying a semaphore set, the number of semaphores in the set, and permission flags as for shmget; the return value is a semaphore set identifier.

Additional operations on individual semaphores are accomplished by using the semop() system call. Semaphores continue to exist even after all processes using them have terminated. The last process to use a semaphore set must explicitly remove it to ensure that the operating system does not run out of semaphores. To do so, invoke semctl() with the semaphore identifier, the number of semaphores in the set, IPC_RMID as the third argument(see table 2,3). The kernel maintains a special internal data structure for each semaphore set which exists within its addressing space. This structure is of type semid_ds, and is defined in linux/sem. h as follows: /* One semid data structure for each set of semaphores in the system. */ struct semid_ds { truct ipc_perm sem_perm; /*holds the permission information for the semaphore set, including the access permissions, and information about the creator of the set*/ time_t sem_otime; /* Time of the last semop() operation*/ time_t sem_ctime; /* Time of the last change to this structure (mode change)*/ struct sem *sem_base; /* Pointer to the first semaphore in the array*/ struct wait_queue *eventn; struct wait_queue *eventz; struct sem_undo *undo; /* Number of undo requests in this array*/ ushort sem_nsems; /* Number of semaphores in the semaphore set (the array)*/ }; Table 2:Systemcalls invoked with Semaphore System call |Prototype |Return | |semget() |int semget ( key_t key, int nsems, int semflg ); |semaphore set IPC identifier on success | | | |-1 on error: errno = | | | |EACCESS (permission denied) | | | EEXIST (set exists, cannot create (IPC_EXCL)) | | | |EIDRM (set is marked for deletion) | | | |ENOENT (set does not exist, no IPC_CREAT was ENOMEM (Not enough memory to | | | |create new set) | | | |ENOSPC (Maximum set limit exceeded) | |semop() |int semop ( int semid, struct sembuf *sops, unsigned |0 on success (all operations performed) | | |nsops); |-1 on error: errno = | | | |E2BIG (nsops greater than max number of ops | | | |allowed EACCESS (permission denied) | | | |EAGAIN (IPC_NOWAIT asserted, operation could not EFAULT (invalid address | | | |pointed to by sops | | | |argument) | | | |EIDRM (semaphore set was removed) | | | |EINTR (Signal received while sleeping) | | | |EINVAL (set doesn’t exist, or semid is invalid) | | | |ENOMEM (SEM_UNDO asserted, not enough | | | |memory to undo structure necessary) | | |ERANGE (semaphore value out of range) | |semctl() |int semctl ( int semid, int semnum, int cmd, union semun |positive integer on success | | |arg ); |-1 on error: errno = | | | |EACCESS (permission denied) | | | |EFAULT (invalid address pointed to by arg | | | |argument) | | | |EIDRM (semaphore set was removed) | | | |EINVAL (set doesn’t exist, or semid is invalid) | | | |EPERM (EUID has no privileges for cmd in arg) | | | |ERANGE (semaphore value out of range) | IPC_CREAT

Create the semaphore set if it doesn’t already exist in the kernel. IPC_EXCL When used with IPC CREAT, fail if semaphore set already exists. IPC_STAT Retrieves the semid_ds structure for a set, and stores it in the address of the buf argument in the semun union. IPC_SET Sets the value of the ipc perm member of the semid_ds structure for a set. Takes the values from the buf argument of the semun union. IPC_RMID Removes the set from the kernel. GETALL Used to obtain the values of all semaphores in a set. The integer values are stored in an array of unsigned short integers pointed to by the array member of the union. GETNCNT Returns the number of processes currently waiting for resources. GETPID

Returns the PID of the process which performed the last semop call. GETVAL Returns the value of a single semaphore within the set. GETZCNT Returns the number of processes currently waiting for 100% resource utilization. SETALL Sets all semaphore values with a set to the matching values contained in the array member of the union. SETVAL Sets the value of an individual semaphore within the set to the val member of the union. Table 3:Vales of semop() Systemcall |Semop() |Negative: the process specifying the operation is attempting to decrement the semaphore. | | |Positive: , the process is adding to the semaphore value.

The addition is used to record the return (release) of| | |the resource affiliated with the semaphore. | | |Zero : the process is testing the semaphore to determine if it is at 0. | *************************************************************************** MODULE: semtool. c ***************************************************************************/ #include #include #include #include #include #include #define SEM_RESOURCE_MAX 1 /* Initial value of all semaphores */ void opensem(int *sid, key_t key); void createsem(int *sid, key_t key, int members); void locksem(int sid, int member); void unlocksem(int sid, int member); void removesem(int sid); unsigned short get_member_count(int sid); int getval(int sid, int member); oid dispval(int sid, int member); void changemode(int sid, char *mode); void usage(void); int main(int argc, char *argv[]) { key_t key; int semset_id; if(argc == 1) usage(); /* Create unique key via call to ftok() */ key = ftok(“. “, ’s’); switch(tolower(argv[1][0])) { case ’c’: if(argc ! = 3) usage(); createsem(&semset_id, key, atoi(argv[2])); break; case ’l’: if(argc ! = 3) usage(); opensem(&semset_id, key); locksem(semset_id, atoi(argv[2])); break; case ’u’: if(argc ! = 3) usage(); opensem(&semset_id, key); unlocksem(semset_id, atoi(argv[2])); break; case ’d’: opensem(&semset_id, key); removesem(semset_id); break; case ’m’: opensem(&semset_id, key); hangemode(semset_id, argv[2]); break; default: usage(); } return(0); } void opensem(int *sid, key_t key) { /* Open the semaphore set – do not create! */ if((*sid = semget(key, 0, 0666)) == -1) { printf(“Semaphore set does not exist!
“); exit(1); } } void createsem(int *sid, key_t key, int members) { int cntr; union semun semopts; if(members > SEMMSL) { printf(“Sorry, max number of semaphores in a set is %d
“, SEMMSL); exit(1); } printf(“Attempting to create new semaphore set with %d members
“, members); if((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0666)) == -1) { fprintf(stderr, “Semaphore set already exists!
“); xit(1); } semopts. val = SEM_RESOURCE_MAX; /* Initialize all members (could be done with SETALL) */ for(cntr=0; cntrsem_nsems); } int getval(int sid, int member) { int semval; semval = semctl(sid, member, GETVAL, 0); return(semval); } void changemode(int sid, char *mode) { int rc; union semun semopts; struct semid_ds mysemds; /* Get current values for internal data structure */ semopts. buf = &mysemds; rc = semctl(sid, 0, IPC_STAT, semopts); if (rc == -1) { perror(“semctl”); exit(1); } printf(“Old permissions were %o
“, semopts. buf->sem_perm. mode); /* Change the permissions on the semaphore */ sscanf(mode, “%ho”, &semopts. buf->sem_perm. ode); /* Update the internal data structure */ semctl(sid, 0, IPC_SET, semopts); printf(“Updated…
“); } void dispval(int sid, int member) { int semval; semval = semctl(sid, member, GETVAL, 0); printf(“semval for member %d is %d
“, member, semval); } void usage(void) { fprintf(stderr, “semtool – A utility for tinkering with semaphores
“); fprintf(stderr, ”
USAGE: semtool4 (c)reate
“); fprintf(stderr, ” (l)ock
“); fprintf(stderr, ” (u)nlock
“); fprintf(stderr, ” (d)elete
“); fprintf(stderr, ” (m)ode
“); exit(1); } 2. 4. Message Passing Another IPC mechanism, which processes can use to communicate with each other is IPC Messages.

Each message generated by a process is sent to an “IPC Message Queue”, where it stays until another process reads it(see figure 4). Message queues can be best described as an internal linked list within the kernel’s addressing space. Messages can be sent to the queue in order and retrieved from the queue in several different ways. Each message queue is uniquely identified by an IPC identifier(This identifier is used within the kernel to uniquely identify an “IPC object” such as message queue, semaphore set, or shared memory segment). [3,4] Once a process has read a message from an IPC message queue, the Kernel destroys it. Thus, this proves the well-known fact: Only one process can receive a given message. [3] [pic] Figure 4: Message Passing mechanism

In order to create a new message queue, or access an existing queue, the msgget() system call is used. And for sending a message, a process invokes the msgsnd() systemcall, and for retrieving a message, a process invokes the msgrcv() Systemcall ,and to perform control operations on a message queue, you use the msgctl() systemcall. (see table 4). Kernel msqid_ds is an internal data structure which is maintained by the kernel for message queues. The kernel creates, stores, and maintains an instance of this structure for every message queue created on the system[4]. It is defined in Linux/msg. h as follows: /* one msqid structure for each queue on the system */ struct msqid_ds { struct ipc_perm msg_perm; /*is defined in linux/ipc. h.

This holds the permission information for the message queue, including the access permissions, and information about the creator of the queue*/ struct msg *msg_first; /*Link to the first message in the queue (the head of the list)*/ struct msg *msg_last; /* Link to the last message in the queue (the tail of the list)*/ time_t msg_stime; /* Timestamp of the last message that was sent to the queue*/ time_t msg_rtime; /* Timestamp of the last message retrieved from the queue*/ time_t msg_ctime; /* Timestamp of the last “change” made to the queue*/ struct wait_queue *wwait;/* Pointers into the kernel’s wait queue.

They are used when an operation on a message queue deems the process go into a sleep state (i. e. queue is full and the process is waiting for an opening). */ struct wait_queue *rwait; ushort msg_cbytes; /* Total number of bytes residing on the queue (sum of the sizes of all messages). */ ushort msg_qnum; /* Number of messages currently in the queue*/ ushort msg_qbytes; /* max number of bytes on queue */ ushort msg_lspid; /* The PID of the process who sent the last message*/ ushort msg_lrpid; /* The PID of the process who retrieved the last message*/ }; Table 4:Systemcalls invoked with Message Passing System call |Prototype |Return | |msgget() |int msgget ( key_t key, int msgflg ) |message queue identifier on success | | | |-1 on error: errno= | | | |EACCESS (permission denied) | | | |EEXIST (Queue exists, cannot create) | | | |EIDRM (Queue is marked for deletion) | | | |ENOENT (Queue does not exist) | | |ENOMEM (Not enough memory to create | | | |queue) | | | |ENOSPC (Maximum queue limit exceeded) | |msgsnd() |int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, |0 on success | | |int msgflg ); |-1 on error: errno = | | | |EAGAIN (queue is full, and IPC_NOWAIT | | | |was asserted) | | | |EACCES (permission denied, no write permission) | | | |EFAULT (msgp address isn’t accessible/ invalid) | | | |EIDRM (The message queue has been removed) | | | |EINTR (Received a signal while waiting to write) | | | |EINVAL (Invalid message queue identifier, nonpositive | | | |message type, or invalid message size) | | | |ENOMEM (Not enough memory to copy message | | | |buffer) | |msgrcv() |int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, |Number of bytes copied into message buffer | | |long mtype, -1 on error: errno = | | | |E2BIG (Message length is greater than msgsz,) | | | |EACCES (No read permission) | | | |EFAULT (Address pointed to by msgp is invalid) | | | |EIDRM (Queue was removed during retrieval) | | | |EINTR (Interrupted by arriving signal) | | | |EINVAL (msgqid invalid, or msgsz less than 0) | | | |ENOMSG (IPC_NOWAIT asserted, and no message | | | |exists in the queue to satisfy the request) | |msgctl() |int msgctl ( int msgqid, int cmd, struct msqid_ds *buf ); |0 on success | | | |-1 on error: errno = | | | |EACCES (No read permission and cmd is IPC_STAT) | | | |EFAULT (Address pointed to by buf is invalid | | | |IPC_STAT commands) | | | |EIDRM (Queue was removed during retrieval) | | | |EINVAL (msgqid invalid, or msgsz less than 0) | | | |EPERM (IPC_SET or IPC_RMID command was issued, calling process does not have | | |write (access to the queue) | IPC_CREAT Create the queue if it doesn’t already exist in the kernel. IPC_EXCL When used with IPC CREAT, fail if queue already exists. IPC_NOWAIT If the message queue is full, then the message is not written to the queue, and control is returned to the calling process. If not specified, then the calling process will suspend (block) until the message can be written. IPC_STAT Retrieves the msqid_ds structure for a queue, and stores it in the address of the buf argument. IPC_SET Sets the value of the ipc perm member of the msqid_ds structure for a queue. Takes the values from the buf argument. IPC_RMID Removes the queue from the kernel. ************************************************************************** MODULE: msgpass. c *************************************************************************** #include #include #include #include #include #include #define MAX_SEND_SIZE 80 /*size in bytes*/ struct mymsgbuf { long mtype; /* must be represented in a positive number */ char mtext[MAX_SEND_SIZE]; /* The message data itself */ }; void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text); void read_message(int qid, struct mymsgbuf *qbuf, long type); void remove_queue(int qid); void change_queue_mode(int qid, char *mode); void usage(void); int main(int argc, char *argv[]) { key_t key; int msgqueue_id; truct mymsgbuf qbuf; if(argc == 1) usage(); /* Create unique key via call to ftok() */ key = ftok(“. “, ’m’); /* Open the queue – create if necessary */ if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1) { perror(“msgget”); exit(1); } switch(tolower(argv[1][0])) { case ’s’: send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, atol(argv[2]), argv[3]); break; case ’r’: read_message(msgqueue_id, &qbuf, atol(argv[2])); break; case ’d’: remove_queue(msgqueue_id); break; case ’m’: change_queue_mode(msgqueue_id, argv[2]); break; default: usage(); } return(0); } void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text) { * Send a message to the queue */ printf(“Sending a message …
“); qbuf->mtype = type; strcpy(qbuf->mtext, text); if((msgsnd(qid, (struct msgbuf *)qbuf,strlen(qbuf->mtext)+1, 0)) ==-1) { perror(“msgsnd”); exit(1); } } void read_message(int qid, struct mymsgbuf *qbuf, long type) { /* Read a message from the queue */ printf(“Reading a message …
“); qbuf->mtype = type; msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0); printf(“Type: %ld Text: %s
“, qbuf->mtype, qbuf->mtext); } void remove_queue(int qid) { /* Remove the queue from the kernal*/ msgctl(qid, IPC_RMID, 0); } void change_queue_mode(int qid, char *mode) { truct msqid_ds myqueue_ds; /* Get current info */ msgctl(qid, IPC_STAT, &myqueue_ds); /* Convert and load the mode */ sscanf(mode, “%ho”, &myqueue_ds. msg_perm. mode); /* Update the mode */ msgctl(qid, IPC_SET, &myqueue_ds); } void usage(void) { fprintf(stderr, “msgtool – A utility for tinkering with msg queues
“); fprintf(stderr, ”
USAGE: msgtool (s)end
“); fprintf(stderr, ” (r)ecv
“); fprintf(stderr, ” (d)elete
“); fprintf(stderr, ” (m)ode
“); exit(1); } 2. 5. Socket A socket is a bidirectional communication device that can be used to communicate with another process on the same machine or with a process running on other machines.

Internet programs such as Telnet, FTP, and the World Wide Web use sockets. [5] When creating a socket, three parameters are specified: communication style, namespace, and protocol. A communication style controls how the socket treats transmitted data and specifies the number of communication partners. When data is sent through a socket, it is packaged into packets. The communication style determines how these packets are handled and how they are addressed from the sender to the receiver. o Connection styles guarantee delivery of all packets in the order they were sent. If packets are lost or reordered by problems in the network, the receiver automatically requests their retransmission from the sender. Datagram styles do not guarantee delivery or arrival order. Packets may be lost or reordered in transit due to network errors or other conditions. A socket namespace specifies how socket addresses are written. A socket address identifies one end of a socket connection. For example, socket addresses in the “local namespace” are ordinary filenames. In “Internet namespace,” a socket address is composed of the Internet address (also known as IP address) of a host attached to the network and a port number. The port number distinguishes among multiple sockets on the same host. A protocol specifies how data is transmitted[5,6]. Not all combinations of styles, namespaces, and protocols are supported.

A client is the process initiating the connection, and a server is the process waiting to accept connections. To create a connection between two sockets, the client calls connect() systemcall, specifying the three socket choices: namespace, communication style, and protocol. For the namespace parameter, use constants beginning with PF_ (abbreviating “protocol families”). For example, PF_LOCAL or PF_UNIX specifies the local namespace, and PF_INET specifies Internet namespaces. For the communication style parameter, use constants beginning with SOCK_. Use SOCK_STREAM for a connection-style socket, or use SOCK_DGRAM for a datagram-style socket.

The third parameter, the protocol, each protocol is valid for a particular namespace-style combination, because there is usually one best protocol for each such pair, specifying 0 is usually the correct protocol. If socket succeeds, it returns a file descriptor for the socket. You can read from or write to the socket using read, write, as with other file descriptors. write(sockfd, mesg, mesglen) read(sockfd, mesg, mesglen) A server’s life cycle consists of the creation of a connection-style socket, binding an address to its socket, placing a listen() systemcall that enables connections to the socket, placing accept() systemcall, sending and receiving messages and then close() the socket.

While the client’s life cycle consists of the creation of a connection-style socket, setting up connection to server , sending and receiving messages and then close() the socket. (see figure 5 and table 5). [pic] Figure 5: Socket Systemcalls Table 5:Systemcalls for involving Sockets |System call |Prototype |Return | |Socket() |int socket(int domain, int type, int protocol); |an integer representing the newly-assigned descriptor. | | | |returns -1 if an error occurred.

Otherwise, | |Bind() |int bind(int sockfd, const struct sockaddr *my_addr, |0 on success | | |socklen_t addrlen); |-1 if an error occurs | |Listen() |int listen(int sockfd, int backlog); |0 on success | | | |-1 if an error occurs | |Accept() int accept(int sockfd, struct sockaddr *cliaddr, socklen_t |the new socket descriptor for the accepted connection, -1 if an error occurs | | |*addrlen); | | |Connect() |int connect(int sockfd, const struct sockaddr *serv_addr, | 0 represents success, | | |socklen_t addrlen); |-1 represents an error | The server program bellow , creates a local namespace socket and listens for connections on it. When it receives a connection, it reads text messages from the connection and prints them until the connection closes. If one of these messages is “quit,” the server program removes the socket and ends.

The socket-server program takes the path to the socket as its command-line argument. While the client program, connects to a local namespace socket and sends a message. The name path to the socket and the message are specified on the command line. *************************************************************************** MODULE: socketserver. c : Local Namespace ***************************************************************************/ #include #include #include #include #include #include /* Read text from the socket and print it out. Continue until the socket closes. Return non-zero if the client sent a “quit” message, zero otherwise. */ int server (int client_socket) { while (1) { nt length; char* text; /* First, read the length of the text message from the socket. If read returns zero, the client closed the connection. */ if (read (client_socket, &length, sizeof (length)) == 0) return 0; /* Allocate a buffer to hold the text. */ text = (char*) malloc (length); /* Read the text itself, and print it. */ read (client_socket, text, length); printf (“%s
”, text); /* Free the buffer. */ free (text); /* If the client sent the message “quit,” we’re all done. */ if (! strcmp (text, “quit”)) return 1; } } int main (int argc, char* const argv[]) { const char* const socket_name = argv[1]; int socket_fd; struct sockaddr_un name; nt client_sent_quit_message; /* Create the socket. */ socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); /* Indicate that this is a server. */ name. sun_family = AF_LOCAL; strcpy (name. sun_path, socket_name); bind (socket_fd, &name, SUN_LEN (&name)); /* Listen for connections. */ listen (socket_fd, 5); /* Repeatedly accept connections, spinning off one server() to deal with each client. Continue until a client sends a “quit” message. */ do { struct sockaddr_un client_name; socklen_t client_name_len; int client_socket_fd; /* Accept a connection. */ client_socket_fd = accept (socket_fd, &client_name, &client_name_len); /* Handle the connection. */ lient_sent_quit_message = server (client_socket_fd); /* Close our end of the connection. */ close (client_socket_fd); } while (! client_sent_quit_message); /* Remove the socket file. */ close (socket_fd); unlink (socket_name); return 0; } *************************************************************************** MODULE: socketclient. c : Local Namespace ***************************************************************************/ #include #include #include #include #include /* Write TEXT to the socket given by file descriptor SOCKET_FD. */ void write_text (int socket_fd, const char* text) { /* Write the number of bytes in the string, including NUL-termination. / int length = strlen (text) + 1; write (socket_fd, &length, sizeof (length)); /* Write the string. */ write (socket_fd, text, length); } int main (int argc, char* const argv[]) { const char* const socket_name = argv[1]; const char* const message = argv[2]; int socket_fd; struct sockaddr_un name; /* Create the socket. */ socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0); /* Store the server’s name in the socket address. */ name. sun_family = AF_LOCAL; strcpy (name. sun_path, socket_name); /* Connect the socket. */ connect (socket_fd, &name, SUN_LEN (&name)); /* Write the text on the command line to the socket. */ write_text (socket_fd, message); lose (socket_fd); return 0; } Communication over sockets looks very similar to the pipe communication except that two processes don’t need to run on the same computer, and are not restricted to a single input and output file per process. There are a framework for communication much superior to the simple socket communication. This general framework will allow extend distributed system as needed, in a simple yet powerful way, while making the remote execution almost transparent to the client code. This framework include RPC(Remote Procedure Call) and RMI( Remote Method Invocation). RPC is a communication protocol with a client/server architecture.

The idea behind RPC is to call code remotely as if we were just calling a procedure or function, RMI ,used in JAVA, is an object-oriented version of RPC, an approach that is slightly simpler. The real difference between RPC and RMI is that there is objects involved in RMI: instead of invoking functions through a proxy function, we invoke methods through a proxy. this means that the client hold references to remote objects that it can invoke methods on. These references should behave just like local objects, but when invoked dispatch the method invocation to the remote object. With RMI system, we can use services implemented on other hosts – running on a distributed system -almost as we would use objects located on the same host. 3. References 1] Silberschatz A. ; Galvin P. and Gagne G. 2005. Operating System Concepts. Seventh Edition. John Wiley&sons. Publishing, United States of America . pp. 96-106. [2]Ramankutty H. July 2004 . Inter-Process Communication – Part 1. Published in Issue 104 of Linux Gazette. http://linuxgazette. net/104/ramankutty. html. [3] Ghosh S. 23 August 2001. Understanding Linux Kernel Inter-process Communication. Published at Linux. com Articles. http://linux. omnipotent. net/article. php? article_id=12504&page=1. [4] Burkett S. March 1995. Interprocess Communication, The Linux Programmer’s Guide. Version 0. 4. pp. 17-68. [5]Mitchell M. , Oldham J. and Samuel A. 001. Advanced Linux Programming . First Edition. New Riders Publishing, United States of America . pp. 95-126. [6] Stallings W. 2005 . Operating Systems: Internals and Design Principles, Fifth Edition Prentice Hall publishing. Content 1. Introduction …………………………………………………….. 1 2. InterProcess Communication mechanisms………………………….. 1 2. 1. Shared memory mechanism………………………………. 2 2. 2. Pipes and FIFO mechanism………………………………. 6 2. 3. Semaphore mechanisms. …………………………………. 9 2. 4. Message Passing mechanism……………………………… 15 2. 5. Sockets mechanism……………………………………….. 20 3. References………………………………………………………….. 24

Cite this Inter Process Communication

Inter Process Communication. (2018, Mar 27). Retrieved from https://graduateway.com/inter-process-communication-essay/

Show less
  • Use multiple resourses when assembling your essay
  • Get help form professional writers when not sure you can do it yourself
  • Use Plagiarism Checker to double check your essay
  • Do not copy and paste free to download essays
Get plagiarism free essay

Search for essay samples now

Haven't found the Essay You Want?

Get my paper now

For Only $13.90/page