CSCE 313 Lecture 17

From Notes
Jump to navigation Jump to search

« previous | Thursday, March 22, 2012 | next »

Review: Interprocess Communication

Message Queue

struct mymsg { /* user-defined */
    long msgtype; /* first field must be a long identifier */
    char mtext[1]; /* placeholder for message content */
}

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
int msgctl(int msqid, int cmd, struct msgid_ds *buf);

Program 15.9 msgqueuelog.c (Chapter 15)

Shared Memory

#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflag);         // allocate shared memory
void *shmat(int shmid, const void *shmaddr, int shmflg); // get data from shared memory

(Binary) Semaphores

#include <sys/sem.h>
int semget(key_t, int nsems, int semflg); // create semaphore set with nsems semaphores; 0 if set already exists
int semctl(int semid, int semnum, int cmd, ...);</code c>

unlike the semaphores previously mentioned, which have P and V operations, POSIX semaphores have only one operation:

<syntaxhighlight lang="c">#include <sys/sem.h>
int semop(int semid, struct sembuf *sopos, size_t, nsops);

struct sembuf {
    short sem_num; // number of semaphore elements
    short sem_op;  // operation to be performed
    short sem_flg; // options for the operation
}
sem_op > 0 Similar to V operation: add value to semaphore element and awaken all processes that are waiting for element to increase
sem_op == 0 && semval != 0 Similar to P operation: block calling process (waiting for 0) and increment the count of processes waiting for 0
sem_op < 0 add sem_op value to semaphore element value provided that result would not be negative. If result is negative, block process and wait for 0
struct sembuf get_tapes[2];
struct sembuf release_tapes[2];

//                              num     op      flag
setsembuf(&(get_tapes[0]),      0,      -1,     0);             // P operation for first tape drive
setsembuf(&(get_tapes[1]),      1,      -1,     0);             // P operation for second tape drive
setsembuf(&(release_tapes[0]),  0,      +1,     0);             // V operation for first tape drive
setsembuf(&(release_tapes[1]),  1,      +1,     0);             // V operation for second tape drive

semop(S, get_tapes, 1);
// use Tape 0
semop(S, release_tapes, 1);

semop(S, get_tapes, 2);
// use both tapes 0 and 1
semop(S, release_tapes, 2);

Control access to critical section

int main(int argc, char *argv[]) {
    int semid;
    struct sembuf sem_signal[1];
    struct sembuf sem_wait[1];

    semid = semget(IPC_PRIVATE, 1, PERMS);
    setsembuf(sem_wait, 0, -1, 0);
    setsembuf(sem_signal, 0, 1, 0);
    init_element(semid, 0, 1);

    // create chain of n processes
    for (int i=1; i<n; i++) if fork() break;

    semop(semid, sem_wait, 1); // enter critical section
    // in critical section
    semop(semid, sem_signal, 1); // exit critical section

    return 0;
}