<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://homeostasis.scs.carleton.ca/wiki/index.php?action=history&amp;feed=atom&amp;title=Operating_Systems_2019W%3A_Tutorial_8</id>
	<title>Operating Systems 2019W: Tutorial 8 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://homeostasis.scs.carleton.ca/wiki/index.php?action=history&amp;feed=atom&amp;title=Operating_Systems_2019W%3A_Tutorial_8"/>
	<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2019W:_Tutorial_8&amp;action=history"/>
	<updated>2026-04-05T16:59:33Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2019W:_Tutorial_8&amp;diff=22291&amp;oldid=prev</id>
		<title>Soma: Created page with &quot;In this tutorial you will be experimenting with and extending [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/tut4/3000pc.c 3000pc.c] and [http://homeostasis.scs.carle...&quot;</title>
		<link rel="alternate" type="text/html" href="https://homeostasis.scs.carleton.ca/wiki/index.php?title=Operating_Systems_2019W:_Tutorial_8&amp;diff=22291&amp;oldid=prev"/>
		<updated>2019-03-24T22:15:26Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;In this tutorial you will be experimenting with and extending [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/tut4/3000pc.c 3000pc.c] and [http://homeostasis.scs.carle...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;In this tutorial you will be experimenting with and extending [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/tut4/3000pc.c 3000pc.c] and [http://homeostasis.scs.carleton.ca/~soma/os-2017f/code/tut4/3000random.c 3000random.c] (both listed below).&lt;br /&gt;
&lt;br /&gt;
==Key Concepts==&lt;br /&gt;
&lt;br /&gt;
3000pc is a simple implementation of the [https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem producer-consumer problem] in which two processes coordinate their behavior.&lt;br /&gt;
&lt;br /&gt;
In producer-consumer, the two processes share a buffer.  One process &amp;quot;produces&amp;quot; - places things inside the buffer.  The other process &amp;quot;consumes&amp;quot; - takes things out of the buffer.  [https://en.wikipedia.org/wiki/Pipeline_%28Unix%29 UNIX pipes] are a classic implementation of producer-consumer.&lt;br /&gt;
&lt;br /&gt;
In 3000pc, the producer process (the parent process) adds random words to a shared buffer while the consumer (the child process) removes them and prints out the words that it has received.  Note that normally a parent and child process cannot communicate with shared memory; however, here they can because of how the buffer is allocated.  To prevent the contents of the buffer from being corrupted, &amp;#039;&amp;#039;locks&amp;#039;&amp;#039; are used to enforce &amp;#039;&amp;#039;mutual exclusion&amp;#039;&amp;#039;.  If there is nothing for the producer to do (no room in the buffer to add words), it goes to sleep; similarly, the consumer goes to sleep if there are no words for it to consume.  If either process goes to sleep, the other must wake it up.  &lt;br /&gt;
&lt;br /&gt;
3000pc uses the C standard&amp;#039;s way for generating pseudo-random numbers.  This method is fast but not very good.  The Linux kernel, however, has a built-in high quality random number generator.  3000random.c is a demonstration for how to use it.&lt;br /&gt;
&lt;br /&gt;
==Tasks/Questions==&lt;br /&gt;
&lt;br /&gt;
For &amp;#039;&amp;#039;&amp;#039;Questions 3-8&amp;#039;&amp;#039;&amp;#039; make sure you undo your changes before moving on to the next question.&lt;br /&gt;
&lt;br /&gt;
# Compile and run 3000pc.c.  Note that you&amp;#039;ll need to add a &amp;quot;-pthread&amp;quot; option to your compile command.  First run it with a -1 for both delay intervals, then try other values.  When does the producer signal the consumer?  When does the consumer signal the producer?&lt;br /&gt;
# How can you output the random words to a file so that you only see the signal messages on the console?&lt;br /&gt;
# Modify the producer so that it never unlocks each entry (but does lock it).  What happens?&lt;br /&gt;
# Modify the consumer so that it never unlocks each entry (but does lock it).  What happens?&lt;br /&gt;
# What happens if you remove all entry locking/unlocking?  How does the behavior change?&lt;br /&gt;
# Remove the SIGUSR1 signal handler from the producer (so it uses the C library default signal handler).  How does the program behave?&lt;br /&gt;
# Remove the SIGUSR1 signal handler from the consumer (so it uses the C library default signal handler).  How does the program behave?&lt;br /&gt;
# Change the producer and consumer so they only sleep for 1000 nanoseconds (1 millisecond) rather than 1 second during each delay interval.  How does the behavior of the program change?&lt;br /&gt;
# Compile and run 3000random.c.  Note that it takes two arguments.  Where does this program get its random numbers from?&lt;br /&gt;
# Change 3000random.c to use /dev/random rather than /dev/urandom.  How does its performance change, especially when generating a large number of random numbers?&lt;br /&gt;
# Change 3000pc.c to use random numbers from /dev/urandom rather than using the standard library function random().  How does this change affect the relative speed of the producer and consumer processes?&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;(Bonus)&amp;#039;&amp;#039;&amp;#039; Modify 3000pc.c so it takes in an additional command line argument that is the filename of a word list.  This file should have one word per line.  The program should then use this read-in word list rather than the hard coded word list.  Pay attention to:&lt;br /&gt;
#* where you read the file (in the producer, consumer, or before the fork)&lt;br /&gt;
#* where and how you store the words in memory (the word list should be arbitrarily long, but the maximum length of a word can be fixed)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;(Bonus)&amp;#039;&amp;#039;&amp;#039; Modify 3000pc.c so that it has multiple producers and consumers running concurrently, with the number of each specified on the command line.&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
===3000pc.c===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
/* 3000pc.c */&lt;br /&gt;
/* producer-consumer example using signals, processes and mmap */&lt;br /&gt;
/* v1 Oct. 15, 2017 */&lt;br /&gt;
/* Licenced under the GPLv3, copyright Anil Somayaji */&lt;br /&gt;
/* You really shouldn&amp;#039;t be incorporating parts of this in any other code,&lt;br /&gt;
   it is meant for teaching, not production */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mman.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
#include &amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define QUEUESIZE 32&lt;br /&gt;
#define WORDSIZE 16&lt;br /&gt;
&lt;br /&gt;
const int wordlist_size = 27;&lt;br /&gt;
const char *wordlist[] = {&lt;br /&gt;
        &amp;quot;Alpha&amp;quot;,&lt;br /&gt;
        &amp;quot;Bravo&amp;quot;,&lt;br /&gt;
        &amp;quot;Charlie&amp;quot;,&lt;br /&gt;
        &amp;quot;Delta&amp;quot;,&lt;br /&gt;
        &amp;quot;Echo&amp;quot;,&lt;br /&gt;
        &amp;quot;Foxtrot&amp;quot;,&lt;br /&gt;
        &amp;quot;Golf&amp;quot;,&lt;br /&gt;
        &amp;quot;Hotel&amp;quot;,&lt;br /&gt;
        &amp;quot;India&amp;quot;,&lt;br /&gt;
        &amp;quot;Juliet&amp;quot;,&lt;br /&gt;
        &amp;quot;Kilo&amp;quot;,&lt;br /&gt;
        &amp;quot;Lima&amp;quot;,&lt;br /&gt;
        &amp;quot;Mike&amp;quot;,&lt;br /&gt;
        &amp;quot;November&amp;quot;,&lt;br /&gt;
        &amp;quot;Oscar&amp;quot;,&lt;br /&gt;
        &amp;quot;Papa&amp;quot;,&lt;br /&gt;
        &amp;quot;Quebec&amp;quot;,&lt;br /&gt;
        &amp;quot;Romeo&amp;quot;,&lt;br /&gt;
        &amp;quot;Sierra&amp;quot;,&lt;br /&gt;
        &amp;quot;Tango&amp;quot;,&lt;br /&gt;
        &amp;quot;Uniform&amp;quot;,&lt;br /&gt;
        &amp;quot;Victor&amp;quot;,&lt;br /&gt;
        &amp;quot;Whiskey&amp;quot;,&lt;br /&gt;
        &amp;quot;X-ray&amp;quot;,&lt;br /&gt;
        &amp;quot;Yankee&amp;quot;,&lt;br /&gt;
        &amp;quot;Zulu&amp;quot;,&lt;br /&gt;
        &amp;quot;Dash&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
typedef struct entry {&lt;br /&gt;
        char word[WORDSIZE];&lt;br /&gt;
        sem_t lock;&lt;br /&gt;
} entry;&lt;br /&gt;
&lt;br /&gt;
typedef struct shared {&lt;br /&gt;
        int prod_waiting;&lt;br /&gt;
        int con_waiting;&lt;br /&gt;
        entry queue[QUEUESIZE];&lt;br /&gt;
        int last_produced;&lt;br /&gt;
        int last_consumed;&lt;br /&gt;
        pid_t prod_pid;&lt;br /&gt;
        pid_t con_pid;&lt;br /&gt;
        int prod_count;&lt;br /&gt;
        int con_count;&lt;br /&gt;
} shared;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void report_error(char *error)&lt;br /&gt;
{&lt;br /&gt;
        fprintf(stderr, &amp;quot;Error: %s\n&amp;quot;, error);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void usage_exit(char *progname)&lt;br /&gt;
{&lt;br /&gt;
        fprintf(stderr,&lt;br /&gt;
                &amp;quot;Usage: %s &amp;lt;event count&amp;gt; &amp;lt;prod delay int&amp;gt; &amp;lt;con delay int&amp;gt;\n&amp;quot;,&lt;br /&gt;
                progname);&lt;br /&gt;
        exit(-1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void producer_handler(int the_signal)&lt;br /&gt;
{&lt;br /&gt;
        if (the_signal == SIGUSR1) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Producer received SIGUSR1.\n&amp;quot;);&lt;br /&gt;
                return;&lt;br /&gt;
&lt;br /&gt;
        } else {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Producer: No handler for for signal %d?!\n&amp;quot;,&lt;br /&gt;
                        the_signal);&lt;br /&gt;
                return;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void consumer_handler(int the_signal)&lt;br /&gt;
{&lt;br /&gt;
        if (the_signal == SIGUSR1) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Consumer received SIGUSR1.\n&amp;quot;);&lt;br /&gt;
                return;&lt;br /&gt;
        } else {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Consumer: No handler for for signal %d?!\n&amp;quot;,&lt;br /&gt;
                        the_signal);&lt;br /&gt;
                return;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void pick_word(char *word)&lt;br /&gt;
{&lt;br /&gt;
        int pick;&lt;br /&gt;
&lt;br /&gt;
        pick = random() % wordlist_size;&lt;br /&gt;
&lt;br /&gt;
        strcpy(word, wordlist[pick]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void wait_for_producer(shared *s)&lt;br /&gt;
{&lt;br /&gt;
        struct timespec delay;&lt;br /&gt;
        &lt;br /&gt;
        delay.tv_sec = 100;&lt;br /&gt;
        delay.tv_nsec = 0;&lt;br /&gt;
&lt;br /&gt;
        s-&amp;gt;con_waiting = 1;&lt;br /&gt;
        &lt;br /&gt;
        while (s-&amp;gt;con_waiting) {&lt;br /&gt;
                nanosleep(&amp;amp;delay, NULL);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void wait_for_consumer(shared *s)&lt;br /&gt;
{&lt;br /&gt;
        struct timespec delay;&lt;br /&gt;
        &lt;br /&gt;
        delay.tv_sec = 100;&lt;br /&gt;
        delay.tv_nsec = 0;&lt;br /&gt;
&lt;br /&gt;
        s-&amp;gt;prod_waiting = 1;&lt;br /&gt;
        &lt;br /&gt;
        while (s-&amp;gt;prod_waiting) {&lt;br /&gt;
                nanosleep(&amp;amp;delay, NULL);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void wakeup_consumer(shared *s)&lt;br /&gt;
{&lt;br /&gt;
        if (s-&amp;gt;con_waiting) {&lt;br /&gt;
                s-&amp;gt;con_waiting = 0;&lt;br /&gt;
                kill(s-&amp;gt;con_pid, SIGUSR1);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void wakeup_producer(shared *s)&lt;br /&gt;
{&lt;br /&gt;
        if (s-&amp;gt;prod_waiting) {&lt;br /&gt;
                s-&amp;gt;prod_waiting = 0;&lt;br /&gt;
                kill(s-&amp;gt;prod_pid, SIGUSR1);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void output_word(int c, char *w)&lt;br /&gt;
{&lt;br /&gt;
        printf(&amp;quot;Word %d: %s\n&amp;quot;, c, w);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int queue_word(char *word, shared *s)&lt;br /&gt;
{&lt;br /&gt;
        entry *e;&lt;br /&gt;
        int current, retval;&lt;br /&gt;
        &lt;br /&gt;
        current = (s-&amp;gt;last_produced + 1) % QUEUESIZE;&lt;br /&gt;
&lt;br /&gt;
        e = &amp;amp;s-&amp;gt;queue[current];&lt;br /&gt;
&lt;br /&gt;
        sem_wait(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
&lt;br /&gt;
        if (e-&amp;gt;word[0] != &amp;#039;\0&amp;#039;) {&lt;br /&gt;
                /* consumer hasn&amp;#039;t consumed this entry yet */&lt;br /&gt;
                sem_post(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
                wait_for_consumer(s);&lt;br /&gt;
                sem_wait(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e-&amp;gt;word[0] != &amp;#039;\0&amp;#039;) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;ERROR: No room for producer after waiting!\n&amp;quot;);&lt;br /&gt;
                retval = -1;&lt;br /&gt;
                goto done;&lt;br /&gt;
        } else {&lt;br /&gt;
                strncpy(e-&amp;gt;word, word, WORDSIZE);&lt;br /&gt;
                s-&amp;gt;last_produced = current;&lt;br /&gt;
                s-&amp;gt;prod_count++;&lt;br /&gt;
                wakeup_consumer(s);&lt;br /&gt;
                retval = 0;&lt;br /&gt;
                goto done;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
 done:&lt;br /&gt;
        sem_post(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
        return retval;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int get_next_word(char *word, shared *s)&lt;br /&gt;
{&lt;br /&gt;
        entry *e;&lt;br /&gt;
        int current, retval;&lt;br /&gt;
&lt;br /&gt;
        current = (s-&amp;gt;last_consumed + 1) % QUEUESIZE;&lt;br /&gt;
&lt;br /&gt;
        e = &amp;amp;s-&amp;gt;queue[current];&lt;br /&gt;
        &lt;br /&gt;
        sem_wait(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
&lt;br /&gt;
        if (e-&amp;gt;word[0] == &amp;#039;\0&amp;#039;) {&lt;br /&gt;
                /* producer hasn&amp;#039;t filled in this entry yet */&lt;br /&gt;
                sem_post(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
                wait_for_producer(s);&lt;br /&gt;
                sem_wait(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (e-&amp;gt;word[0] == &amp;#039;\0&amp;#039;) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;ERROR: Nothing for consumer after waiting!\n&amp;quot;);&lt;br /&gt;
                retval = -1;&lt;br /&gt;
                goto done;&lt;br /&gt;
        } else {&lt;br /&gt;
                strncpy(word, e-&amp;gt;word, WORDSIZE);&lt;br /&gt;
                e-&amp;gt;word[0] = &amp;#039;\0&amp;#039;;&lt;br /&gt;
                s-&amp;gt;last_consumed = current;&lt;br /&gt;
                s-&amp;gt;con_count++;&lt;br /&gt;
                wakeup_producer(s);&lt;br /&gt;
                retval = 0;&lt;br /&gt;
                goto done;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
 done:&lt;br /&gt;
        sem_post(&amp;amp;e-&amp;gt;lock);&lt;br /&gt;
        return retval;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void producer(shared *s, int event_count, int producer_delay_interval)&lt;br /&gt;
{&lt;br /&gt;
        char word[WORDSIZE];&lt;br /&gt;
        int i;&lt;br /&gt;
        struct sigaction signal_handler_struct;&lt;br /&gt;
 &lt;br /&gt;
        memset (&amp;amp;signal_handler_struct, 0, sizeof(signal_handler_struct));&lt;br /&gt;
        signal_handler_struct.sa_handler = producer_handler;&lt;br /&gt;
&lt;br /&gt;
        if (sigaction(SIGUSR1, &amp;amp;signal_handler_struct, NULL)) {&lt;br /&gt;
            fprintf(stderr, &amp;quot;Producer couldn&amp;#039;t register SIGUSR1 handler.\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        for (i=0; i &amp;lt; event_count; i++) {        &lt;br /&gt;
                pick_word(word);&lt;br /&gt;
                queue_word(word, s);&lt;br /&gt;
                if (producer_delay_interval &amp;gt; 0) {&lt;br /&gt;
                        if (i % producer_delay_interval == 0) {&lt;br /&gt;
                                sleep(1);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Producer finished.\n&amp;quot;);&lt;br /&gt;
        exit(0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void consumer(shared *s, int event_count, int consumer_delay_interval)&lt;br /&gt;
{&lt;br /&gt;
        char word[WORDSIZE];&lt;br /&gt;
        int i;&lt;br /&gt;
        struct sigaction signal_handler_struct;&lt;br /&gt;
 &lt;br /&gt;
        memset (&amp;amp;signal_handler_struct, 0, sizeof(signal_handler_struct));&lt;br /&gt;
        signal_handler_struct.sa_handler = consumer_handler;&lt;br /&gt;
&lt;br /&gt;
        if (sigaction(SIGUSR1, &amp;amp;signal_handler_struct, NULL)) {&lt;br /&gt;
            fprintf(stderr, &amp;quot;Consumer couldn&amp;#039;t register SIGUSR1 handler.\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        for (i=0; i &amp;lt; event_count; i++) {        &lt;br /&gt;
                get_next_word(word, s);&lt;br /&gt;
                output_word(s-&amp;gt;con_count, word);&lt;br /&gt;
                if (consumer_delay_interval &amp;gt; 0) {&lt;br /&gt;
                        if (i % consumer_delay_interval == 0) {&lt;br /&gt;
                                sleep(1);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;Consumer finished.\n&amp;quot;);&lt;br /&gt;
        exit(0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void init_shared(shared *s)&lt;br /&gt;
{&lt;br /&gt;
        int i;&lt;br /&gt;
        &lt;br /&gt;
        s-&amp;gt;con_waiting = 0;&lt;br /&gt;
        s-&amp;gt;last_consumed = -1;&lt;br /&gt;
&lt;br /&gt;
        s-&amp;gt;prod_waiting = 0;&lt;br /&gt;
        s-&amp;gt;last_produced = -1;&lt;br /&gt;
        &lt;br /&gt;
        s-&amp;gt;prod_pid = -1;&lt;br /&gt;
        s-&amp;gt;con_pid = -1;&lt;br /&gt;
&lt;br /&gt;
        s-&amp;gt;prod_count = 0;&lt;br /&gt;
        s-&amp;gt;con_count = 0;&lt;br /&gt;
                &lt;br /&gt;
        for (i=0; i&amp;lt;QUEUESIZE; i++) {&lt;br /&gt;
                s-&amp;gt;queue[i].word[0] = &amp;#039;\0&amp;#039;;&lt;br /&gt;
                /* semaphore is shared between processes,&lt;br /&gt;
                   and initial value is 1 (unlocked) */&lt;br /&gt;
                sem_init(&amp;amp;s-&amp;gt;queue[i].lock, 1, 1); &lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
        int pid, count, prod_interval, con_interval;&lt;br /&gt;
        &lt;br /&gt;
        shared *s;&lt;br /&gt;
&lt;br /&gt;
        srandom(42);&lt;br /&gt;
        &lt;br /&gt;
        if (argc &amp;lt; 4) {&lt;br /&gt;
                if (argc &amp;lt; 1) {&lt;br /&gt;
                        report_error(&amp;quot;no command line&amp;quot;);&lt;br /&gt;
                        usage_exit(argv[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        report_error(&amp;quot;Not enough arguments&amp;quot;);&lt;br /&gt;
                        usage_exit(argv[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        count = atoi(argv[1]);&lt;br /&gt;
        prod_interval = atoi(argv[2]);&lt;br /&gt;
        con_interval = atoi(argv[3]);&lt;br /&gt;
&lt;br /&gt;
        s = (shared *) mmap(NULL, sizeof(shared),&lt;br /&gt;
                             PROT_READ|PROT_WRITE,&lt;br /&gt;
                             MAP_SHARED|MAP_ANONYMOUS, -1, 0);&lt;br /&gt;
        &lt;br /&gt;
        if (s == MAP_FAILED) {&lt;br /&gt;
                report_error(strerror(errno));&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        init_shared(s);&lt;br /&gt;
        &lt;br /&gt;
        pid = fork();&lt;br /&gt;
&lt;br /&gt;
        if (pid) {&lt;br /&gt;
                /* producer */&lt;br /&gt;
                s-&amp;gt;prod_pid = getpid();&lt;br /&gt;
                producer(s, count, prod_interval);&lt;br /&gt;
        } else {&lt;br /&gt;
                /* consumer */&lt;br /&gt;
                s-&amp;gt;con_pid = getpid();&lt;br /&gt;
                consumer(s, count, con_interval);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        /* This line should never be reached */&lt;br /&gt;
        return -1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===3000random.c===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot; line&amp;gt;&lt;br /&gt;
/* 3000random.c */&lt;br /&gt;
/* prints out random numbers obtained from system /dev/urandom */&lt;br /&gt;
/* (This is much, much better than using rand() or random())! */&lt;br /&gt;
/* v1 Oct. 15, 2017 */&lt;br /&gt;
/* Licenced under the GPLv3, copyright Anil Somayaji */&lt;br /&gt;
/* You really shouldn&amp;#039;t be incorporating parts of this in any other code,&lt;br /&gt;
   it is meant for teaching, not production */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE 1024&lt;br /&gt;
&lt;br /&gt;
typedef struct rand_state {&lt;br /&gt;
        unsigned long buffer[BUFSIZE];&lt;br /&gt;
        int current;&lt;br /&gt;
        int fd;&lt;br /&gt;
} rand_state;&lt;br /&gt;
&lt;br /&gt;
void fill_rand_buffer(rand_state *r)&lt;br /&gt;
{&lt;br /&gt;
        ssize_t count;&lt;br /&gt;
&lt;br /&gt;
        count = read(r-&amp;gt;fd, (void *) &amp;amp;r-&amp;gt;buffer,&lt;br /&gt;
                     BUFSIZE * sizeof(unsigned long));&lt;br /&gt;
&lt;br /&gt;
        if (count &amp;gt; sizeof(unsigned long)) {&lt;br /&gt;
                r-&amp;gt;current = (count / sizeof(unsigned long)) - 1;&lt;br /&gt;
                /* was %, that was wrong! */&lt;br /&gt;
                /* left out -1, that was wrong! */&lt;br /&gt;
        } else {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Couldn&amp;#039;t fill random buffer.\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void system_rand_init(rand_state *r)&lt;br /&gt;
{&lt;br /&gt;
        r-&amp;gt;fd = open(&amp;quot;/dev/urandom&amp;quot;, O_RDONLY);&lt;br /&gt;
&lt;br /&gt;
        fill_rand_buffer(r);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
long system_rand(long max, rand_state *r)&lt;br /&gt;
{        &lt;br /&gt;
        unsigned long val;&lt;br /&gt;
&lt;br /&gt;
        if (r-&amp;gt;current &amp;lt; 0) {&lt;br /&gt;
                fill_rand_buffer(r);                &lt;br /&gt;
                if (r-&amp;gt;current &amp;lt; 0) {&lt;br /&gt;
                        /* fill_rand_buffer should have already&lt;br /&gt;
                           reported an error */&lt;br /&gt;
                        return 0;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        val = r-&amp;gt;buffer[r-&amp;gt;current];&lt;br /&gt;
        r-&amp;gt;current--;&lt;br /&gt;
        return val % max;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
        int count, i;&lt;br /&gt;
        long max, x;&lt;br /&gt;
        rand_state r;&lt;br /&gt;
&lt;br /&gt;
        if (argc != 3) {&lt;br /&gt;
                fprintf(stderr, &amp;quot;Usage: %s &amp;lt;count&amp;gt; &amp;lt;max&amp;gt;\n&amp;quot;, argv[0]);&lt;br /&gt;
                exit(-1);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        count = atoi(argv[1]);&lt;br /&gt;
        max = atol(argv[2]);&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;quot;count = %d, max = %ld\n&amp;quot;, count, max);&lt;br /&gt;
        &lt;br /&gt;
        system_rand_init(&amp;amp;r);&lt;br /&gt;
        &lt;br /&gt;
        for (i = 0; i &amp;lt; count; i++) {&lt;br /&gt;
                x = system_rand(max, &amp;amp;r);&lt;br /&gt;
                printf(&amp;quot;%ld\n&amp;quot;, x);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Soma</name></author>
	</entry>
</feed>