Transcript XSI IPC

XSI IPC



Message Queues
Semaphores
Shared Memory
XSI IPC

Each XSI IPC structure has two ways to
identify it



An internal (within the Kernel) non
negative integer identifier
An external key value of type key_t
We must specify a key when we create
an XSI IPC structure. This is converted
to an internal identifier by the Kernel
XSI IPC



No file system representation as with
FIFOs
ipcs to list XSI IPCs
ipcrm to remove a XSI IPC
Creating Keys

3 ways



Server creates XSI IPC structure with a key of
IPC_PRIVATE and stores the returned internal
identifier in a file for the client to read
Client and Server agree ahead of time on the key.
Requires error handling in case the key is already
in use
Client and Server agree on a pathname and
project ID and use the ftok function
ftok
key_t ftok(const char *pathname, int proj_id);



pathname must be the path to an
existing file
proj_id contains a value between 0 and
255 (only lower 8 bits of int are used)
Note that occasionally different
pathnames with the same project id can
return the same key!
Permissions Structure
Every XSI IPC structure has a permissions structure
associated with it
struct ipc_perm {
key_t key;
/* Key */
uid_t uid;
/* Effective UID of owner */
gid_t gid;
/* Effective GID of owner */
uid_t cuid;
/* Effective UID of creator */
gid_t cgid;
/* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short seq; /* Sequence number */
};

Permissions Structure



All fields are initialized when the IPC
structure is created
mode is the same as for the open
function but no execute permission
uid, gid, and mode can be modified
with msgctl, semctl or shmctl

Only the creator of the IPC or root can
change these
Message Queues



Similar to FIFO. Allows two (or more)
processes to exchange data
Not FIFO, messages may be retrieved
out of order
Message queue remains until deleted or
system rebooted
Message Queues






Message Queues are linked lists of messages
in Kernel memory
Each message queue has its own identifier
Messages within queue can be of different
types
Queue opened or created with msgget
New messages added with msgsnd
Messages de-queued with msgrcv
Message Queues
struct msqid_ds {
struct ipc_perm msg_perm;
/* Ownership and permissions */
time_t
msg_stime; /* Time of last msgsnd() */
time_t
msg_rtime; /* Time of last msgrcv() */
time_t
msg_ctime; /* Time of last change */
msgqnum_t msg_qnum;
/* Current number of messages
in queue */
msglen_t
msg_qbytes; /* Maximum number of bytes
allowed in queue */
pid_t
msg_lspid; /* PID of last msgsnd() */
pid_t
msg_lrpid; /* PID of last msgrcv() */
…
};
Message Queues

Kernel defined limits




MSGMAX: Max size in bytes of a single
message
MSGMNB: Max size in bytes of a single
queue
MSGMNI: Max number of message queues
system wide
MSGTQL: Max number of messages system
wide
msgget
int msgget(key_t key, int msgflg);
 Gets or creates a queue. msgflg param
is used to initialize the mode member of
the permission structure
 Returns message queue ID if ok and -1
on error
msgsnd
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);



msqid internal ID of message queue
msgsz size in bytes of the message
msgflg


OR of zero or more of: IPC_NOWAIT,
MSG_NOERROR
msgp pointer to actual message
msgsnd

msgp pointer to the actual message.
Must be of the form
struct mymsg {
long mytype;
char mytext[512];
};
msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,
long msgtyp, int msgflg);



Retrieves a message from the queue
msgsz is the size in bytes of the text
portion of the structure pointed to by
msgp
msgp is a pointer to a structure that will
hold the message retrieved from the
queue
msgrcv

msgtyp used to retrieve messages out
of order



msgtyp = 0 - retrieve the first message on
the queue
msgtyp > 0 - return the first message with
a matching type
msgtyp < 0 - return the first message on
the queue with a type <= |msgtyp|
msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);


Performs various operations on a message
queue
cmd



IPC_STAT - gets the msqid_ds structure
IPC_SET - sets the following fields of the
msqid_ds structure: msg_perm.uid,
msg_perm.gid, msg_perm.mode, msg_qbytes
IPC_RMID - removes the queue
Semaphores




Similar to a mutex with a built in
counter
Provides controlled access to shared
resources
Counter may be any positive integer
Binary semaphores – value of 0 or 1
Semaphores

To obtain access to a shared resource



Test the semaphore that controls the
resource
If the value is positive, decrement the
semaphore count by 1 and access the
resource
Otherwise, (value is 0) sleep until another
process releases the resource and
increments the semaphore then repeat
Semaphores
Data structure for semaphore set
struct semid_ds {
struct ipc_perm sem_perm;
time_t
sem_otime; /* Last semop time */
time_t
sem_ctime; /* Last change time */
unsigned short sem_nsems; /* # in set */
…
};

Semaphores
Anonymous data structure for a single semaphore
struct {
unsigned short semval; /* value always >= 0 */
pid_t sempid; /* pid for last operation */
unsigned short semncnt;
unsigned short semzcnt;
…
};

semget

Create or access a semaphore set
int semget(key_t key, int nsems, int semflg);
 nsems number of semaphores in this set.
nsems > 0 when server is creating set, and
== 0 when client is accessing existing set
 semflg the mode member of the
permissions struct is initialized with the
corresponding permission bits of semflg
semop
int semop(int semid, struct sembuf *sops, unsigned nsops);
struct sembuf {
unsigned short sem_num; /* semaphore number */
short
sem_op; /* semaphore operation */
short
sem_flg; /* operation flags */
};



sops is a pointer to an array of sembuf
structs
nsops is the number of elements in the array
All the operations are performed atomically
semop

sem_op



> 0 - process releasing resources. Value of
sem_op added to the semaphores current value
< 0 - process needs resources. If semaphores
value is >= sem_op then sem_op is subtracted
from it and the process can use the resource.
Otherwise, semncnt incremented and process
goes to sleep
== 0 - process wants to wait until the
semaphores value is zero. semzcnt incremented
and process is put to sleep
semctl
int semctl(int semid, int semnum, int cmd, union semun arg);




semid semaphore set ID
semnum index of a particular semaphore in
the set
cmd operation to be performed. IPC_RMID to
delete semaphore. See page 530 for full list
arg optional 4th argument. Not required for all
commands. Note that this is NOT a pointer so
we can’t pass in NULL
Shared Memory



Allows unrelated process to share an
area of memory
Faster because no copying needed
Must be careful to control access (often
through the use of semaphores)
Shared Memory
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t
shm_segsz; /* Size of segment (bytes) */
time_t
shm_atime; /* Last attach time */
time_t
shm_dtime; /* Last detach time */
time_t
shm_ctime; /* Last change time */
pid_t
shm_cpid; /* PID of creator */
pid_t
shm_lpid; /* PID of last shmat()/shmdt() */
shmatt_t
shm_nattch; /* No. of current attaches */
...
};
shmget
int shmget(key_t key, size_t size, int shmflg);
 size number of bytes – specified by the
server when creating the shared memory
area. Client passes zero for this parameter
 shmflg – mode member of permissions
struct set with the corresponding bits
shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);

Attaches a shared memory segment to the
current process



shmid the ID of the shared memory segment
shmaddr if zero is passed in (recommended)
Kernel will attach at first available location
shmflg SHM_RND – rounds to next page
boundary, SHM_RDONLY, 0 (attached read/write)
shmdt
int shmdt(const void *shmaddr);
 Detaches a shared memory segment
 shmaddr is the address of the memory
segment to detach
 Returns 0 on success or -1 on error