530 likes | 784 Views
ch15: POSIX IPC. Ju, Hong Taek Computer Network Lab. Keimyung University juht@kmu.ac.kr Rm: 1228, Tel: 580-5234. Objectives. Lean about classical interprocess communication Experience with synchronized shared memory Explore semaphore implementation
E N D
ch15: POSIX IPC Ju, Hong Taek Computer Network Lab. Keimyung University juht@kmu.ac.kr Rm: 1228, Tel: 580-5234
Objectives • Lean about classical interprocess communication • Experience with synchronized shared memory • Explore semaphore implementation • Use message queues for interprocess logging • Understand the consequences of persistence
15.1 POSIX:XSI Interprocess Communication • InterProcess Communication (IPC) provides mechanisms for sharing information • among processes on the same system • IPC is part of the POSIX:XSI Extension and has its origin in UNIX System V interprocess communication • IPC inncludes message queue, semaphore sets, shared memory • These mechanisms have a similar structure
15.1.1 Identifying and accessing IPC objects • POSIX:XSI identifies each IPC object by a unique integer: key • greater than or equal to zero • returned form the get function for the object • the same way as the open function • A key must be specified to designate the particular object to be created or accessed • Pick a key in one of the following three ways • Let the system pick a key (IPC_PRIVATE) • Pick a key directly • Ask the system to generate a key from a specified path by calling ftok
The ftok function allows independent processes to derive the same key • Based on a known pathname • The file corresponding to the pathname must exist and accessible that want to access an IPC object • The pathname is a name of file in file system • The id allows several IPC objects of the same type to be keyed form a single pathname • Return a key if successful, otherwise return -1 and set errno #include <sys/ipc.h> key_t ftok(cont char *path, int id);
15.1.2 Accessing POSIX:XSI IPC resources form the shell • The POSIX:XSI Extension for shells and utilities defines shell commands for examining and deleting IPC resources • The ipcs command displays information about POSIX:XSI IPC resources • The ipcrm command removes POSIX:XSI Extension IPC resources ipcs [-qms] [-a | -bcopt] ipcrm [-q msgid | -Q msgkey | -s semid | -S semkey | -m shmid | -M shmkey] ....
15.2 POSIX:XSI Semaphore Sets • A POSIX:XSI semaphore sets consists of an array of semaphore elements • The semaphore elements are similar, but not identical, to the classical integer semaphores as described earlier. • A process can perform operation on the entire set in a single call: AND synchronization • Each semaphore element includes • semval: a nonnegative integer representing the value of the semaphore element • sempid: the process ID of the last process to manipulate the semaphore element • semncnt: the number of processes waiting for the semaphore element value to increase • semzcnt: the number of processes waiting for the semaphore element value to equal 0
The major data structure for the semaphore set is semid_ds • is defined in sys/sem.h • has the following members /* operation permission structure */ struct ipc_perm sem_perm; /* number of semaphores in the set */ unsigned short sem_nsems; time_t sem_otime; /* time of last semop */ time_t sem_ctime; /* time of last semctl */ • Each semaphore element has two queues • A queue of processes waiting for the value to equal to zero • A queue of processes waiting for the value to increase
15.2.1 Semaphore creation • The semget function returns the semaphore identifier associated with the key parameter • creates the identifier and its associated semaphore set • if either the key is IPC_PRIVATE or semflag & IPC_CREAT is nonzero and no semaphore set or identifier is already associated with key • The semflag parameter specifies the number of semaphore elements in the set • The individual semaphore elements are referenced by the integers 0 through nsems-1 • Semaphores have permissions specified by the semflag argument in the same way as for files #include <sys/sem.h> int semget(key_t key, int nsems, int semflag);
The following code segment create a new semaphore set • The IPC_PRIVATE key guarantees that semget creates a new semaphore • The process must specify by using the IPC_CREAT flag that it is creating a new semaphore • To get a new semaphore set from made-up key or a key derived from a pathname #define PERMS (S_IRUSR | S_IWUSR) int semid; if((semid = semget(IPC_PRIVATE, 3, PERMS)) == -1 ) perror(“Fail to create new private semaphore”);
The following code segment access a semaphore set with a identified by the key value 99887 • Giving a specific key value allows cooperating processes to agree on a common semaphore set • If you replace the semflag argument with PERMS | IPC_CREAT | IPC_EXECL when the semaphore already exists, what happen? #define PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) #define KEY ((key_t)99887) int semid; if((semid = semget(KEY, 1, PERMS|IPC_CREAT)) == -1 ) perror(“Fail to access semaphore with key 99887”);
Use ipcs and ipcrm to display and remove the created semaphore set
15.2.2 Semaphore control • Each element of a semaphore set must be initialized with semctl before it is used • Control operations in element semnum for the semaphore set semid • The cmd parameter specifies the type of operation • The optional fourth parameter, arg, depends on the value of cmd • Returns a nonnegative value if the cmd is the GETVAL, GETPID, GETNCNT or GETZCNT, and successful • Returns 0 if all other values of cmd and successful • Returns -1 and sets errno if unsuccessful #include <sys/sem.h> int semctl(int semid, int semnum, int cmd, ...);
Refer Table 15.2 to the value of cmd parameter • The arg parameter is of type union semun, which must be defined in programs that use it union semun { int val; struct semid_ds *buf; unsigned short *array; } arg;
Sets the value of the specified semaphore element to semvalue • Deletes the semaphore specified by semid
15.2.3 POSIX semaphore set operations • The semop function atomically performs a user-defined collection of semaphore operation • semid: the semaphore set • sops: an array of elemet operation • nsops: the number of element operations in the sops array • Returns 0 if successful, otherwise return -1 and sets errno #include <sys/sem.h> int semop(int semid, struct sembuf *sops, size_t nsops);
The semop function performs all the operations specified in sops array atomically on a single semaphore set • If any of the individual element operations would cause the process to block, the process blocks and none of the operations are performed • The struct sembuf structure includes the following members • short sem_num : number of the semaphore element • short sem_op : particular element operation • short sem_flag : flags to specify options for the operation
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 • semop blocks the process on the event that the semaphore element value increases if the adding operation would make the element value negative • semop wakes the processes waiting for 0 if the resulting value is 0
What is wrong with the following code to declare myopbuf and initialize it so that sem_num is 1, sem_op is 1, and sem_flag is 0 struct sembuf myopbuf = {1, -1, 0 }; • The function setsembuf initialize the struct sembuf structure members sem_num, sem_op and sem_flag
The following code segment atomically increments element zero of semid by 1 and element one of semid by 2 struct sembuf myop[2]; setsembuf(myop, 0, 1, 0); setsembuf(myop+1, 1, 2, 0); if( semop(semid, myop, 2) == -1) perror(“Failed to perform semaphore operation”);
Suppose a two-element semaphore set, S, represents a tape drive system in which Process 1 uses Tape A, Process 2 uses Tape A and B, and Process 3 uses Tape B. Both tape drives must be accessed in a mutually exclusive manner.
struct sembuf get_tapes[2]; struct sembuf release_tapes[2]; setsembuf(&(get_tapes[0]), 0, -1, 0); setsembuf(&(get_tapes[1]), 1, -1, 0); setsembuf(&(release_tapes[0]), 0, 1, 0); setsembuf(&(release_tapes[1]), 1, 1, 0); Process 1: semop(S, get_tapes, 1); <use Tape A> semop(S, release_tapes, 1); Process 2: semop(S, get_tapes, 2); <use Tape A and B> semop(S, release_tapes, 2); Process 3: semop(S, get_tapes+1, 1); <use Tape B> semop(S, release_tapes+1, 1);
15.3 POSIX:XSI Shared Memory • Shared memory allows processes to read and write from the same memory segment • The sys/shm.h header file defines the data structures for shared memory, including shmid_ds, which has the following members struct ipc_perm shm_perm; /* operation permission structure */ size_t shm_segsz; /* size of segment in bytes */ pid_t shm_lpid; /* process ID of last operation */ pid_t shm_cpid; /* process ID of creator */ shmatt_t shm_nattch; /* number of current attahces */ time_t shm_atime; /* time of last shmat */ time_t shm_dtime; /* time of last shmdt */ time_t shm_ctime; /* time of last shctl */
15.3.1 Accessing a shared memory segment • The shmget function returns an identifier for the shared memory segment associated with the key parameter • Returns a nonnegative integer corresponding to the shared memory identifier #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);
15.3.2 Attaching and detaching a shared memory segment • The semat function attaches the shared memory segment specified by shmid • Use a shmaddr value of NULL • shmflg for memory alignment • Returns a void * pointer, address of shared memory • When finished, a program calls shmdt to detach the shared memory • Returns 0 if successful, otherwise return -1 #include <sys/shm.h> void *shmat(int shmid, cont void *shmaddr, int shmflg); #include <sys/shm.h> int shmdt(const void *shmaddr);
15.3.3 Controlling shared memory • The shmctl function provides a variety of control operation • shmid: shared memory ID • cmd: operation to be performed • IPC_RMID: remove shared memory • IPC_SET: set value of field from values found in buf • IPC_STAT: copy current values for shared memory into buf • buf: depends on the value of cmd #include <sys/shm.h> int shmctl(int shmid, int cmd, struct chmid_ds *buf);
15.4 POSIX:XSI Message Queues • The message queue allows a process to send and receive message form other processes • The sys/msg.h header file defines the data structures for shared memory, including shmid_ds, which has the following members struct ipc_perm msg_perm; /* operation permission structure */ msgqnum_t msg_qnum; /* number of messages in queue */ msglen_t msg_qbytes; /* maximum bytes allowed in queue */ pid_t msg_lspid; /* process ID of msgsnd */ pid_t msg_lrpid; /* process ID of msgrcv */ time_t shm_stime; /* time of last msgsnd */ time_t shm_rtime; /* time of last msgrcv */ time_t shm_ctime; /* time of last msgctl */
15.4.1 Accessing a message queue • The msgget function returns the message queue identifier associated with the key parameter • Returns a nonnegative integer corresponding to the message queue identifier #include <sys/shm.h> int msgget(key_t key, int msgflg);
A program inserts messages into the queue with msgsnd • The msgp parameter might be defined as follows sturct mymsg { long mtype; /* message type */ char mtext[1]; /* message text */ } • The message type must be greater than 0 and user or application specific value #include <sys/shm.h> int msgsnd (int msgid, const void *msgp, size_t msgsz, int msgflag);
Steps needed to send the string mymessage to a message queue • Allocate a buffer, mbuf, which is of type mymsg_t and size sizeof(mymsg_t) + strlen(mymessage) • Copy mymessage into the mbuf->mtext member • Set the message type in the mbuf->mtype member • Send the message • Free mbuf
A program can remove a message from a message queue with msgrcv • msgp: a user-defined buffer for holding the message to be retrieved • msgsz: the actual size of the message text • msgtyp: for message selection #include <sys/shm.h> int msgrcv (int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflag);
Use msgctl to deallocate or change permissions for the message queue • cmd : specifies the action to be taken • IPC_RMID: remove the message queue • IPC_SET: set member of the msgid_ds data structure from buf • IPC_STAT: copy members of the msgid_ds data structure into buf #include <sys/shm.h> int msgctl (int msgid, int cmd, struct msgid_ds *buf);