Each of the synchronization primitives can be set up to be used across process boundaries. This cross-boundary setup is done by ensuring that the synchronization variable is located in a shared memory segment and by calling the appropriate init routine with type set to USYNC_PROCESS.
If type is set to USYNC_PROCESS, then the operations on the synchronization variables work just as the variables do when type is USYNC_THREAD.
mutex_init(&m, USYNC_PROCESS, 0); rwlock_init(&rw, USYNC_PROCESS, 0); cond_init(&cv, USYNC_PROCESS, 0); sema_init(&s, count, USYNC_PROCESS, 0);
Example 29, Producer and Consumer Problem Using USYNC_PROCESS shows the producer and consumer problem with the producer and consumer in separate processes. The main routine maps zero-filled memory that main shares with its child process, into its address space. Note that mutex_init() and cond_init() must be called because the type of the synchronization variables is USYNC_PROCESS.
A child process is created to run the consumer. The parent runs the producer.
This example also shows the drivers for the producer and consumer. The producer_driver reads characters from stdin and calls the producer. The consumer_driver gets characters by calling the consumer and writes them to stdout.
The data structure for Example 29, Producer and Consumer Problem Using USYNC_PROCESS is the same as that used for the solution with condition variables. See Examples of Using Nested Locking With a Singly-Linked List.
Example 29 Producer and Consumer Problem Using USYNC_PROCESSmain() {
int zfd;
buffer_t *buffer;
zfd = open("/dev/zero", O_RDWR);
buffer = (buffer_t *)mmap(NULL, sizeof(buffer_t),
PROT_READ|PROT_WRITE, MAP_SHARED, zfd, 0);
buffer->occupied = buffer->nextin = buffer->nextout = 0;
mutex_init(&buffer->lock, USYNC_PROCESS, 0);
cond_init(&buffer->less, USYNC_PROCESS, 0);
cond_init(&buffer->more, USYNC_PROCESS, 0);
if (fork() == 0)
consumer_driver(buffer);
else
producer_driver(buffer);
}
void producer_driver(buffer_t *b) {
int item;
while (1) {
item = getchar();
if (item == EOF) {
producer(b, `\0');
break;
} else
producer(b, (char)item);
}
}
void consumer_driver(buffer_t *b) {
char item;
while (1) {
if ((item = consumer(b)) == '\0')
break;
putchar(item);
}
}
A child process is created to run the consumer. The parent runs the producer.