The Digital Cat - Chttps://www.thedigitalcatonline.com/2013-04-23T08:29:00+02:00Adventures of a curious cat in the land of programmingConcurrent programming - 62013-04-23T08:29:00+02:002013-04-23T08:29:00+02:00Leonardo Giordanitag:www.thedigitalcatonline.com,2013-04-23:/blog/2013/04/23/concurrent-programming-6/<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Permanent link">¶</a></h2>
<p>Issue 5 of this series ended with a small program where two processes exchanged ten numbers through a message queue, thus being a synchronized producer-consumer couple. This time I am going to show and comment the code of a very simple communication simulator written in C. The code leverages IPC queues to allow multiple processes to talk each other while running concurrently.</p>
<h2 id="the-simulator">The simulator<a class="headerlink" href="#the-simulator" title="Permanent link">¶</a></h2>
<p>The program simulates a messaging switch, where multiple users (child processes) connect to a central switch (parent process) and send text messages (SMS-like) to other users through it. The switch receives messages and route them if the recipient is reachable (process is running). Moreover, the switch can perform a timing operation on a user, checking how much time the user needs to answer a message, or select it for termination. Last, the switch counts how many times a user sends a message to an unreachable user and when a threshold is reached terminates it. Switch and user decisions are taken extracting pseudo-random numbers and comparing them with thresholds given on the command line. Remember that the simulation wants to demonstrate a concrete use of message queues and does not claim to be a complete communication system between processes.</p>
<h2 id="10000-feet-overview">10,000 feet overview<a class="headerlink" href="#10000-feet-overview" title="Permanent link">¶</a></h2>
<p>I splitted the simulator in 3 parts, namely two stacked layers of function and the main application code. The first layer implements the message structure, provides functions to interact with it (getters and setters), exports basic functions to manage queues and to send and receive messages. The second layer exports functions that implement the protocol, i.e. the actions users and switch can perform. Last, the main function contains the actual logic of the whole simulation. Due to the instructional purpose of the simulation some of the solution implemented are far from optimal or even correct (e.g. random numbers management); I suggest you to try to evolve the simulation, adding new services or messages between users.</p>
<h2 id="debugging-nightmares">Debugging nightmares<a class="headerlink" href="#debugging-nightmares" title="Permanent link">¶</a></h2>
<p>Be ready to spend some time debugging your multiprocessing applications! If you ever debugged some code, you know that the most friendly bugs are by far those which are reproducible: you only need to add some debugging output or step through the code with the debugger and the bug is spotted. Multiprocessing and network application are at the very opposite corner: most of the time the bugs in that sort of applications are very difficult to reproduce, when not impossible. The concurrent execution of multiple processes, indeed, makes every execution unique, since the actual execution sequence is random (random means that it is the result of so many factors that the result is unpredictable and thus irreproducible). Network programs suffers from the same problems (concurrent execution), worsened by network lags that add a factor of randomness.</p>
<h2 id="code-and-analysis">Code and analysis<a class="headerlink" href="#code-and-analysis" title="Permanent link">¶</a></h2>
<p>I am not going to include the whole code of the layers directly in the post text as they are a straightforward implementation of what was presented in the previous articles; the code of the main application is, on the contrary, analyzed block by block. The links to the source files are at the end of the article, together with compilation instructions.</p>
<h2 id="layer-1">Layer 1<a class="headerlink" href="#layer-1" title="Permanent link">¶</a></h2>
<h4 id="message-structure">Message structure<a class="headerlink" href="#message-structure" title="Permanent link">¶</a></h4>
<p>The structure of the message is</p>
<div class="highlight"><pre><span></span><code><span class="k">typedef</span><span class="w"> </span><span class="k">struct</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">sender</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">recipient</span><span class="p">;</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">text</span><span class="p">[</span><span class="mi">160</span><span class="p">];</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">service</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">service_data</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="n">message_t</span><span class="p">;</span>
<span class="k">typedef</span><span class="w"> </span><span class="k">struct</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">mtype</span><span class="p">;</span>
<span class="w"> </span><span class="n">message_t</span><span class="w"> </span><span class="n">mtext</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="n">messagebuf_t</span><span class="p">;</span>
</code></pre></div>
<p>Here, <code>sender</code> and <code>recipient</code> are numbers that identify the switch and the users (0 is the switch, then users are numbered increasingly when they connect to the switch); <code>text</code> is the content of a message a user sends to another user, and is 160 characters long to mimic SMS behaviour. Last <code>service</code> is the identifier of some system operation, like a request the switch sends to the users; <code>service_data</code> carries the optional data the service needs to communicate. Actual services are implemented in layer 2 and I am going to describe them later.</p>
<h4 id="other-functions">Other functions<a class="headerlink" href="#other-functions" title="Permanent link">¶</a></h4>
<p>Layer 1 exposes many functions: some are simple set and get functions to deal with the message structure while five simplify access to IPC structures; <code>build_key()</code> makes an IPC key from a given character, <code>create_queue()</code> and <code>remove_queue()</code> manage IPC queues and last <code>send_message()</code> and <code>receive_message()</code> give a simple way to route messages.</p>
<p>A very simple error management code has been introduced here: C language does not allow to use exceptions, so errors have to be managed by functions or returned through the <code>return</code> statement. A solid error management in C is outside the scope of this article, so here you will find the bare minimum.</p>
<p>The error management of <code>receive_message()</code> needs a little explanation.</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">receive_message</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">type</span><span class="p">,</span><span class="w"> </span><span class="n">messagebuf_t</span><span class="w"> </span><span class="o">*</span><span class="n">qbuf</span><span class="p">){</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">;</span>
<span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">messagebuf_t</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="p">((</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">msgrcv</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">msgbuf</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="n">qbuf</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">type</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">))</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">errno</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">ENOMSG</span><span class="p">){</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="p">{</span>
<span class="w"> </span><span class="n">perror</span><span class="p">(</span><span class="s">"msgrcv"</span><span class="p">);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Here, <code>msgrcv()</code> fails even when there are no messages of the given type, producing a <code>ENOMSG</code> error. This is the reason why that case has been ignored through the <code>if(errno == ENOMSG)</code> construct.</p>
<h2 id="layer-2">Layer 2<a class="headerlink" href="#layer-2" title="Permanent link">¶</a></h2>
<h4 id="the-protocol">The protocol<a class="headerlink" href="#the-protocol" title="Permanent link">¶</a></h4>
<p>Layer2 implements the actual communication protocol between the switch and the users. Users send text messages to other users, and those messages are routed by the switch. Users and switch can also send service messages; those are messages encompassing information used to manage the system. </p>
<p>Every user, when spawned, initializes a queue, connects to the switch and communicates the queue id. Since the queues can contain old unread messages, it is necessary to empty them before the use. Each user enters a loop where it sleeps a while, receives service messages, sends messages and last receives text messages. At the same time, the switch collects queue ids, routes text messages from the sender to the recipient and sometimes sends a service request to a user.</p>
<p>The services the switch can request from users are to terminate and to test the answering time. Both can be requested on a probability base, but the first is also forced when the user sends too many messages to unreachable recipients.</p>
<p>The answering time test is performed in a simple way: the switch requests the service and records the time of the request. The user answers with a message that contains the time at which it received the request and the switch computes the difference between the two. Pay attention that both the timing service and the random number extraction used to request services on a probability base are not exact; the code works but is good only for a demonstration system.</p>
<p>I defined some useful constants in the header file: <code>MAX_SLEEP</code> is the maximum number of seconds a user waits before performing an action while <code>TYPE_SERVICE</code> and <code>TYPE_TEXT</code> identify the type of message. The defines which name starts with <code>SERVICE_</code> list all the possible services: <code>SERVICE_TERMINATE</code> forces a user to quit; <code>SERVICE_TIME</code> makes it perform a timing operation; <code>SERVICE_CONNECT</code> and <code>SERVICE_DISCONNECT</code> tell the switch a new user has connected or disconnected; <code>SERVICE_QID</code> bears the identifier of the user queue to the switch; <code>SERVICE_UNREACHABLE_DESTINATION</code> communicates a user that the recipient of a message is no more online.</p>
<h4 id="queues">Queues<a class="headerlink" href="#queues" title="Permanent link">¶</a></h4>
<p>Two functions are dedicated to queues, <code>init_queue()</code> and <code>close_queue()</code>. The first builds an IPC key from a given number (previously converting it to a char) and runs the <code>create_queue()</code> function from layer 1. Because of the char conversion the range of integers it can accept is 0-255, and for simplicity's sake there is no check in the whole code that a queue key has not yet been assigned. For this example, I am simply leveraging that different numbers return different keys and, thus, queues.</p>
<p>The second function closes the queue running the <code>remove_queue()</code> function from layer 1. The underlying system calls are not used directly to allow the future introduction of checks on the assigned queues.</p>
<h4 id="user-functions">User functions<a class="headerlink" href="#user-functions" title="Permanent link">¶</a></h4>
<p>Users have five functions that implement their part of the protocol. Two functions communicate to the switch that the user connected or disconnected, namely <code>user_send_connect()</code> and <code>user_send_disconnect()</code>; both carry the <code>sender</code> id and the switch id <code>sw</code>, which however in the main program is always 0. The <code>user_send_qid()</code> function communicates to the switch the queue id of the user; <code>user_send_text_message()</code> sends a string of text to another user and <code>user_send_time()</code> answers the timing service.</p>
<h4 id="switch-functions">Switch functions<a class="headerlink" href="#switch-functions" title="Permanent link">¶</a></h4>
<p>The switch can execute <code>switch_send_text_message()</code> to deliver a text message sent by a user; <code>switch_send_terminate()</code> to ask a user to terminate; <code>switch_send_time()</code> to ask a user to perform a timing service.</p>
<h4 id="code-analysis">Code analysis<a class="headerlink" href="#code-analysis" title="Permanent link">¶</a></h4>
<p>Now I will briefly review the whole application code to better explain the different parts of the system. Please remember that this is a demonstration system so many choices have been made for simplicity's sake.</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><unistd.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/msg.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><time.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><signal.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><wait.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"layer1.h"</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"layer2.h"</span>
<span class="cp">#define MINCHILDS 1</span>
<span class="cp">#define MAXCHILDS 15</span>
<span class="cp">#define MAXFAILS 10</span>
</code></pre></div>
<p>After the list of includes, you will find three defines that rule the number of child processes the system can spawn and the maximum number of messages a user can send to unreachable recipients before the switch asks it to terminate.</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">random_number</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">max</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">r</span><span class="p">,</span><span class="n">x</span><span class="p">;</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="w"> </span><span class="n">random</span><span class="p">();</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="kt">double</span><span class="p">)</span><span class="w"> </span><span class="n">max</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">RAND_MAX</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="p">((</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">usage</span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Telephone switch simulator</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s <number of users> <service probability> <text message probability></span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" <number of users> - Number of users alive in the system (%d - %d)</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">MINCHILDS</span><span class="p">,</span><span class="w"> </span><span class="n">MAXCHILDS</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" <service probability> - The probability that the switch requires a service from the user (0-100)</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" <text message probability> - The probability the a user sends a message to another user (0-100)</span><span class="se">\n\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>The <code>random_number()</code> function is used to extract a random number between 0 and a maximum <code>max</code>; <code>RAND_MAX</code> is a define of the standard library and represents the maximum number the <code>random()</code> function can return and in the GNU C library it is 2^31 (2147483647); here it is used to calculate a proportion with the maximum value given by the caller. The <code>usage()</code> function helps the user remembering the command line arguments; as you can see, the program receives 3 mandatory input values: the number of users that the switch can spawn; the probability that the switch requests a service to a user when the latter sends a message; the probability that a user sends a text message to another user.</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">users_number</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">service_probability</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">text_message_probability</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">status</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">deadproc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="cm">/* A counter of the already terminated user processes */</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">qid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">sw</span><span class="p">;</span><span class="w"> </span><span class="cm">/* Qid of the switch */</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">dest</span><span class="p">;</span><span class="w"> </span><span class="cm">/* Destination of the message */</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">olddest</span><span class="p">;</span><span class="w"> </span><span class="cm">/* Destination of the previous message */</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">queues</span><span class="p">[</span><span class="n">MAXCHILDS</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span><span class="w"> </span><span class="cm">/* Queue identifiers - 0 is the qid of the switch */</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msg_recipient</span><span class="p">;</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">msg_text</span><span class="p">[</span><span class="mi">160</span><span class="p">];</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msg_service</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msg_service_data</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">t</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">MAXCHILDS</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">];</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">unreachable_destinations</span><span class="p">[</span><span class="n">MAXCHILDS</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">];</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">padding</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">" "</span><span class="p">;</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">text</span><span class="p">[</span><span class="mi">160</span><span class="p">];</span>
<span class="w"> </span><span class="n">messagebuf_t</span><span class="w"> </span><span class="n">msg</span><span class="p">,</span><span class="w"> </span><span class="n">in</span><span class="p">;</span>
</code></pre></div>
<p>Many of these variables are just helpers that simplify the code; <code>queues</code> holds the queue identifier of each process; <code>timing</code> holds the information about user timing service results; <code>unreachable_destinations</code> contains how many times each user sent a message to an unreachable recipient; <code>dest</code> and <code>olddest</code> are used to avoid a user to send a message to the recipient of the previous one. The <code>padding</code> variable is a quick and dirty way to create two columns, the left one filled by switch messages and the right one by user ones.</p>
<p>Remember that in C you have to declare variables at the beginning of the program while in C++ you can declare them anywhere. This means that child processes, a copy of the parent, carry in memory some variables such as <code>queues</code> and <code>timings</code> that are used only by the switch. This is both a waste of resources and a dangerous situation, so remember that in general statically allocated variables are not a good choice for concurrent programs.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Command line argument parsing */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">argc</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">4</span><span class="p">){</span>
<span class="w"> </span><span class="n">usage</span><span class="p">(</span><span class="n">argv</span><span class="p">);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">users_number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strtol</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">);</span><span class="w"> </span>
<span class="w"> </span><span class="n">service_probability</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strtol</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">);</span>
<span class="w"> </span><span class="n">text_message_probability</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strtol</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="p">((</span><span class="n">users_number</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">MINCHILDS</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">users_number</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">MAXCHILDS</span><span class="p">)){</span>
<span class="w"> </span><span class="n">usage</span><span class="p">(</span><span class="n">argv</span><span class="p">);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="p">((</span><span class="n">service_probability</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">service_probability</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">100</span><span class="p">)){</span>
<span class="w"> </span><span class="n">usage</span><span class="p">(</span><span class="n">argv</span><span class="p">);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="p">((</span><span class="n">text_message_probability</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">text_message_probability</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">100</span><span class="p">)){</span>
<span class="w"> </span><span class="n">usage</span><span class="p">(</span><span class="n">argv</span><span class="p">);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Number of users: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">users_number</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Probability of a service request: %d%%</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">service_probability</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Probability of a text message: %d%%</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">text_message_probability</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize the random number generator */</span>
<span class="w"> </span><span class="n">srandom</span><span class="p">(</span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
</code></pre></div>
<p>All these lines contain initialization code and checks for the values passed on the command line.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Switch queue initialization */</span>
<span class="w"> </span><span class="n">sw</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">init_queue</span><span class="p">(</span><span class="mi">255</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Read the last messages we have in the queue */</span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">sw</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_TEXT</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Receiving old text messages</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Read the last messages we have in the queue */</span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">sw</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_SERVICE</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Receiving old service messge</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* All queues are "uninitialized" (set equal to switch queue) */</span>
<span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">users_number</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">queues</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sw</span><span class="p">;</span>
<span class="w"> </span><span class="n">unreachable_destinations</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>The switch initializes its queue; this has to be done before spawning users since the <code>sw</code> variable will be copied in each child process and used to communicate with the switch. The queue is initialized with the number 255 just to be sure that no child process initializes the same queue. As explained, IPC queues provide no mechanism to ensure uniqueness of the instanced queues, so we have to establish our own system; in this simple example we spawn a maximum of 15 users, so we could also use <code>16</code> or <code>MAXCHILDS+1</code> to initialize the switch queue. Since queues are shared structures and nothing prevents the system to assign to a process a previously used queue we must ensure that the queue is empty, so the switch reads and discards all text and service messages found in its queue. Last, the <code>queues</code> and <code>unreachable_destinations</code> arrays are initialized.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Create users */</span>
<span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">users_number</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">){</span>
<span class="w"> </span><span class="n">srandom</span><span class="p">(</span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1000</span><span class="o">*</span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize queue */</span>
<span class="w"> </span><span class="n">qid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">init_queue</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Read the last messages we have in the queue */</span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_TEXT</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Receiving old text messages</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Read the last messages we have in the queue */</span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_SERVICE</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Receiving old service messge</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Let the switch know we are alive */</span>
<span class="w"> </span><span class="n">user_send_connect</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">sw</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Let the switch know how to reach us */</span>
<span class="w"> </span><span class="n">user_send_qid</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">sw</span><span class="p">);</span>
</code></pre></div>
<p>This code spawns the users and from here the code splits in two, and the code of the user processes is inside the if construct. As you can see, the user acts like the switch at the very beginning, initializing its own queue and flushing the possible messages it contains. After this, the user sends the switch a message to communicate that it is alive and sends its qid to allow the user to communicate.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Enter the main loop */</span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">){</span>
<span class="w"> </span><span class="n">sleep</span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="n">MAX_SLEEP</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Check if the switch requested a service */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_SERVICE</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">msg_service</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_service</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">msg_service</span><span class="p">){</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">SERVICE_TERMINATE</span><span class="p">:</span>
<span class="w"> </span><span class="cm">/* Send an acknowledgement to the switch */</span>
<span class="w"> </span><span class="n">user_send_disconnect</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">(),</span><span class="w"> </span><span class="n">sw</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Read the last messages we have in the queue */</span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_TEXT</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">msg_sender</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_sender</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="n">get_text</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Message received</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s Sender: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s Text: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Remove the queue */</span>
<span class="w"> </span><span class="n">close_queue</span><span class="p">(</span><span class="n">qid</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Termination</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">SERVICE_TIME</span><span class="p">:</span>
<span class="w"> </span><span class="n">user_send_time</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">sw</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Timing</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>The user loops infinitely and at each loop sleeps a random number of seconds. After that, it checks its message queue for service messages (<code>receive_message()</code> with the parameter <code>TYPE_SERVICE</code>); if the requested service is <code>SERVICE_TERMINATE</code>, an acknowledgement is sent to the switch (<code>user_send_disconnect()</code>) so that the user is marked as offline and no more messages are sent with it as recipient. The user then reads all remaining text messages in its queue and closes the queue. Last with <code>exit()</code>the user process terminates. If the requested service is <code>SERVICE_TIME</code>, the user simply sends the current time back to the switch through <code>user_send_time()</code>.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Send a message */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">random_number</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">text_message_probability</span><span class="p">){</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">random_number</span><span class="p">(</span><span class="n">users_number</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Do not send a message to the switch, to yourself and to the previous recipient */</span>
<span class="w"> </span><span class="k">while</span><span class="p">((</span><span class="n">dest</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">dest</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">dest</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">olddest</span><span class="p">)){</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">random_number</span><span class="p">(</span><span class="n">users_number</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">olddest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dest</span><span class="p">;</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Message to user %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">dest</span><span class="p">);</span>
<span class="w"> </span><span class="n">sprintf</span><span class="p">(</span><span class="n">text</span><span class="p">,</span><span class="w"> </span><span class="s">"A message from me (%d) to you (%d)"</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">dest</span><span class="p">);</span>
<span class="w"> </span><span class="n">user_send_text_message</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">dest</span><span class="p">,</span><span class="w"> </span><span class="n">text</span><span class="p">,</span><span class="w"> </span><span class="n">sw</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Check the incoming box for simple messages */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_TEXT</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">msg_sender</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_sender</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="n">get_text</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s%d -- U %02d -- Message received</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s Sender: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%s Text: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">padding</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>The user extracts a random number and tests it against the probability given on the command line; if the test gives a positive result the user extracts a random user, avoiding the switch (<code>dest == 0</code>), itself (<code>dest == i</code>) and the recipient of the previous message it sent (<code>dest == olddest</code>). The new recipient is saved in <code>olddest</code>, and the message is sent through <code>user_send_text_message()</code>. This part ends the user code.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Switch (parent process) */</span><span class="w"> </span>
<span class="w"> </span><span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">){</span>
<span class="w"> </span><span class="cm">/* Check if some user is answering to service messages */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">sw</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_SERVICE</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">msg_service</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_service</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="n">msg_sender</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_sender</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">msg_service</span><span class="p">){</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">SERVICE_CONNECT</span><span class="p">:</span>
<span class="w"> </span><span class="cm">/* A new user has connected */</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Service: connection</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" User: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">SERVICE_DISCONNECT</span><span class="p">:</span>
<span class="w"> </span><span class="cm">/* The user is terminating */</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Service: disconnection</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" User: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">deadproc</span><span class="o">++</span><span class="p">;</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">SERVICE_QID</span><span class="p">:</span>
<span class="w"> </span><span class="cm">/* The user is sending us its queue id */</span>
<span class="w"> </span><span class="n">msg_service_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_service_data</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Service: queue</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" User: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Qid: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_service_data</span><span class="p">);</span>
<span class="w"> </span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">msg_service_data</span><span class="p">;</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">SERVICE_TIME</span><span class="p">:</span>
<span class="w"> </span><span class="n">msg_service_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_service_data</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Timing informations */</span>
<span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">msg_service_data</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Service: timing</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" User: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Timing: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
<span class="w"> </span><span class="cm">/* The user is no more blocked by a timing operation */</span>
<span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>The switch code has a structure similar to that of the user code. It loops infinitely with a <code>while(1)</code> statement, and inside this it checks for incoming messages and acts accordingly. The first thing it does is to check for service messages. If the service is <code>SERVICE_CONNECT</code> a user is communicating that it is alive, and the switch simply print out a log of this event; when a user disconnects it sends a <code>SERVICE_DISCONNECT</code> message and the switch increases the number of dead processes to monitor the number of active user processes; if the service is a <code>SERVICE_QID</code> a user is sending the switch its queue identifier and this is stored in the <code>queues</code> array; last, the <code>SERVICE_TIME</code> messages mean that a user is answering a timing request; its answer is compared with the recorded send time and the result is printed.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Check if some user has connected */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">receive_message</span><span class="p">(</span><span class="n">sw</span><span class="p">,</span><span class="w"> </span><span class="n">TYPE_TEXT</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">in</span><span class="p">)){</span>
<span class="w"> </span><span class="n">msg_recipient</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_recipient</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="n">msg_sender</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_sender</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">);</span>
<span class="w"> </span><span class="n">get_text</span><span class="p">(</span><span class="o">&</span><span class="n">in</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* If the destination is connected */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">queues</span><span class="p">[</span><span class="n">msg_recipient</span><span class="p">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">sw</span><span class="p">){</span>
<span class="w"> </span><span class="cm">/* Send the message (forward it) */</span>
<span class="w"> </span><span class="n">switch_send_text_message</span><span class="p">(</span><span class="n">msg_sender</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">,</span><span class="w"> </span><span class="n">queues</span><span class="p">[</span><span class="n">msg_recipient</span><span class="p">]);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Routing message</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Sender: %d -- Destination: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">,</span><span class="w"> </span><span class="n">msg_recipient</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Text: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="p">{</span>
<span class="w"> </span><span class="n">unreachable_destinations</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">unreachable_destinations</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="n">MAXFAILS</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">continue</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- Unreachable destination</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Sender: %d -- Destination: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">,</span><span class="w"> </span><span class="n">msg_recipient</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Text: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">msg_text</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" Threshold: %d/%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">unreachable_destinations</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">],</span><span class="w"> </span><span class="n">MAXFAILS</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">unreachable_destinations</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">MAXFAILS</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- User %d reached max unreachable destinations</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">switch_send_terminate</span><span class="p">(</span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]);</span>
<span class="w"> </span><span class="cm">/* Remove its queue from the list */</span>
<span class="w"> </span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sw</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>Here, the switch checks the queue for incoming text messages users send to other users. If the recipient is connected (reachable) the message is routed through <code>switch_send_text_message()</code>; otherwise the counter of failed dispatches <code>unreachable_destinations</code> is incremented for that user; when the maximum number of failures <code>MAXFAILS</code> is reached the switch sends that user a termination request.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Randomly request a service to the sender of the last message */</span>
<span class="w"> </span><span class="k">if</span><span class="p">((</span><span class="n">random_number</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">service_probability</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">sw</span><span class="p">)){</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">random_number</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">40</span><span class="p">){</span>
<span class="w"> </span><span class="cm">/* The user must terminate */</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- User %d chosen for termination</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">),</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">switch_send_terminate</span><span class="p">(</span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]);</span>
<span class="w"> </span><span class="cm">/* Remove its queue from the list */</span>
<span class="w"> </span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sw</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* Check if we are already timing that user */</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">0</span><span class="p">]){</span>
<span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"%d -- S -- User %d chosen for timing...</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">timing</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="n">msg_sender</span><span class="p">);</span>
<span class="w"> </span><span class="n">switch_send_time</span><span class="p">(</span><span class="n">queues</span><span class="p">[</span><span class="n">msg_sender</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>Each user that sends a message through the switch can be selected as the destination of a service request. Here, the switch tests a random number against the probability given on the command line, ensuring that the users is not already unreachable. The probability of a termination service is hardcoded (40%), the other case being the timing service; when the latter is requested, the switch sends a message to the user recording the dispatch time so that it can be later compared with the user answer.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">else</span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">deadproc</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">users_number</span><span class="p">){</span>
<span class="w"> </span><span class="cm">/* All childs have been terminated, just wait for the last to complete its jobs */</span>
<span class="w"> </span><span class="n">waitpid</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">status</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Remove the switch queue */</span>
<span class="w"> </span><span class="n">remove_queue</span><span class="p">(</span><span class="n">sw</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"No more active users. Switch turns off.</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Terminate the program */</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>When there are no incoming messages the switch checks if the number of dead processes is equal to the number of users; when this happens the switch waits for each child process (to avoid zombie processes), removes its queue and terminates.</p>
<h2 id="files-and-compilation">Files and compilation<a class="headerlink" href="#files-and-compilation" title="Permanent link">¶</a></h2>
<p>The 5 files of this small program can be downloaded here:</p>
<ul>
<li><a href="/code/ipc_demo/layer1.h">layer1.h</a></li>
<li><a href="/code/ipc_demo/layer1.c">layer1.c</a></li>
<li><a href="/code/ipc_demo/layer2.h">layer2.h</a></li>
<li><a href="/code/ipc_demo/layer2.c">layer2.c</a></li>
<li><a href="/code/ipc_demo/main.c">main.c</a></li>
</ul>
<p>and can be compiled with the following command line</p>
<div class="highlight"><pre><span></span><code>gcc<span class="w"> </span>-o<span class="w"> </span>ipc_demo<span class="w"> </span>main.c<span class="w"> </span>layer1.c<span class="w"> </span>layer2.c
</code></pre></div>
<p>A typical execution can be obtained running the program with the following parameters</p>
<div class="highlight"><pre><span></span><code>./ipc_demo<span class="w"> </span><span class="m">8</span><span class="w"> </span><span class="m">30</span><span class="w"> </span><span class="m">80</span>
</code></pre></div>
<p>Remember that the output lines of the processes are mixed and generally not in order; indeed, you can find the answer of a user printed before the switch request. Timestamps can help you find the right order, but the resolution of the <code>time()</code> function is a second, and in such a time span many messages can be sent.</p>
<h2 id="conclusions">Conclusions<a class="headerlink" href="#conclusions" title="Permanent link">¶</a></h2>
<p>This article ends by now this little series on concurrent programming in C and IPC structures. As you can see C is not the best language to implement concurrent programming concepts, due to its very low level nature. However, since many OSs are written in C (and/or C++) knowledge of the way this language can provide concurrent execution is useful.</p>
<p>There is much left to say about concurrent programming structures: atomicity, mutual exclusions, threads, monitors are just some of the most important. I will post new articles on such topics in the future, perhaps showing their implementation in other languages.</p>Concurrent programming - 52013-02-28T17:49:00+02:002013-02-28T17:49:00+02:00Leonardo Giordanitag:www.thedigitalcatonline.com,2013-02-28:/blog/2013/02/28/concurrent-programming-5/<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Permanent link">¶</a></h2>
<p>In the past articles we introduced the concept of concurrent programming and studied a first solution to the problem of intercommunication: semaphores. As explained, the use of semaphores allows us to manage access to shared resources, and this is a first and very simple form of synchronization. In this issue, we will go one step further introducing a richer tool for concurrent programming: <em>message queues</em>.</p>
<h2 id="limits-of-semaphores">Limits of semaphores<a class="headerlink" href="#limits-of-semaphores" title="Permanent link">¶</a></h2>
<p>Ruling access to a resource through semaphores is a good form of synchronization, even if it is very limited. Indeed it prevents two or more processes simultaneously modifying shared data but does not allow them to exchange information.</p>
<p>Moreover, the basic use of semaphores does not guarantee the absence of dangerous situations. As an example remember that, in a multitasking environment, we do not know in advance which process will be executed and when. This means that a resource could be inaccessible for a process since it is always blocked by other processes.</p>
<p>Thus, while being a good tool in the multitasking programmer's bag, semaphores are not the final solution to his or her problems. So we now introduce a new tool which plays a big role in multitasking and distributed systems called <strong>message queues</strong>.</p>
<h2 id="message-queues-theory">Message queues theory<a class="headerlink" href="#message-queues-theory" title="Permanent link">¶</a></h2>
<p>Since message queues are one of the most important structures in computer science, let us dive into them at a slow pace. So first of all, what is a <strong>message</strong> in this context? Simply stated, a message is some <strong>data</strong> with a given <strong>format</strong>, which is a complex form to say everything. Indeed in the context of communication between processes, or computers, a message is a stream of bits which must be formatted according to a previously agreed format, where format means a set of rules the stream of bit must obey.</p>
<p>For example, we could simply state that a message is a raw extended <a href="https://en.wikipedia.org/wiki/ASCII">ASCII</a> string: this means that the stream must contain a multiple of 8 bits (since each extended ASCII character is represented by 8 bits). Our format is very simple, in this case, but it is enough to state that a message made of 377 bit is invalid. We can also make a message encompass entire files, and there is in general no limit to the size.</p>
<p>Now we have a definition of message. What is a <strong>queue</strong>? A queue is a list structure, where a given number of <em>homogeneous</em> objects can be stored. An object can be inserted in the list (<strong>push</strong>ed) and extracted from it (<strong>pop</strong>ped). Usually a queue in the messaging environment is a FIFO (First In First Out) one, meaning that the first object pushed is the first object popped. There is a plenty of mathematical and computer science theory about queues, buffers, FIFO, LIFO and other list types, and we will not review such topics here. Just a notice, to open further research by the reader: the stack, one of the most important concepts in programming, is also a memory buffer, or a queue, where the computer stores function calls and local variables.</p>
<p>So message queues are buffers where arbitrary (but homogeneous) objects called messages can be stored for a later retrieval.</p>
<p>Every process can create one or more queues and every process can send a message to one of them. The only prerequisite is that the unique identifier of the queue must be known. Since we are now working with processes spawned by a fork operation, each process can know the identifier of a queue if the queue has been created before executing <code>fork()</code>.</p>
<p>The knowledge of a queue identifier makes it is also possible to read messages from it. Messages can be accessed sequentially, reading the messages in chronological order (from the oldest, the first, to the most recent, the last arrived), but selectively, that is considering only the messages of a certain type: this last feature give us a sort of control on the priority of the messages we read.</p>
<p>Queues, therefore, can be used to implement several communication scenarios, from the simplest ones where all processes send messages to and read messages from the same queue, to more complex solutions such as a full mail system between processes.</p>
<p>Irrespective of the communication framework we set for our processes, synchronization can now be performed through a richer tool. Processes needing synchronization can exchange messages to establish the correct timings schedule when performing actions. Messages, thus, do not replace semaphores, but, as already seen, cover functionalities that they cannot provide.</p>
<p>Before we can switch to implement message queues in C language, it is necessary to speak about another problem related to messages: the need of a <em>communication protocol</em>.</p>
<h2 id="creating-a-protocol">Creating a protocol<a class="headerlink" href="#creating-a-protocol" title="Permanent link">¶</a></h2>
<p>A <strong>protocol</strong> is a set of rules which control the interaction of elements in a set. Every time you must regulate the exchange of information between two or more actors in a scenario you need a protocol, even when dealing with humans and not computers.</p>
<p>In <a href="https://www.thedigitalcatonline.com/blog/2013/02/13/concurrent-programming-4/">the past article</a> we implemented a very simple protocol when instructing processes to access a resource according to the status of a semaphore. The latter is also modified as part of the protocol itself.</p>
<p>As already stated in a past article, there is no difference between interprocess communication on the same machine or in a distributed environment (multiple machines): indeed, every network protocol (TCP/IP, DNS, SMTP, just to cite some of the most famous) is built on a message exchange architecture.</p>
<p>This is a simple example of a protocol based on message exchange: two processes, A and B, are executing concurrently and processing different data. Once they end the processing they have to merge their results. Here, synchronization problems arise: what process actually does the merging? If the process in charge of the merging operation is the process A, for example, the merging protocol can be described by these time charts, one for each process</p>
<h4 id="process-b">PROCESS B<a class="headerlink" href="#process-b" title="Permanent link">¶</a></h4>
<ol>
<li>Work with your data</li>
<li>When you finish send a message to A</li>
<li>When A answers, begin sending it your results</li>
</ol>
<h4 id="process-a">PROCESS A<a class="headerlink" href="#process-a" title="Permanent link">¶</a></h4>
<ol>
<li>Work with your data</li>
<li>Wait for a message from B</li>
<li>Answer the message</li>
<li>Receive data and merge them with yours</li>
</ol>
<p>Choosing the merger process is in this case totally arbitrary. This, however, can be a very important part of a protocol.</p>
<p>This protocol is extensible ina simple way to the case of n processes: every process but A works with its own data and then send a message to A. When A answers, the other process sends its results: the only process modified in this generalization is A since it has to receive messages from multiple processes instead of just one.</p>
<h2 id="system-v-message-queues">System V Message Queues<a class="headerlink" href="#system-v-message-queues" title="Permanent link">¶</a></h2>
<p>Now it is the time to speak about implementing these concepts in a Linux operating system environment. As already said we have a set of primitives that allow us to manage the structures related to message queues, and they are very similar to those dedicated to semaphore management, already described in <a href="https://www.thedigitalcatonline.com/blog/2013/02/13/concurrent-programming-4/">the past article</a>.</p>
<p>The structure used to describe a message is <code>msgbuf</code> and is declared in <code>linux/msg.h</code></p>
<div class="highlight"><pre><span></span><code><span class="cm">/* message buffer for msgsnd and msgrcv calls */</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">msgbuf</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">mtype</span><span class="p">;</span><span class="w"> </span><span class="cm">/* type of message */</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">mtext</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span><span class="w"> </span><span class="cm">/* message text */</span>
<span class="p">};</span>
</code></pre></div>
<p>The field <code>mtype</code> represents the type of the message and is a strictly positive number: the correspondence between numbers and message types has to be set in advance and is part of the protocol definition.</p>
<p>The second field represents the content of the message. With the standard definition, no real message can be held inside it because the space is too little (just one byte). This is just a placeholder since the real structure used to describe messages can be redefined in order to contain complex data. An example of redefinition is the following</p>
<div class="highlight"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">message</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">mtype</span><span class="p">;</span><span class="w"> </span><span class="cm">/* message type */</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">sender</span><span class="p">;</span><span class="w"> </span><span class="cm">/* sender id */</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">receiver</span><span class="p">;</span><span class="w"> </span><span class="cm">/* receiver id */</span><span class="w"> </span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">info</span><span class="w"> </span><span class="n">data</span><span class="p">;</span><span class="w"> </span><span class="cm">/* message content */</span>
<span class="p">};</span>
</code></pre></div>
<p>As you can see this is not a redefinition in the sense of object inheritance, being C a pure procedural language. The redefined structure must obey two simple rules: the first field must be a <code>long mtype</code> and the maximum size dimension shall be 8192 bytes.</p>
<p>This last limit is hard coded in the Linux kernel, i.e. there is a C <code>#define</code> directive in <code>linux/msg.h</code> which states</p>
<div class="highlight"><pre><span></span><code><span class="cp">#define MSGMAX 8192 </span><span class="cm">/* <= INT_MAX */</span><span class="cp"> </span><span class="cm">/* max size of message (bytes) */</span>
</code></pre></div>
<p>In the same file, there are other interesting limits such as <code>MSGMNB</code>, the maximum total size of a queue, which in Linux is set by default to 16384. That means that a queue containing 2 messages is already full.</p>
<p>A short notice about kernel parameters such as <code>MSGMAX</code>, <code>MSGMNB</code> and others: kernel parameters can obviously be changed by modifying the source code and recompiling the kernel, that is generating a custom Linux kernel. Varying some parameters, however, can be dangerous for the portability of your programs. Indeed, if you increase the maximum size of a message to, say, 16384 bytes, in order to host big messages, your application will crash on a kernel without that modification, where the maximum size is still 8192. Kernel parameters can also be changed at runtime through the <code>/proc</code> filesystem and the sysctl interface: these topics are very rich and important and thus deserve a larger space. For the time being, I let the reader research about them.</p>
<h4 id="create-a-queue">Create a queue<a class="headerlink" href="#create-a-queue" title="Permanent link">¶</a></h4>
<p>To create a new queue a process should call the <code>msgget()</code> function</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="n">msgget</span><span class="p">(</span><span class="kt">key_t</span><span class="w"> </span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msgflg</span><span class="p">)</span>
</code></pre></div>
<p>which receives as arguments an IPC key (see <a href="https://www.thedigitalcatonline.com/blog/2013/02/13/concurrent-programming-4/">issue 4</a>) and some flags, which by now can be set to <code>IPC_CREAT | 0660</code> (create the queue if it does not exist
and grant access to the owner and group users). The returned integer is called queue identifier and is unique in the system.</p>
<h4 id="send-messages">Send messages<a class="headerlink" href="#send-messages" title="Permanent link">¶</a></h4>
<p>To send a message to a queue we call the <code>msgsnd()</code> primitive</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="n">msgsnd</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">msqid</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">msgbuf</span><span class="w"> </span><span class="o">*</span><span class="n">msgp</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msgsz</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msgflg</span><span class="p">)</span>
</code></pre></div>
<p>where <code>msqid</code> is the identifier of the queue, <code>msgp</code> is a pointer to the message we have to send, <code>msgz</code> the size of the message in bytes (excluding the length of the <code>mtype</code> field, which is 4 bytes) and <code>msgflg</code> a flag related to the waiting policy.</p>
<p>Here, <code>msgp</code> is a pointer to a <code>struct msgbuf</code>. However, since that structure has been redefined, our actual call will contain a pointer to a variable of the redefined type.</p>
<p>The length of the message in bytes can be easily be found as</p>
<div class="highlight"><pre><span></span><code><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">message</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>
</code></pre></div>
<p>where <code>struct message</code> is our redefinition of <code>struct msgbuf</code>.</p>
<p>Waiting policies are similar to those introduced for semaphores. This time the policy is used when the queue is full. If <code>msgflg</code> is set to <code>IPC_NOWAIT</code>, the sender process will not wait for some available space and will exit with an error code.</p>
<h4 id="read-messages">Read messages<a class="headerlink" href="#read-messages" title="Permanent link">¶</a></h4>
<p>To read messages contained in a queue we use the <code>msgrcv()</code> system call</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="n">msgrcv</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">msqid</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">msgbuf</span><span class="w"> </span><span class="o">*</span><span class="n">msgp</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msgsz</span><span class="p">,</span><span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">mtype</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">msgflg</span><span class="p">)</span>
</code></pre></div>
<p>where the <code>msgp</code> pointer identifies the variable where we will copy the message read from the queue and mtype identifies the subset of messages we want to consider. As before, <code>msgp</code> should be a pointer to a variable of our redefined type and both <code>msgz</code> and <code>msgflg</code> have the same meaning of their counterparts in <code>msgsnd()</code>.</p>
<h4 id="delete-a-queue">Delete a queue<a class="headerlink" href="#delete-a-queue" title="Permanent link">¶</a></h4>
<p>Last, a queue can be removed calling the <code>msgctl()</code> primitive</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">msgctl</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">msqid</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">cmd</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">msqid_ds</span><span class="w"> </span><span class="o">*</span><span class="n">buf</span><span class="p">);</span>
</code></pre></div>
<p>where the command <code>cmd</code> to remove the queue is <code>IPC_RMID</code>. Other two commands, <code>IPC_STAT</code> and <code>IPC_SET</code>, are available through <code>msgctl()</code>, but they are not interesting now.</p>
<h2 id="putting-it-all-together">Putting it all together<a class="headerlink" href="#putting-it-all-together" title="Permanent link">¶</a></h2>
<p>Let's test all these concepts with a simple program which creates a message queue, sends a message to it, reads the message and cancels the queue. After the message has been read, a comparison between the original values and the ones in the message is performed to check that the system is working.</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/msg.h></span>
<span class="cm">/* Redefines the struct msgbuf */</span>
<span class="k">typedef</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">mymsgbuf</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">mtype</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">int_num</span><span class="p">;</span>
<span class="w"> </span><span class="kt">float</span><span class="w"> </span><span class="n">float_num</span><span class="p">;</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">ch</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="n">message_t</span><span class="p">;</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">qid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">key_t</span><span class="w"> </span><span class="n">msgkey</span><span class="p">;</span>
<span class="w"> </span><span class="n">message_t</span><span class="w"> </span><span class="n">sent</span><span class="p">;</span>
<span class="w"> </span><span class="n">message_t</span><span class="w"> </span><span class="n">received</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">length</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/* Initialize the seed of the pseudo-random number generator */</span>
<span class="w"> </span><span class="n">srand</span><span class="w"> </span><span class="p">(</span><span class="n">time</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
<span class="w"> </span><span class="cm">/* Length of the message */</span>
<span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">message_t</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>
<span class="w"> </span><span class="n">msgkey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ftok</span><span class="p">(</span><span class="s">"."</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="cm">/* Create the queue*/</span>
<span class="w"> </span><span class="n">qid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">msgget</span><span class="p">(</span><span class="n">msgkey</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_CREAT</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mo">0660</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"QID = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">qid</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Build a message */</span>
<span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">mtype</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">int_num</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rand</span><span class="p">();</span>
<span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">float_num</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">float</span><span class="p">)(</span><span class="n">rand</span><span class="p">())</span><span class="o">/</span><span class="mi">3</span><span class="p">;</span>
<span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">ch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">abs</span><span class="p">(</span><span class="n">rand</span><span class="p">())</span><span class="o">%</span><span class="mi">26</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">97</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/* Send the message */</span>
<span class="w"> </span><span class="n">msgsnd</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">sent</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"MESSAGE SENT</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Receive the message */</span>
<span class="w"> </span><span class="n">msgrcv</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">received</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">mtype</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"MESSAGE RECEIVED</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Control that received and sent messages are equal */</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Interger number = %d (sent %d) -- "</span><span class="p">,</span><span class="w"> </span><span class="n">received</span><span class="p">.</span><span class="n">int_num</span><span class="p">,</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">int_num</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">received</span><span class="p">.</span><span class="n">int_num</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">int_num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" OK</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"ERROR</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Float number = %f (sent %f) -- "</span><span class="p">,</span><span class="w"> </span><span class="n">received</span><span class="p">.</span><span class="n">float_num</span><span class="p">,</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">float_num</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">received</span><span class="p">.</span><span class="n">float_num</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">float_num</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" OK</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"ERROR</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Char = '%c' (sent '%c') -- "</span><span class="p">,</span><span class="w"> </span><span class="n">received</span><span class="p">.</span><span class="n">ch</span><span class="p">,</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">ch</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">received</span><span class="p">.</span><span class="n">ch</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">sent</span><span class="p">.</span><span class="n">ch</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">" OK</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"ERROR</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Destroy the queue */</span>
<span class="w"> </span><span class="n">msgctl</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_RMID</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p><a href="/code/queues1.c">source code</a></p>
<p>Now we can create two processes and let them communicate through a message queue. Remembering forking concepts explained in the <a href="https://www.thedigitalcatonline.com/blog/2013/02/04/concurrent-programming-2/">issue 2</a> you can recall that the child process, when created, receives a copy of the memory of its parent. This means that creating the queue before the fork operation results in both the parent and the child knowing the right queue identifier and thus capable of access it.</p>
<p>The following code creates a queue, then forks the execution. The child generates a random number, prints it on the standard output and sends them to the parent, which in turn prints it on the screen.</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/msg.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><sys/types.h></span>
<span class="cm">/* Redefines the message structure */</span>
<span class="k">typedef</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">mymsgbuf</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">mtype</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">num</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="n">message_t</span><span class="p">;</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">qid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">key_t</span><span class="w"> </span><span class="n">msgkey</span><span class="p">;</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="n">message_t</span><span class="w"> </span><span class="n">buf</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">length</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="n">message_t</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="k">sizeof</span><span class="p">(</span><span class="kt">long</span><span class="p">);</span>
<span class="w"> </span><span class="n">msgkey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ftok</span><span class="p">(</span><span class="s">"."</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="n">qid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">msgget</span><span class="p">(</span><span class="n">msgkey</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_CREAT</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="mo">0660</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">())){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"CHILD - Queue ID = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">qid</span><span class="p">);</span>
<span class="w"> </span><span class="n">srand</span><span class="w"> </span><span class="p">(</span><span class="n">time</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
<span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">sleep</span><span class="w"> </span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">4</span><span class="p">);</span>
<span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">mtype</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">num</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">100</span><span class="p">;</span>
<span class="w"> </span><span class="n">msgsnd</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"> </span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"CHILD - Sent message number %d: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">num</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"PARENT - Queue ID = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">qid</span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">sleep</span><span class="w"> </span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">4</span><span class="p">);</span>
<span class="w"> </span><span class="n">msgrcv</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"> </span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"PARENT - Received message number %d: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">num</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"PARENT - Waiting for the child to terminate...</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span><span class="w"> </span>
<span class="w"> </span><span class="n">waitpid</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"PARENT - Child ended</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="n">msgctl</span><span class="p">(</span><span class="n">qid</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_RMID</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p><a href="/code/queues2.c">source code</a></p>
<p>Compiling and running the program you can check the correct working of the shared message queue.</p>
<h2 id="conclusions">Conclusions<a class="headerlink" href="#conclusions" title="Permanent link">¶</a></h2>
<p>In this article, we introduced a new IPC structure called message queue and the related concepts of message and protocol. These concepts are very important and are going to be the foundation stone of a project we will realize step by step in the future articles: a simple telephone switch simulator.</p>Concurrent programming - 42013-02-13T10:50:00+02:002013-02-13T10:50:00+02:00Leonardo Giordanitag:www.thedigitalcatonline.com,2013-02-13:/blog/2013/02/13/concurrent-programming-4/<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Permanent link">¶</a></h2>
<p>In the past issue, of this series of articles about concurrent programming we started to concern ourselves with the problems of synchronization between processes. In this installment, we will investigate further the subject introducing some structures and functions collectively known as <em>Unix System V IPC</em>.</p>
<h2 id="ipc-interprocess-communication">IPC: InterProcess Communication<a class="headerlink" href="#ipc-interprocess-communication" title="Permanent link">¶</a></h2>
<p>Communication between processes, either running on the same machine or over a network, is one of the most interesting topics in computer science and, despite its age, new solutions to this problem keep arising. With the widespread availability of Internet access, the subject is now a little shifted towards pure network communication, which represents just a part of the techniques known as <strong>IPC</strong>: InterProcess Communication.</p>
<p>This abbreviation encompasses several different scopes in the field of multiprocessing, the most important ones being <strong>synchronization</strong>, <strong>shared data management</strong> and <strong>messaging</strong>. In this article, we will focus on local IPC, i.e. communication between processes running on the same machine. The underlying concepts and techniques, however, can be easily applied to a network environment too, but they require a layer to manage network communication, which is out of the scope of this series.</p>
<h2 id="more-on-synchronization">More on synchronization<a class="headerlink" href="#more-on-synchronization" title="Permanent link">¶</a></h2>
<p>As briefly shown in the last article synchronization problems are not only among the most complex issues to solve in computer science, but can also lead to severe malfunctions of our software.</p>
<p>Let's reconsider and formalize the example given in the last post. Say we create two different processes working on the same data. If the two processes just read the same data from memory (or disk) no problems can arise: data are static, and accessing does not change them. So the execution of the two processes is called <strong>consistent</strong>, which highlights that repeated executions or executions spanning a long time will always result in the same system behaviour.</p>
<p>If now one of the processes wants to modify data different situations can come up, depending on the actual timing of the operations. Say we have two processes <code>A</code> and <code>B</code> and an element <code>d</code>; process <code>A</code> increases element <code>d</code> by 1 while process <code>B</code> prints the element value on the screen. In a sort of metalanguage, we could express this situation with the following syntax</p>
<div class="highlight"><pre><span></span><code><span class="n">A</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">d</span><span class="o">-></span><span class="n">d</span><span class="o">+</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">d</span><span class="o">-></span><span class="kr">output</span><span class="w"> </span><span class="p">}</span>
</code></pre></div>
<p>where <code>&</code> stands for a concurrent execution; in other words the two processes are not synchronized. One of the possible resulting executions is</p>
<div class="highlight"><pre><span></span><code>(-) d = 5
(A) d = 6
(B) output = 6
</code></pre></div>
<p>while the other is</p>
<div class="highlight"><pre><span></span><code>(-) d = 5
(B) output = 5
(A) d = 6
</code></pre></div>
<p>As you can see, different timings can lead to different results; let's pretend that element <code>d</code> is the amount of money in your bank account, and you will suddenly realize the importance of the matter. Such a reliance of data on timing or system conditions is known as <strong>data inconsistency</strong>.</p>
<p>As we already described, waiting is a trivial form of synchronization that can solve this problem. However it is as simple as inefficient as it blocks the execution of one process while the other is operating and this happens even if the blocked process is no more operating on shared data. The block is indeed based on the simple assumption that one process could lead to data inconsistency.</p>
<p>It is thus necessary to increase the <strong>granularity</strong> of this block. Granularity is the scope of an action: the higher is the granularity the narrowest is the scope. So we have to restrict the scope of the block, which by now covers the whole process.</p>
<h2 id="system-v-keys">System V keys<a class="headerlink" href="#system-v-keys" title="Permanent link">¶</a></h2>
<p>A part of the IPC structures introduced by Unix System V is explicitly dedicated to resource identification, the capability of labelling arbitrary objects and limiting access management to them. This is done through the use of the so-called <em>SysV IPC Keys</em>: a <strong>key</strong>, in this context, is a number used to identify univocally an IPC structure. An IPC key can be generated by <code>ftok()</code></p>
<div class="highlight"><pre><span></span><code><span class="kt">key_t</span><span class="w"> </span><span class="nf">ftok</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">pathname</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">proj_id</span><span class="p">);</span>
</code></pre></div>
<p>where <code>pathname</code> is an existing file name with the full path and <code>proj_id</code> is a number without any restriction. It is guaranteed that the returned key is the same for subsequent calls with the same parameters, but it is not guaranteed that different parameters result in different keys: in other words <em>keys are not guaranteed to be unique</em>. Since IPC functions require a key created with <code>ftok()</code> the best solution is to write a small library that keeps track of assigned keys and avoids duplicates.</p>
<h2 id="semaphores-part-1">Semaphores - part 1<a class="headerlink" href="#semaphores-part-1" title="Permanent link">¶</a></h2>
<p>The idea of traffic light can be profitably borrowed to control access to resources. A <strong>semaphore</strong>, in the IPC world, is a structure capable of containing a positive or null integer and which manages a queue of processes waiting for a particular condition of the semaphore itself.</p>
<p>Despite their simplicity, the power of semaphores is big, thus their correct use is not trivial. We will therefore start writing code without error control, just to focus on the real subject. Please remember that in real world applications, error control code can vary from 40% up to 80% of the total amount, so bear in mind that code without error control is good only for the purpose of understanding concepts.</p>
<p>The first possible use of a semaphore is that of access controller: the value of the semaphore represents the number of processes that can concurrently access the resource. Every time a process access the resource it decrements the value of the semaphore and every time a process releases the resource it increments the value. If the resource is exclusive (that is only one process can access the resource at a time), the maximum value of the semaphore will be 1.</p>
<p>A second use of the semaphore is that of resource counter. The value in this case is the number of resources available to processes, e.g. memory cells, network connections, and so on. As you can easily understand, using a resource is equivalent to locking its access.</p>
<p>Let's consider a practical case where both the uses of semaphores will be useful.</p>
<p>We build a buffer of length L where n processes W1,..., Wn can write to, but from which just one process R can read. Say also that just one process can access the buffer at a given time T. As you can easily understand W processes can write at any time except when the buffer is full while the process R can read at any time except when the buffer is empty.</p>
<p>This buffer could be easily managed in a standard single task environment by declaring 2 flags, the first to signal overflow and the second to signal underflow. We are in a multitasking environment now, so flags declared before the fork operation are not shared between processes (each process has its own copy of the flags, and they are not linked). So we have to use a shared structure, and this is where IPC semaphores take the field.</p>
<p>We can declare three semaphores: the first one will manage access to the buffer while the second and third will keep track of how many elements are in the buffer (later it will become clear why two semaphores are not sufficient).</p>
<p>Given that access to the buffer is exclusive the first semaphore will be a binary one (which value thus will be 0 or 1) while the second and the third will have values linked to the length of the buffer.</p>
<p>In C language the SysV primitive to create a semaphore is</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">semget</span><span class="p">(</span><span class="kt">key_t</span><span class="w"> </span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">nsems</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">semflg</span><span class="p">);</span>
</code></pre></div>
<p>where <code>key</code> is an IPC key created with <code>ftok()</code>, <code>nsems</code> is the number of semaphores we want to create and <code>semflg</code> a set of flags controlling access to the semaphores. Access to IPC structures is ruled by a 12 bit system which is almost identical to the Unix file system access control, but we will not dive into it. As you can also notice <code>semget()</code> manages sets of semaphores, which helps us to keep the code compact.</p>
<p>Let's review the full code to create a semaphore</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/sem.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">key_t</span><span class="w"> </span><span class="n">key</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">semid</span><span class="p">;</span>
<span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ftok</span><span class="p">(</span><span class="s">"/etc/fstab"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="cm">/* create a semaphore set with only 1 semaphore: */</span>
<span class="w"> </span><span class="n">semid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">semget</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mo">0666</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">IPC_CREAT</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Do not compile and execute it by now. As you can see from the <code>#include</code> statements, IPC structures are provided by the operating system itself and not by the standard C library. The key is created by passing to <code>ftok()</code> a file that certainly exists in the system and the PID of the current process. To know more about permission flags check the manual page for <code>semget()</code>.</p>
<p>Let's go on learning to manage and remove semaphores; the primitive used to interact with a semaphore is</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">semnum</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">cmd</span><span class="p">,</span><span class="w"> </span><span class="p">...)</span>
</code></pre></div>
<p>where <code>semid</code> is the semaphore set identifier returned from <code>semget()</code>, <code>semnum</code> the index of the semaphore inside the set and <code>cmd</code> the command you want to run. The value <code>semnum</code> is optional for some commands. Some commands need also an additional argument which type is <code>union semun</code>, defined as</p>
<div class="highlight"><pre><span></span><code><span class="k">union</span><span class="w"> </span><span class="nc">semun</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">val</span><span class="p">;</span><span class="w"> </span><span class="cm">/* value for SETVAL */</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">semid_ds</span><span class="w"> </span><span class="o">*</span><span class="n">buf</span><span class="p">;</span><span class="w"> </span><span class="cm">/* buffer for IPC_STAT, IPC_SET */</span>
<span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="kt">short</span><span class="w"> </span><span class="o">*</span><span class="n">array</span><span class="p">;</span><span class="w"> </span><span class="cm">/* array for GETALL, SETALL */</span>
<span class="w"> </span><span class="cm">/* Linux specific part: */</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">seminfo</span><span class="w"> </span><span class="o">*</span><span class="n">__buf</span><span class="p">;</span><span class="w"> </span><span class="cm">/* buffer for IPC_INFO */</span>
<span class="p">};</span>
</code></pre></div>
<p>To set the value of a semaphore the command is <code>SETVAL</code> and the value is specified through a <code>union semun</code> variable. To set the value of the first semaphore to 1 we modify the program this way</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/sem.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">key_t</span><span class="w"> </span><span class="n">key</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">semid</span><span class="p">;</span>
<span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="nc">semun</span><span class="w"> </span><span class="n">arg</span><span class="p">;</span>
<span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ftok</span><span class="p">(</span><span class="s">"/etc/fstab"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="cm">/* create a semaphore set with only 1 semaphore: */</span>
<span class="w"> </span><span class="n">semid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">semget</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mo">0666</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">IPC_CREAT</span><span class="p">);</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Last we have to cancel the semaphore releasing the structures needed for its management; this is done by the command <code>IPC_RMID</code>, which removes the semaphore and notifies all processes queued to access it that it has been removed. Let this notification aside for the moment and change the code to remove the semaphore</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/sem.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">key_t</span><span class="w"> </span><span class="n">key</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">semid</span><span class="p">;</span>
<span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="nc">semun</span><span class="w"> </span><span class="n">arg</span><span class="p">;</span>
<span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ftok</span><span class="p">(</span><span class="s">"/etc/fstab"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="cm">/* create a semaphore set with only 1 semaphore: */</span>
<span class="w"> </span><span class="n">semid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">semget</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mo">0666</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">IPC_CREAT</span><span class="p">);</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* deallocate semaphore */</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_RMID</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Now you can compile and run it. As you can imagine the program seems to do nothing: it just silently creates a semaphore, sets its value and removes it.</p>
<h2 id="semaphores-part-2">Semaphores - part 2<a class="headerlink" href="#semaphores-part-2" title="Permanent link">¶</a></h2>
<p>Time to use effectively the semaphore: the function that allows to performs operations on a semaphore is </p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">semop</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="o">*</span><span class="n">sops</span><span class="p">,</span><span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="n">nsops</span><span class="p">);</span>
</code></pre></div>
<p>where <code>semid</code> is the set identifier, <code>sops</code> an array of operations and <code>nsops</code> the length of the latter. Each operation is declared through a <code>struct sembuf</code></p>
<div class="highlight"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">ushort</span><span class="w"> </span><span class="n">sem_num</span><span class="p">;</span><span class="w"> </span><span class="cm">/* semaphore index in array */</span>
<span class="w"> </span><span class="kt">short</span><span class="w"> </span><span class="n">sem_op</span><span class="p">;</span><span class="w"> </span><span class="cm">/* semaphore operation */</span>
<span class="w"> </span><span class="kt">short</span><span class="w"> </span><span class="n">sem_flg</span><span class="p">;</span><span class="w"> </span><span class="cm">/* operation flags */</span>
<span class="p">};</span>
</code></pre></div>
<p>For the time being we will always set <code>sem_flg</code> to 0. Operations are always integers and obey the following rules</p>
<ol>
<li>
<p><code>sem_op</code> < 0 This signals that you want to decrease the semaphore value, or in other words lock one of the resources controlled by it. If the value of the semaphore can be decremented without becoming negative it will be and the process running <code>semop()</code> continues. Otherwise, the calling process falls in a sleep status until the semaphore has that number of resources available.</p>
</li>
<li>
<p><code>sem_op</code> = 0 This signals that you are waiting for the semaphore to reach value zero; that is the condition where no resources are available. The calling process falls in a sleep status until that moment.</p>
</li>
<li>
<p><code>sem_op</code> > 0 This signals that you want increase the semaphore value, or in other words release the given number of resources.</p>
</li>
</ol>
<p>Now we can write some code to implement the buffer example previously given. We are going to create 5 processes called W (writers) and a process called R (reader). Each W process tries to lock the resource (the buffer) through a semaphore, and if the buffer is not full, adds an element and releases the lock. The R process tries to lock the buffer, removes an element if available (buffer not empty) and releases the lock.</p>
<p>Since we did not yet talk about shared memory we have to simulate read and write operation, i.e. pretend the operation has been performed. This is necessary since each process has its own memory space and cannot access that of another process. So each process has its own copy of the buffer, and the copies are not linked each other. Later in this series we will talk about techniques that allow sharing memory regions between processes.</p>
<p>As already stated, we need 3 semaphores: the first acts as access controller and its maximum value is 1 while the other two manage overflow and underflow conditions. A single semaphore could not handle both conditions, since <code>semop()</code> acts one-way only.</p>
<p>Let's clarify the latter statement before looking at the code. Say we have a single semaphore to manage over- and underflow conditions, with a value equal to the number of empty spaces in the buffer. Each time a W process fills the buffer it can decrease the semaphore value by one unit until the value reaches 0, which represents the condition of full buffer. This way however the empty buffer condition cannot be managed since the R process can increment the value of the semaphore without any limit. Semaphores, indeed, just control the lower boundary and not the upper one.</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdlib.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><errno.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/ipc.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><linux/sem.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="w"> </span><span class="cm">/* IPC structures */</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">key_t</span><span class="w"> </span><span class="n">key</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">semid</span><span class="p">;</span>
<span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="nc">semun</span><span class="w"> </span><span class="n">arg</span><span class="p">;</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">lock_res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">};</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">rel_res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">};</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">push</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">};</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">pop</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">};</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">len</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">num_proc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">num_write_actions</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">20</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">num_read_actions</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="p">(</span><span class="n">argc</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">2</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"Usage: %s <size></span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">strtol</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">);</span>
<span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ftok</span><span class="p">(</span><span class="s">"/etc/fstab"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="cm">/* Create a set with 3 semaphores */</span>
<span class="w"> </span><span class="n">semid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">semget</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mo">0666</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">IPC_CREAT</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize semaphore #0 to 1 - Resource controller */</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize semaphore #1 to buf_length - Overflow controller */</span>
<span class="w"> </span><span class="cm">/* Sem value represents free space in buffer */</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">len</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize semaphore #2 to buf_length - Underflow controller */</span>
<span class="w"> </span><span class="cm">/* Sem value represents the number of elements in buffer */</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Fork */</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num_proc</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">pid</span><span class="p">){</span>
<span class="w"> </span><span class="cm">/* Child process code*/</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num_write_actions</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">sleep</span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">6</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Try to lock the buffer - sem #0 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">lock_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">perror</span><span class="p">(</span><span class="s">"semop:lock_res (write)"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Lock a free cell - sem #1 */</span>
<span class="w"> </span><span class="cm">/* Push an element - sem #2 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">push</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"---> Child process %d: Element written</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"---> Child process %d: BUFFER FULL</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Release the buffer */</span>
<span class="w"> </span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">rel_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">num_read_actions</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">sleep</span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">3</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Try to lock the buffer - sem #0 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">lock_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">perror</span><span class="p">(</span><span class="s">"semop:lock_res (read)"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Unlock a free cell - sem #1 */</span>
<span class="w"> </span><span class="cm">/* Pop an element - sem #2 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">pop</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"<--- Parent process %d: Element read</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"<--- Parent process %d: BUFFER EMPTY</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Release the buffer */</span>
<span class="w"> </span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">rel_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Destroy semaphores */</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_RMID</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Let us review the most interesting parts of the code.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">lock_res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">};</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">rel_res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">};</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">push</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">};</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">sembuf</span><span class="w"> </span><span class="n">pop</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="n">IPC_NOWAIT</span><span class="p">};</span>
</code></pre></div>
<p>These four lines of code declare the actions we will use later on the semaphore set. The first two are single actions while the second two are double ones. The first action, <code>lock_res</code>, is used to lock the buffer: as you can see the semaphore number 0 is decremented by 1 and in case of busy resource the strategy is waiting (the last 0 in the action). The second action releases the buffer and is the mirror image of the first one.</p>
<p>The third and fourth actions are specular too; each of them is an array of two actions, the first on the semaphore number 1 and the second on the semaphore number 2; while the first one is incremented the second is decremented and vice versa. The policy is changed from the first two actions: <code>IPC_NOWAIT</code> forces the process to continue execution, in contrast with the previous case, when the process was put on hold.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Initialize semaphore #0 to 1 - Resource controller */</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize semaphore #1 to buf_length - Overflow controller */</span>
<span class="w"> </span><span class="cm">/* Sem value represents free space in buffer */</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">len</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Initialize semaphore #2 to buf_length - Underflow controller */</span>
<span class="w"> </span><span class="cm">/* Sem value represents the number of elements in buffer */</span>
<span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="n">semctl</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">SETVAL</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">);</span>
</code></pre></div>
<p>Next, semaphores must be initialized: as already stated the first one is set to 1, being a binary access controller, the second to the length of the buffer as overflow controller and the third to 0 as underflow controller.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Try to lock the buffer - sem #0 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">lock_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">perror</span><span class="p">(</span><span class="s">"semop:lock_res (write)"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Lock a free cell - sem #1 */</span>
<span class="w"> </span><span class="cm">/* Push an element - sem #2 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">push</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"---> Child process %d: Element written</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"---> Child process %d: BUFFER FULL</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Release the buffer */</span>
<span class="w"> </span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">rel_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
</code></pre></div>
<p>Child process code (a writer) tries first of all to lock the buffer using <code>lock_res</code>; once the control over the resource has been acquired it performs the <code>push</code> action and writes on the standard output a meaningful message. Otherwise, it signals that the buffer is full. The last action it performs is to release the resource through <code>rel_res</code>.</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="cm">/* Try to lock the buffer - sem #0 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">lock_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">perror</span><span class="p">(</span><span class="s">"semop:lock_res (read)"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Unlock a free cell - sem #1 */</span>
<span class="w"> </span><span class="cm">/* Pop an element - sem #2 */</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">pop</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">-1</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"<--- Parent process %d: Element read</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"<--- Parent process %d: BUFFER EMPTY</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cm">/* Release the buffer */</span>
<span class="w"> </span><span class="n">semop</span><span class="p">(</span><span class="n">semid</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">rel_res</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
</code></pre></div>
<p>As you can immediately notice parent process (reader) mimics the behaviour of the child. It lock the buffer, reads some data with the <code>pop</code> action and release the resource.</p>
<p>Try to change the parameters such as the buffer length (on the command line) or the number of cycles performed by parent and child processes to see what happens. </p>
<h2 id="conclusions">Conclusions<a class="headerlink" href="#conclusions" title="Permanent link">¶</a></h2>
<p>In the next article, we will introduce and deal with atomicity, which is a very important concept in concurrent programming and database systems. We will also introduce a new IPC structure, which has a broad use in distributed systems: message queues.</p>Concurrent programming - 32013-02-06T12:25:00+02:002013-02-06T12:25:00+02:00Leonardo Giordanitag:www.thedigitalcatonline.com,2013-02-06:/blog/2013/02/06/concurrent-programming-3/<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Permanent link">¶</a></h2>
<p>In the first article, we stepped into the world of multitasking, going over its meaning and the reasons behind its existence. In the second article, we met the fundamental fork operation and wrote our first multitasking code. In this article, we will go ahead and introduce ourselves in the topic of synchronization: the problem we face now indeed is to release the full power of multitasking, that is to share the work between processes.</p>
<p>In the first part of the article, I want to make a step back to the basics of multitasking to clarify the single/multiple CPU theme. Then we will start talking about shared data between processes, first looking at the problems arising and then writing some code.</p>
<h2 id="simultaneous-execution">Simultaneous execution<a class="headerlink" href="#simultaneous-execution" title="Permanent link">¶</a></h2>
<p>We should never forget that the main reason behind multitasking on a single CPU is to give the impression of simultaneous execution, not to speed up execution.</p>
<p>Let's clarify this statement. A single CPU can execute only one operation at a time, so running two processes means to run the first one for a little time, then switch to execute the second one and so on. As already stated, this interlacing operation is what we call multitasking, and it is clear that such a technique slows down the interlaced processes: since each of the two processes runs for half the time (the other half being spent by the other process), the result is a process that runs half the speed.</p>
<p>If you add to this that a switch operation does not come for free, because some time is spent by the operating system replacing the current process with the other one, you suddenly realize that multitasking is a double-edged sword: on one side, it gives us the chance to run multiple programs at the same time, on the other side, it slows down the execution of the whole system.</p>
<p>This issue can only be solved by using multiple CPUs or multiple cores (the two are not exactly the same), either on the same physical machine or on different ones.</p>
<p>So, if you are writing an algorithm to process an image in foreground, that is for a user that is waiting in front of the screen, you could split it profitably in many parts, each of which will process a tile of the whole image. This way the user could have a glance at the whole result while it is being computed. The same technique counts if, for example, you are computing statistics about a set of data: since some computations last longer than others you could split them among different processes so that the user can immediately obtain the faster ones.</p>
<p>If, on the contrary, you are writing code that runs in background without the user being there waiting for the results, you should never split it in different processes if you are working on a single CPU. That way you are just tangling up the code and wasting the CPU cycles to switch between processes without any real benefit.</p>
<h2 id="working-together">Working together<a class="headerlink" href="#working-together" title="Permanent link">¶</a></h2>
<p>Being our processes running at the very same time on different CPUs or just interlacing on a single one, a completely new set of problems arises if the two have to work on the same data.</p>
<p>Just imagine this very common scenario: two processes share a common storage area in memory where partial results of their computations can be temporarily saved. So each process writes data on the storage area, then runs computing other data and last loads previously saved data to finalize its work. What happens if, in the meantime, the second process wrote some of its temporary data on the same area? The first process has no way to figure out that the loaded data is not correct, and this can lead to catastrophic results. The worst thing about such a bug, as quite always in the multitasking environment, is that such a problem can arise or not, depending on input, times, status of the running machine and so on. This class of problems is usually known as race condition and is one of the most subtle and dangerous bug forms since it is difficult to spot, to reproduce and sometimes to test automatically.</p>
<p>A little search about the Therac-25 accident (1987) can clearly exemplify the extent of the problem that such a bug can cause.</p>
<h2 id="basic-synchronization">Basic synchronization<a class="headerlink" href="#basic-synchronization" title="Permanent link">¶</a></h2>
<p>The simplest form of synchronization is waiting; that is, a process sits down until another process finishes running, then runs its own code. The system call that allows a process to wait for another to end is</p>
<div class="highlight"><pre><span></span><code><span class="kt">pid_t</span><span class="w"> </span><span class="n">waitpid</span><span class="w"> </span><span class="p">(</span><span class="kt">pid_t</span><span class="w"> </span><span class="n">PID</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="o">*</span><span class="n">STATUS_PTR</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">OPTIONS</span><span class="p">)</span>
</code></pre></div>
<p>where <code>PID</code> is the PID of the process we are waiting for, <code>STATUS_PTR</code> a pointer to an integer which will contain the status of the child process (<code>NULL</code> if the information is not needed) and <code>OPTIONS</code> a set of options we have not to care about for now.</p>
<p>This is an example of a program in which the parent creates a child process and waits until it ends up</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><unistd.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><sys/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">){</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">8</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"-child-</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"+parent+ Waiting for the child to terminate...</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span><span class="w"> </span>
<span class="w"> </span><span class="n">waitpid</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"+parent+ ...ended</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Let's save the code as <code>fork_demo3.c</code>, compile it and execute. The output I get from this program is the following</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>./fork_demo3
+parent+<span class="w"> </span>Waiting<span class="w"> </span><span class="k">for</span><span class="w"> </span>the<span class="w"> </span>child<span class="w"> </span>to<span class="w"> </span>terminate...
-child-
-child-
-child-
-child-
-child-
-child-
-child-
-child-
+parent+<span class="w"> </span>...ended
</code></pre></div>
<p>Looking at it you can realize a very important thing about <code>waitpid()</code>: it is a so-called <strong>blocking system call</strong>; that is something that keeps running until a certain condition is met. In this case, <code>waitpid()</code> keeps doing nothing until the child ends. So waiting is a blocking synchronization technique.</p>
<h2 id="relationships">Relationships<a class="headerlink" href="#relationships" title="Permanent link">¶</a></h2>
<p>Speaking about parents and children there are two more type of processes we can find in the system: <strong>orphans</strong> and <strong>zombies</strong>. A process is orphaned when the parent terminates while it is still running, according to the real meaning of the word orphan; in such a case the orphan process is adopted by <code>init</code>, the first process in the system, thus becoming one of its children.</p>
<p>Zombie processes, on the contrary, are already terminated, but they have not been waited by the parent. In other words, they are not running, but the operating system still holds their data to allow the parent to collect the exit status.</p>
<p>A simple demonstration of the zombie status can be done with the following code</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><unistd.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><sys/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"-child-</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">14</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"+parent+</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p>Save it as <code>zombie_demo.c</code>, compile and run. Just after the child has printed its string open another terminal and run <code>ps xa</code>. The last lines of your output will be something like</p>
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="m">4399</span><span class="w"> </span>pts/1<span class="w"> </span>S+<span class="w"> </span><span class="m">0</span>:00<span class="w"> </span>./zombie_demo
<span class="w"> </span><span class="m">4400</span><span class="w"> </span>pts/1<span class="w"> </span>Z+<span class="w"> </span><span class="m">0</span>:00<span class="w"> </span><span class="o">[</span>zombie_demo<span class="o">]</span><span class="w"> </span><defunct>
</code></pre></div>
<p>As you can see the first process listed is the parent, while the second, the child, is marked as defunct and its status is zombie (Z).</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">¶</a></h2>
<p>Multitasking is a fundamental technique, which must be however used with care; as any other technology, it cannot solve every problem, neither its introduction comes completely for free.</p>
<p>Synchronization between processes is something which must be carefully considered and implemented since errors in this field can lead to devious bugs.</p>
<p>Last you met two new types of processes, orphans and zombies, and learned why they can be found in the system.</p>
<p>In the next article, we will study some classical synchronization problems and introduce the basic InterProcess Communication (IPC) structures and techniques Unix systems make available to programmers.</p>Concurrent programming - 22013-02-04T10:35:00+02:002013-02-04T10:35:00+02:00Leonardo Giordanitag:www.thedigitalcatonline.com,2013-02-04:/blog/2013/02/04/concurrent-programming-2/<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Permanent link">¶</a></h2>
<p>In the past article I introduced the concept of process and how important it is for our operating system: in this new issue of the Concurrent Programming series we will go on and begin to write multitasking code; we will start from one of the basic concepts of the whole picture, the forking operation. Afterwards, we will start to introduce the problem of process synchronization and communication, which we will deeply face in a later instalment.</p>
<h2 id="the-c-standard-library">The C standard library<a class="headerlink" href="#the-c-standard-library" title="Permanent link">¶</a></h2>
<p>The C standard library, nicknamed libc, is a collection of functions for the C language which has been standardized by ANSI and later by ISO. An implementation of it can be found in any major compiler or operating system, especially Unix-like ones.</p>
<p>In the GNU ecosystem, which Linux distributions are grounded on, the library is implemented by glibc (GNU libc). The library reached version 2.17 in December 2012 and is free software released under LGPL, a less restrictive version of the GPL which most notably allows the use of the library by non-GPL software, even proprietary one.</p>
<p>You can find and navigate glibc sources <a href="https://sourceware.org/git/?p=glibc.git;a=summary">here</a></p>
<h2 id="c-language-and-pids">C language and PIDs<a class="headerlink" href="#c-language-and-pids" title="Permanent link">¶</a></h2>
<p>Processes, like every resource in a computer, are managed by the kernel. This is a part of the operating system that runs continuously in background, exposing functions to other programs that allow them to obtain, manage and release resources such as memory, disk space and CPU time. One of the things the kernel exposes to the hosted programs is the process management, which stands for structures that represent the current status of processes in the system. Using the libc the programmer can easily access those structures in a read-only way.</p>
<p>Let us start with the simple concept of PID, the Process IDentifier we described in the past issue of this series. In the libc, the <code>pid_t</code> type is defined as an integer capable of containing a pid. To show this we will now take a little tour of the glibc source code: we will cover the whole path this time only, just to highlight both the chances given us by the source code and the complexity of a project like glibc.</p>
<p>We can find the initial definition of <code>pid_t</code> <a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=posix/sys/types.h;h=33c2176d0f0b38f1a81bf8c76d38f08d2ab38675;hb=HEAD">here</a></p>
<div class="highlight"><pre><span></span><code><span class="cp">#ifndef __pid_t_defined</span>
<span class="k">typedef</span><span class="w"> </span><span class="n">__pid_t</span><span class="w"> </span><span class="kt">pid_t</span><span class="p">;</span>
<span class="cp">#define __pid_t_defined</span>
<span class="cp">#endif</span>
</code></pre></div>
<p>As you can see the definition of the type is protected by multiple header inclusion, as usual in the C world. The underlying <code>__pid_t</code> type is then defined <a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=bits/types.h;h=dc7b784f965749c44257bf030508d6642c07dec7;hb=HEAD">here</a></p>
<div class="highlight"><pre><span></span><code><span class="cp">#define __STD_TYPE typedef</span>
<span class="cp">#define __S32_TYPE int</span>
<span class="n">__STD_TYPE</span><span class="w"> </span><span class="n">__PID_T_TYPE</span><span class="w"> </span><span class="n">__pid_t</span><span class="p">;</span><span class="w"> </span><span class="cm">/* Type of process identifications. */</span>
</code></pre></div>
<p>Notice that even the typedef keyword is defined by a macro (remember that the C preprocessor is a little more than a text macro replacement tool); this definition in particular avoids compiler warning when using the <code>long long</code> type which is not supported by all versions of the C standard. <code>S32</code> stands for “signed 32 bits” as you can read in the code documentation.</p>
<p>The last macro <code>__PID_T_TYPE</code> can be found <a href="https://sourceware.org/git/?p=glibc.git;a=blob;f=bits/typesizes.h;h=8268b90276700a382db37331be1d8ef5a516403d;hb=HEAD">here</a></p>
<div class="highlight"><pre><span></span><code><span class="cp">#define __PID_T_TYPE __S32_TYPE</span>
</code></pre></div>
<p>The heavy use of defines and compiler features made by glibc code allows the library to be compiled on very different architectures.</p>
<h2 id="telling-the-pid">Telling the PID<a class="headerlink" href="#telling-the-pid" title="Permanent link">¶</a></h2>
<p>Let us now discover the function which give us the knowledge of the pid of the process containing our program</p>
<div class="highlight"><pre><span></span><code><span class="kt">pid_t</span><span class="w"> </span><span class="nf">getpid</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</code></pre></div>
<p>which is defined with <code>pid_t</code> in <code>unistd.h</code> and <code>sys/types.h</code>. The libc simply uses the system call called <code>getpid</code> and its real implementation can be found in the <a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=kernel/timer.c;h=367d008584823a6fe01ed013cda8c3693fcfd761;hb=HEAD">kernel source</a></p>
<div class="highlight"><pre><span></span><code><span class="n">SYSCALL_DEFINE0</span><span class="p">(</span><span class="n">getpid</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">task_tgid_vnr</span><span class="p">(</span><span class="n">current</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>We can now write a program whose aim is to print on the standard output its own pid. With an editor of your choice write the following code</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><unistd.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><sys/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">getpid</span><span class="p">();</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"The pid assigned to the process is %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">pid</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p><a href="/code/print_pid.c">source code</a></p>
<p>Save the program as print_pid.c and compile it</p>
<div class="highlight"><pre><span></span><code>gcc<span class="w"> </span>-o<span class="w"> </span>print_pid<span class="w"> </span>print_pid.c
</code></pre></div>
<p>If this operation returns errors make sure you installed gcc and libc headers; refer to your distribution knowledge base to solve this task.</p>
<p>The compiler will build an executable named <code>print_pid</code> (since the current directory is probably not in the system path you can run it with <code>./print_pid</code>). Executing the program we will have no great surprises: it prints out a positive number and if you executes it more than once this number will likely increase progressively; this is not mandatory, however, because another process could be created between two executions of <code>print_pid</code>. Try for example to execute <code>print_pid</code>, then <code>ps</code> and then <code>print_pid</code> again.</p>
<h2 id="forking">Forking<a class="headerlink" href="#forking" title="Permanent link">¶</a></h2>
<p>Now it is time to meet one of the most important concepts in the field of operating systems, that is the concept of forking.</p>
<p>Forking in general means that one thing splits in two and each part acts like an independent being. At the very moment of the split the two entities are the same, exactly the same, except for the fact that they live in two different spaces. This computer science concept can be retrieved in nature when a simple organism generates a clone of itself. After the cloning the two organisms are the exact copy, but they can be told apart since they are two things (the right one and the left one for example). Back to the operating system world we find the very same problem when a process forks; after the fork operation we have two processes with two different PIDs, but the two contain the same program at the same execution point.</p>
<p>So, when a program (running as process A) creates another process (B) the two are identical, that is they have the same code, the memory full of the same data (not the same memory, since the memory regions are different) and the same processor status. From this point on the two can continue in two different ways, just like our cloning organisms, for example depending on the user's input or some other data. The process A is called the <strong>parent</strong> process while B is the <strong>child</strong> process; now you can begin to understand better the name <em>parent of all the processes</em> given to init. The function which creates a new process is</p>
<div class="highlight"><pre><span></span><code><span class="kt">pid_t</span><span class="w"> </span><span class="n">fork</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</code></pre></div>
<p>The number returned is a pid, but it deserves a particular attention. We said that the first process duplicates itself splitting in a parent and a child, which will then execute interlacing themselves with the other running processes, doing different works; but immediately after the duplication which process will be executed, the parent or the child?</p>
<p>Well, the answer is as simple as unuseful: one of the two. The decision about which process has to be executed is taken by a part of the operating system called scheduler, and it pays no attention if a process is the parent or the child, following an algorithm based on other parameters.</p>
<p>If we are writing processes that implement a service (such as serving network connections) we need nothing more: the two processes are the same and they behave the same way, so by cloning the process we just incremented the number of service providers. This is usually done by Web servers such as Apache, which spawns a copy of itself to serve incoming connections.</p>
<h2 id="parent-and-child">Parent and child<a class="headerlink" href="#parent-and-child" title="Permanent link">¶</a></h2>
<p>Sometimes, anyway, it is fundamental to know what process is in execution: after the fork both processes are at the same execution point (that is just after the <code>fork()</code> call) so how can them tell if they are the parent or the child one?</p>
<p>In order to clarify this question let us look at the following algorithm:</p>
<ol>
<li>fork</li>
<li>if you are the child then execute ...</li>
<li>if you are the parent then execute ...</li>
</ol>
<p>which could represent in a sort of metalanguage the code of our program. The question can be expressed this way: “You have been cloned. Who are you, the original one or the clone?”</p>
<p>The answer is once again very simple: the <code>fork()</code> function returns 0 to the child process and the child's PID to the parent. So it is enough to test if the returned PID is zero and we will know what process is executing the current code. Putting it in C language we obtain</p>
<div class="highlight"><pre><span></span><code><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">code</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">child</span><span class="w"> </span><span class="n">process</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">code</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">parent</span><span class="w"> </span><span class="n">process</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<p>It's time to write the first real example of multitasking code: you can save it in a <code>fork_demo.c</code> file and compile it as we did before.</p>
<p>The program will fork itself, and both the parent and the child will write something on the screen; the final output will be the interlaced output of the two (if all goes right).</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span><span class="w"> </span><span class="cpf"><unistd.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><sys/types.h></span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf"><stdio.h></span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">){</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">8</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"-child-</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">8</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"+parent+</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>
<p><a href="/code/fork_demo.c">source code</a></p>
<p>Lines number 01-03 contain the includes for the necessary libraries (standard I/O, multitasking).</p>
<p>The main function returns an integer (as always in GNU), which normally is zero if the program reached the end without errors or an error code if something goes wrong; let us state this time all will run without errors (we can later add some error control code, when the basic concepts will be clear).</p>
<p>Then we define the data type containing a pid (line 06) and an integer working as counter for loops (line 07). At line 09 we call <code>fork()</code> and it will return zero to the program executed in the child process and the pid of the child process to the parent; the test is at line 11. Now the code at lines 12-15 will be executed in the child process while the rest (lines 18-22) will be executed in the parent. Note that we omitted the <code>else</code> statement since the child code ends with a <code>return</code>; thus there is no way for the child to execute the code of the parent.</p>
<p>The two parts simply write 8 times on the standard output the string <code>-child-</code> or <code>+parent+</code>, depending on which process executes it, and then end returning 0. Executing the program will perhaps let you unsatisfied: the result is likely not to be a real mix between the two strings, and this due to the speed of execution of such a short loop. The scheduler runs the parent or the child for a quantum of time which is enough for the process to end the loop; thus probably your output will be a list of <code>+parent+</code> strings followed by a list of <code>-child-</code> ones, or the contrary.</p>
<p>To highlight the interlacing effect we can insert a random delay before each <code>printf()</code> call: we can do this with <code>sleep()</code> and <code>rand()</code> functions</p>
<div class="highlight"><pre><span></span><code><span class="n">sleep</span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">4</span><span class="p">)</span>
</code></pre></div>
<p>this make the program sleep for a random number of seconds between 0 and 3. Now the child code looks like</p>
<div class="highlight"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">8</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="w"> </span><span class="n">sleep</span><span class="w"> </span><span class="p">(</span><span class="n">rand</span><span class="p">()</span><span class="o">%</span><span class="mi">4</span><span class="p">);</span>
<span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">"-child-</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>and the same for the parent's code. Save it as <code>fork_demo2.c</code>, compile and execute. It is slower now, and we notice a difference in the output string order, and more differences between an execution and the previous one. For example my output is</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>./fork_demo2
-child-
+parent+
+parent+
-child-
-child-
+parent+
+parent+
-child-
-child-
+parent+
+parent+
-child-
-child-
-child-
+parent+
+parent+
</code></pre></div>
<p>As always when dealing with multitasking code, your output is probably different from mine and will also be different between consecutive executions. Try also to change the parameters of the program, such as the sleep time or the number of loops.</p>
<h2 id="why-forking">Why forking<a class="headerlink" href="#why-forking" title="Permanent link">¶</a></h2>
<p>Thinking carefully about the parent and child example a question arises: why should I write code that forks, with all the intricacies it entails, when I could simply write two different programs and run them, letting the operating system to deal with their simultaneous execution?</p>
<p>This is a very interesting question, and the answer is very simple, though the underlying concept is rather complex. When you run a program the shell or the GUI follows a pattern called <strong>fork-and-exec</strong>: first it forks, then the child process executes the desired program. The reason of this behaviour is that the <code>exec</code> family of system calls replace the running program with a new program but do not change the PID. So the tasks are divided between system calls: <code>fork</code> creates a new process while <code>exec</code> loads the given program into the newly created process.</p>
<h2 id="dos-and-windows">DOS and Windows<a class="headerlink" href="#dos-and-windows" title="Permanent link">¶</a></h2>
<p>Operating systems of the DOS and Windows family do not provide a <code>fork</code> mechanism but a <code>spawn</code> family of system calls, which directly implement the fork-and-exec technique; this is a good example of the different implementation OSs make of common computer science concepts: while both implement multitasking and let many processes run concurrently, the way this target is reached can vary significantly.</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">¶</a></h2>
<p>Starting from the knowledge of processes you stepped into the fundamental Unix concept of forking, learning to tell apart parent and child processes and running your first multitasking-based program. You also started to understand how complex can some operating system issues be, and that real world OSs can provide very different solutions to them.</p>
<p>In the next article we will start to look after processes synchronization and data sharing between processes.</p>Concurrent programming - 12013-01-31T16:47:00+02:002013-01-31T16:47:00+02:00Leonardo Giordanitag:www.thedigitalcatonline.com,2013-01-31:/blog/2013/01/31/concurrent-programming-1/<h2 id="abstract">Abstract<a class="headerlink" href="#abstract" title="Permanent link">¶</a></h2>
<p><em>I already published this series of articles on concurrent programming on LinuxFocus from November 2002 and now I carefully reviewed them. Feel free to notify me any error you will find.</em></p>
<p>The purpose of this article (and the following ones in this series) is to introduce the reader to the concept of multitasking and to its implementation in the Linux operating system. Thus, we will start from the theoretical concepts at the base of multitasking and from those we will move towards advanced concept like multithreading and interprocess communication. We will practice some code and some Linux internals along this path, and I will try constantly to exemplify how real world operating system realize the concepts I am introducing.</p>
<h2 id="prerequisites">Prerequisites<a class="headerlink" href="#prerequisites" title="Permanent link">¶</a></h2>
<p>Prerequisites for the understanding of the article are:</p>
<ul>
<li>Minimal knowledge of the text shell use (bash)</li>
<li>Basic knowledge of C language (syntax, loops, libraries)</li>
</ul>
<p>Even if I wrote the articles using a Linux machine, any Unix-like operating system, most notably Mac OS X, shares the concepts I will present. However, pay attention to the fact that while any Unix-like system behaves the same way (more or less), its internal structures and code can be significantly different. On the other hand OSs of the DOS and Windows family share some concepts with Unix-like ones but behave very differently.</p>
<p>One of the biggest positive aspects of dealing with an open source operating system like Linux is the possibility to look at the code: this allow us to uncover the internal working of a system that runs on the most important data center of the planet.</p>
<h2 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Permanent link">¶</a></h2>
<p>One of the most decisive turning points in the history of operating systems was the concept of multiprogramming, a technique for interlacing the execution of several programs in order to gain a more constant use of the system's resources. Let us think about a simple workstation, where a user can execute at the same time a word processor, an audio player, a print queue, a web browser and more, and we can understand the importance of this technique. As we will discover this little list is only a minimal part of the set of programs that are currently executing on the machine, even though they are the most visible ones.</p>
<h2 id="the-concept-of-process">The concept of process<a class="headerlink" href="#the-concept-of-process" title="Permanent link">¶</a></h2>
<p>In order to interlace programs, a remarkable change of the operating system is necessary; in order to avoid conflicts between running programs an unavoidable choice is to encapsulate each of them with all the information needed for their execution.</p>
<p>Before we explore what happens in the operating system let us give some technical nomenclature: given a running program, at a given time the <strong>code</strong>
is the set of instructions which it is made of while the <strong>memory space</strong> is the part of machine memory taken up by its code and data. The <strong>processor status</strong> is the value of the microprocessor's parameters, such as the registers, the flags or the Program Counter (the address of the next instruction to be executed).</p>
<p>Given a tern of objects made of code, memory space and processor status we can define a <strong>running program</strong>. If at a given time during the operation of the machine we save this information and replace them with the same set taken from another running program, the flow of the latter will continue from the point at which it was stopped: doing this once with the first program and once with the second realizes the interlacing previously described. We name <strong>process</strong> (or <strong>task</strong>) the tern of objects we used, a concept which has to do with that of program, yet being an extension of it.</p>
<p>Let us explain what was happening to the workstation we spoke about in the introduction: only one task is in execution at each moment (there is only one microprocessor with just one core and it cannot do two things at the same time), and the machine executes part of its code. After a certain amount of time named <strong>quantum</strong> the running process is suspended, its tern of objects is saved and replaced by those of another waiting process, whose code will be executed for a quantum of time, and so on. This mechanism is what we call multitasking (or multiprocessing).</p>
<p>As stated before the introduction of multitasking causes a set of problems, most of which are not trivial, such as the management of the waiting processes queues (called <strong>scheduling</strong>); nevertheless those problems have to do with the architecture of each operating system, and are not the topic of the current article.</p>
<h2 id="processes-in-linux-and-unix">Processes in Linux and Unix<a class="headerlink" href="#processes-in-linux-and-unix" title="Permanent link">¶</a></h2>
<p>Let us discover something about the processes running on the machine. The command which gives us such information is ps which is an acronym for Process Status. Opening a normal text shell and typing the ps command we will obtain an output such as</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ps
<span class="w"> </span>PID<span class="w"> </span>TTY<span class="w"> </span>TIME<span class="w"> </span>CMD
<span class="m">2241</span><span class="w"> </span>ttyp4<span class="w"> </span><span class="m">00</span>:00:00<span class="w"> </span>bash
<span class="m">2346</span><span class="w"> </span>ttyp4<span class="w"> </span><span class="m">00</span>:00:00<span class="w"> </span>ps
</code></pre></div>
<p>I state in advance that this list is not complete, but let us concentrate ourself on this for the moment: ps has given us the list of each process running on the current terminal. We recognize in the last column the name the process is started with (such as "firefox" for Mozilla Firefox and "gcc" for the GNU Compiler Collection). Obviously "ps" appears in the list because it was running when it compiled the list of running processes. The other listed process is the Bourne Again Shell, the shell running on the terminal.</p>
<p>Let us leave out for the moment the information about TIME and TTY and let us look at PID, the Process IDentifier. The pid is a strictly positive number (not zero) the operating system assigns univocally to each running process; once the process terminated the pid can be reused, but the OS guarantees that the pid of a process remains the same during its execution and that it is unique. All this implies that the output each of you will
obtain from the ps command will probably be different from that in the above example.</p>
<p>Just to check the latter sentence, let us open another shell without closing the first one and type the ps command: this time the output gives the same list of processes but with
different pid numbers, showing that they are two different processes even if the program they executes is the same.</p>
<p>We can also obtain a list of all processes running on a Linux box: the ps command man page says that the switch -e means "select all processes". Let us type "ps -e" in a terminal and ps will print out a long list formatted as previously seen. In order to analyze in a comfortable way this list we can redirect the output of ps in the ps.log file:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ps<span class="w"> </span>-e<span class="w"> </span>><span class="w"> </span>ps.log
</code></pre></div>
<p>Now we can read this file editing it with our preferred editor (or simply with the less command); as stated at the beginning of this article the number of running processes is higher than we would expect; on the machine I'm currently writing on they are around 170.</p>
<p>That list contains not only processes started by us (through the command line or our graphical environment of choice), but also a set of processes, some of which with strange names: the number and the identity of the listed processes depends on the configuration of your system, but there are some common things.</p>
<p>First of all, no matter how you configured the system, the process with pid equal to 1 is always "init", the so called father of all the processes. Wait, wait, I hear you screaming “What about fatherhood among processes?”. This concept will become clear later, when we will talk about forking and the way the system spawns new processes. By now just note that the fact that init owns the pid number 1 tells us that it is the first process executed by a Unix-like operating system.</p>
<p>Another thing we can easily note is the presence of many processes, whose name ends with a "d": they are the so called "daemons" and are some of the most important processes of the system. Since this is just an introductory article we will not diffusely talk about deamons now: just say they are programs that sit waiting for specific events and when one of those events occur the daemons waiting for it perform some actions. A typical example of a daemon is sshd, which establishes or refuses SSH connections upon external requests.</p>
<p>The existence of daemons makes even clearer why multitasking is vital for a modern operating system: since there are many peripherals and connections to manage, through multitasking we can run many small specialized programs (call them deamons, services, components), each of which knows only how to manage that specific object. This is a typical concept of the Unix world, summarized by the sentence “do one thing and do it well”.</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Permanent link">¶</a></h2>
<p>This article introduced you to the meaning of multitasking and to the reason of its implementation. You started to familiarize with the concept of process and the related jargon and discovered a little about the internal working of the operating system by looking at all the processes running in it. </p>
<p>Next article will dig into the fundamental concept of process forking, both from the theoretical point of view and with real C examples. We will also later talk about interprocess communication, multithreading, multiple CPUs and cores and scheduling.</p>
<p>Feel free to ask questions or point errors through comments or social networks.</p>