{"id":10583,"date":"2025-10-22T20:31:37","date_gmt":"2025-10-22T20:31:37","guid":{"rendered":"https:\/\/pokecon.jp\/job\/?p=10583"},"modified":"2025-10-22T20:31:37","modified_gmt":"2025-10-22T20:31:37","slug":"you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals","status":"publish","type":"post","link":"https:\/\/pokecon.jp\/job\/10583\/","title":{"rendered":"You don&#8217;t need Kafka: Building a message queue with only two UNIX signals"},"content":{"rendered":"\n<\/p>\n<div>\n<p>Have you ever asked yourself what if we could replace any message broker with a very simple one using only two UNIX signals? Well, I\u2019m not surprised if you didn\u2019t. But I did. And I want to share my journey of how I achieved it.<\/p>\n<p>If you want to learn about UNIX signals, binary operations the easy way, how a message broker works under the hood, and a bit of Ruby, this post is for you.<\/p>\n<p>And if you came here just because of the clickbait title, I apologize and invite you to keep reading. It\u2019ll be fun, I promise.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/leandronsp.com\/uploads\/3491.png\" alt=\"image\"\/><\/p>\n<h2><a target=\"_blank\" href=\"#its-all-about-unix\" aria-hidden=\"true\" class=\"anchor\" id=\"its-all-about-unix\"\/>It\u2019s all about UNIX<\/h2>\n<p>A few days ago, I saw some discussion on the internet about how we could send messages between processes. Many people think of sockets, which are the most common way to send messages, even allowing communication across different machines and networks. Some don\u2019t even realize that pipes are another way to send messages between processes:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">echo<\/span> <span style=\"color: #98c379;\">'hello'<\/span> <span style=\"color: #56b6c2;\">|<\/span> <span style=\"color: #61afef;\">base64<\/span>\n<\/p><p><span style=\"color: #61afef;\">aGVsbG8K<\/span>\n<\/p><\/code><\/pre>\n<p>Here\u2019s what\u2019s happening:<\/p>\n<ul>\n<li>The process <code>echo<\/code> is started with the content \u201chello\u201d<\/li>\n<li><code>echo<\/code> is a program that prints the message to <em>STDOUT<\/em><\/li>\n<li>Through the pipe, the content in <em>STDOUT<\/em> is <strong>sent<\/strong> directly to the <em>STDIN<\/em> of the <code>base64<\/code> process<\/li>\n<li>The <code>base64<\/code> process encodes its input to Base64 and then puts the result in <em>STDOUT<\/em><\/li>\n<\/ul>\n<p>Note the word \u201csend\u201d. Yes, anonymous pipes are a form of <strong>IPC (Inter-process communication).<\/strong> Other forms of IPC in UNIX include:<\/p>\n<ul>\n<li>named pipes (mkfifo)<\/li>\n<li>sockets<\/li>\n<li>regular files<\/li>\n<li>or even a simple <strong>signal<\/strong><\/li>\n<\/ul>\n<h2><a target=\"_blank\" href=\"#unix-signals\" aria-hidden=\"true\" class=\"anchor\" id=\"unix-signals\"\/>UNIX signals<\/h2>\n<p>According to <a target=\"_blank\" href=\"https:\/\/leandronsp.com\/articles\/url\">Wikipedia<\/a>:<\/p>\n<blockquote>\n<p>A UNIX signal is a standardized message sent to a program to trigger specific behaviour, such as quitting or error handling<\/p>\n<\/blockquote>\n<p>There are many signals we can send to a process, including:<\/p>\n<ul>\n<li>SIGTERM &#8211; sends a notification to the process to terminate. It can be \u201ctrapped,\u201d which means the process can do some cleanup work before termination, like releasing OS resources and closing file descriptors<\/li>\n<li>SIGKILL &#8211; sends a termination signal that cannot be trapped or ignored, forcing immediate termination<\/li>\n<li>SIGINT &#8211; the interrupt signal, typically sent when you press <code>Ctrl+C<\/code> in the terminal. It can be trapped, allowing the process to perform cleanup before exiting gracefully<\/li>\n<li>SIGHUP &#8211; the hangup signal, originally sent when a terminal connection was lost. Modern applications often use it to reload configuration files without restarting the process<\/li>\n<li>SIGQUIT &#8211; similar to SIGINT but also generates a core dump for debugging<\/li>\n<li>SIGSTOP &#8211; pauses (suspends) a process. Cannot be trapped or ignored<\/li>\n<li>SIGCONT &#8211; resumes a process that was paused by <em>SIGSTOP<\/em><\/li>\n<li>SIGCHLD &#8211; sent to a parent process when a child process terminates or stops<\/li>\n<li><strong>SIGUSR1<\/strong> and <strong>SIGUSR2<\/strong> &#8211; user-defined signals that applications can use for custom purposes<\/li>\n<\/ul>\n<h2><a target=\"_blank\" href=\"#sending-messages-using--signals\" aria-hidden=\"true\" class=\"anchor\" id=\"sending-messages-using--signals\"\/>Sending messages using  signals<\/h2>\n<p>Okay, we know that signals are a primitive form of IPC. UNIX-like systems provide a syscall called <code>kill<\/code> that sends signals to processes. Historically, this syscall was created solely to terminate processes. But over time, they needed to accommodate other types of signals, so they reused the same syscall for different purposes.<\/p>\n<p>For instance, let\u2019s create a simple Ruby script <code>sleeper.rb<\/code> which sleeps for 60 seconds, nothing more:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Process ID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Sleeping for 60 seconds...<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">60<\/span>\n<\/p><\/code><\/pre>\n<p>After running we see:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>Process ID: 55402\n<\/p><p>Sleeping for 60 seconds...\n<\/p><\/code><\/pre>\n<p>In another window, we can <strong>send<\/strong> the <code>SIGTERM<\/code> signal to the process <code>55402<\/code> via syscall <code>kill<\/code>:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">kill<\/span> <span style=\"color: #e06c75;\">-SIGTERM<\/span> <span style=\"color: #d19a66;\">55402<\/span>\n<\/p><\/code><\/pre>\n<p>And then, in the script session:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\">[1]    55402 terminated  ruby sleeper.rb\n<\/p><\/code><\/pre>\n<h3><a target=\"_blank\" href=\"#signal-traps\" aria-hidden=\"true\" class=\"anchor\" id=\"signal-traps\"\/>Signal traps<\/h3>\n<p>In Ruby, we can also <em>trap<\/em> a signal using the <code>trap<\/code> method in Ruby:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Process ID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Sleeping for 60 seconds...<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGTERM<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">do<\/span> \n<\/p><p>  <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Received SIGTERM, exiting gracefully...<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">exit<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">60<\/span>\n<\/p><\/code><\/pre>\n<p>Which in turn, after sending the signal, will gracefully:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>Process ID: 55536\n<\/p><p>Sleeping for 60 seconds...\n<\/p><p>Received SIGTERM, exiting gracefully...\n<\/p><\/code><\/pre>\n<p>After all, we <em>cannot send messages using signals<\/em>. They are a primitive way of sending <em>standardized messages<\/em> which will trigger specific behaviours. At most, we can trap some signals, but nothing more.<\/p>\n<blockquote>\n<p>Okay Leandro, but what\u2019s the purpose of this article then?<\/p>\n<\/blockquote>\n<p><em>Hold on<\/em>. That\u2019s exactly why I\u2019m here. To prove points by doing useless stuff, like when I <a target=\"_blank\" href=\"https:\/\/leandronsp.com\/articles\/simulating-oop-in-bash-3mop\">simulated OOP in Bash<\/a> a couple of years ago (it was fun though).<\/p>\n<p>To understand how we can \u201chack\u201d UNIX signals and send messages between processes, let\u2019s first talk a bit about <strong>binary operations<\/strong>. Yes, those \u201czeros\u201d and \u201cones\u201d you were scared of when you saw them for the first time. But they don\u2019t bite (\ud83e\udd41 LOL), I promise.<\/p>\n<h2><a target=\"_blank\" href=\"#what-is-a-message\" aria-hidden=\"true\" class=\"anchor\" id=\"what-is-a-message\"\/>What is a message?<\/h2>\n<p>If we model a message as a sequence of characters, we could say that at a high-level, messages are simply <em>strings<\/em>. But in memory, they are stored as <strong>bytes<\/strong>.<\/p>\n<p>We know that bytes are made of bits. In computer terms, what\u2019s a bit? It\u2019s simply an abstraction representing <strong>only two states<\/strong>:<\/p>\n<p>That\u2019s it. For instance, using <a target=\"_blank\" href=\"https:\/\/leandronsp.com\/articles\/url\">ASCII<\/a>, we know that the letter \u201ch\u201d has the following codes:<\/p>\n<ul>\n<li>104 in decimal<\/li>\n<li><code>0x68<\/code> in hexadecimal<\/li>\n<li><code>01101000<\/code> in binary<\/li>\n<\/ul>\n<p>Binary-wise, what if we represented each \u201c0\u201d with a specific signal and each \u201c1\u201d with another? We know that some signals such as SIGTERM, SIGINT, and SIGCONT can be trapped, but intercepting them would harm their original purpose.<\/p>\n<p>But thankfully, UNIX provides two user-defined signals that are perfect for our hacking experiment.<\/p>\n<h2><a target=\"_blank\" href=\"#sending-sigusr1-and-sigusr2\" aria-hidden=\"true\" class=\"anchor\" id=\"sending-sigusr1-and-sigusr2\"\/>Sending SIGUSR1 and SIGUSR2<\/h2>\n<p>First things first, let\u2019s trap those signals in the code:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Process ID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Sleeping forever. Send signals to this process to see how it responds.<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">do<\/span> \n<\/p><p>  <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Received SIGUSR1 signal<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">do<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Received SIGUSR2 signal<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #e06c75;\">sleep<\/span>\n<\/p><\/code><\/pre>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>Process ID: 56172\n<\/p><p>Sleeping forever. Send signals to this process to see how it responds.\n<\/p><\/code><\/pre>\n<p>After sending some <code>kill -SIGUSR1 56172<\/code> and <code>kill -SIGUSR2 56172<\/code>, we can see that the process prints the following content:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>Process ID: 56172\n<\/p><p>Sleeping forever. Send signals to this process to see how it responds.\n<\/p><p>Received SIGUSR1 signal\n<\/p><p>Received SIGUSR2 signal\n<\/p><p>Received SIGUSR2 signal\n<\/p><p>Received SIGUSR1 signal\n<\/p><p>Received SIGUSR1 signal\n<\/p><p>Received SIGUSR2 signal\n<\/p><\/code><\/pre>\n<p><strong>Signals don\u2019t carry data<\/strong>. But the example we have is perfect for changing to bits, uh?<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>Received SIGUSR1 signal # 0\n<\/p><p>Received SIGUSR2 signal # 1\n<\/p><p>Received SIGUSR2 signal # 1\n<\/p><p>Received SIGUSR1 signal # 0\n<\/p><p>Received SIGUSR2 signal # 1\n<\/p><p>Received SIGUSR1 signal # 0\n<\/p><p>Received SIGUSR1 signal # 0\n<\/p><p>Received SIGUSR1 signal # 0\n<\/p><\/code><\/pre>\n<p>That\u2019s exactly <code>01101000<\/code>, the binary representation of the letter \u201ch\u201d. We\u2019re simply <strong>encoding<\/strong> the letter as a binary representation and sending it via signals<\/p>\n<p>Again, we\u2019re <strong>encoding it as a binary<\/strong> and sending it <strong>via signals<\/strong>.<\/p>\n<p><em>How cool is that<\/em>?<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/leandronsp.com\/uploads\/3299.png\" alt=\"image\"\/><\/p>\n<h3><a target=\"_blank\" href=\"#decoding-the-binary-data\" aria-hidden=\"true\" class=\"anchor\" id=\"decoding-the-binary-data\"\/>Decoding the binary data<\/h3>\n<p>On the other side, the receiver should be capable of decoding the message and converting it back to the letter \u201ch\u201d:<\/p>\n<ul>\n<li>sender <em>encodes<\/em> the message<\/li>\n<li>receiver <em>decodes<\/em> the message<\/li>\n<\/ul>\n<p>So, how do we decode <code>01101000<\/code> (the letter \u201ch\u201d in ASCII)? Let\u2019s break it down into a few steps:<\/p>\n<ol>\n<li>First, we need to see the 8 bits as individual digits in their respective positions<\/li>\n<li>The rightmost bit is at position 0, whereas the leftmost bit is at position 7. This is how we define the most significant bit (<strong>MSB<\/strong>, the leftmost) and the least significant bit (<strong>LSB<\/strong>, the rightmost)<\/li>\n<li>For this example, we perform a <strong>left shift<\/strong> operation on each bit and then sum all the values, in this case from MSB to LSB (the order doesn\u2019t matter much for now): <code>(0 :<br \/><em>left shift on <em>zeros<\/em> will always produce a <em>zero<\/em><\/em><\/code><\/li>\n<\/ol>\n<ul>\n<li><code>0  = <code>(2 ** 7) * 0<\/code> = <code>128 * 0<\/code> = 0<\/code><\/li>\n<li><code>1  = <code>(2 ** 6) * 1<\/code> = <code>64 * 1<\/code> = 64<\/code><\/li>\n<\/ul>\n<p>Similarly to the remaining bits:<\/p>\n<ul>\n<li><code>1  = 32<\/code><\/li>\n<li><code>0  = 0<\/code><\/li>\n<li><code>1  = 8<\/code><\/li>\n<li><code>0  = 0<\/code><\/li>\n<li><code>0  = 0<\/code><\/li>\n<li><code>0  = 0<\/code><\/li>\n<\/ul>\n<p>So, our sum becomes, from MSB to LSB:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>MSB                          LSB\n<\/p><p>0   1    1    0   1   0   0   0\n<\/p><p>0 + 64 + 32 + 0 + 8 + 0 + 0 + 0 = 104\n<\/p><\/code><\/pre>\n<p>104 is exactly the <strong>decimal representation<\/strong> of the letter \u201ch\u201d in ASCII.<\/p>\n<p><em>How wonderful is that?<\/em><\/p>\n<h3><a target=\"_blank\" href=\"#sending-the-letter-h\" aria-hidden=\"true\" class=\"anchor\" id=\"sending-the-letter-h\"\/>Sending the letter \u201ch\u201d<\/h3>\n<p>Now let\u2019s convert these operations to Ruby code. We\u2019ll write a simple program <code>receiver.rb<\/code> that receives signals in order from LSB to MSB (positions 0 to 7) and then converts them back to ASCII characters, printing to <code>STDOUT<\/code>.<\/p>\n<p>Basically, we\u2019ll <strong>accumulate<\/strong> bits and whenever we form a complete byte, we\u2019ll decode it to its ASCII representation. The very basic implementation of our <code>accumulate_bit(bit)<\/code> method would look like as follows:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># start with the LSB<\/span>\n<\/p><p><span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\"># The left shift operator (\n<\/span><\/p><p>  <span style=\"color: #7f848e;\"># shift the bits of the number to the left.<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\">#<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\"># This is equivalent of: (2 ** @position) * bit<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\"> <span style=\"color: #e06c75;\">@position<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/span><\/p><p>  <span style=\"color: #c678dd;\">return<\/span> <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">7<\/span> <span style=\"color: #7f848e;\"># stop accumulating after 8 bits (byte)<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #d19a66;\">1<\/span> <span style=\"color: #7f848e;\"># move to the next bit position: 0 becomes 1, 1 becomes 2, etc.<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># Letter \"h\" in binary is 01101000<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># But we'll send from the LSB to the MSB<\/span>\n<\/p><p><span style=\"color: #7f848e;\">#<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># 0110 1000 (MSB -&gt; LSB) becomes 0001 0110 (LSB -&gt; MSB)<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># The order doesn't matter that much, it'll depend on <\/span>\n<\/p><p><span style=\"color: #7f848e;\"># the receiver's implementation.<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #7f848e;\"># should print 104, which is the ASCII code for \"h\"<\/span>\n<\/p><\/code><\/pre>\n<p><em>Pay attention to this code. It\u2019s very important and builds the foundation for the next steps. If you didn\u2019t get it, go back and read it again. Try it yourself in the terminal or using your preferred programming language.<\/em><\/p>\n<p>Now, how to convert the decimal <code>104<\/code> to the ASCII character representation? Luckily, Ruby provides a method called <code>chr<\/code> which does the job:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">irb<\/span><span style=\"color: #56b6c2;\">&gt;<\/span> <span style=\"color: #e06c75;\">puts<\/span> <span style=\"color: #d19a66;\">104<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span>\n<\/p><p><span style=\"color: #56b6c2;\">=&gt;<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">h<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><\/code><\/pre>\n<p>We could do the same job for the rest of the word \u201chello\u201d, for instance. According to the <a target=\"_blank\" href=\"https:\/\/www.ascii-code.com\/\">ASCII table<\/a>, it should be the following:<\/p>\n<ul>\n<li><code>e<\/code> in decimal is <code>101<\/code><\/li>\n<li><code>l<\/code> in decimal is <code>108<\/code><\/li>\n<li><code>o<\/code> in decimal is <code>111<\/code><\/li>\n<\/ul>\n<p>Let\u2019s check if Ruby knows that:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #d19a66;\">104<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span>    <span style=\"color: #7f848e;\"># \"h\"<\/span>\n<\/p><p><span style=\"color: #d19a66;\">101<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span>    <span style=\"color: #7f848e;\"># \"e\"<\/span>\n<\/p><p><span style=\"color: #d19a66;\">108<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span>    <span style=\"color: #7f848e;\"># \"l\"<\/span>\n<\/p><p><span style=\"color: #d19a66;\">111<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span>    <span style=\"color: #7f848e;\"># \"o\"<\/span>\n<\/p><\/code><\/pre>\n<p>We can even \u201cdecode\u201d the word to the decimal representation in ASCII:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">irb<\/span><span style=\"color: #56b6c2;\">&gt;<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">hello<\/span><span style=\"color: #98c379;\">\"<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">bytes<\/span>\n<\/p><p><span style=\"color: #56b6c2;\">=&gt;<\/span> <span style=\"color: #c678dd;\">[<\/span><span style=\"color: #d19a66;\">104<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #d19a66;\">101<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #d19a66;\">108<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #d19a66;\">108<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #d19a66;\">111<\/span><span style=\"color: #c678dd;\">]<\/span>\n<\/p><\/code><\/pre>\n<p>Now, time to finish our receiver implementation to properly print the letter \u201ch\u201d:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># start with the LSB<\/span>\n<\/p><p><span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">return<\/span> <span style=\"color: #c678dd;\">unless<\/span> <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">8<\/span> <span style=\"color: #7f848e;\"># if not yet accumulated a byte, keep accumulating<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">print<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Received byte: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">@accumulator<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\"> (<\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">@accumulator<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">)<\/span><span style=\"color: #56b6c2;\">\\n<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># reset the accumulator<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># reset position for the next byte<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\"># The left shift operator (\n<\/span><\/p><p>  <span style=\"color: #7f848e;\"># shift the bits of the number to the left.<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\">#<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\"># This is equivalent of: (2 ** @position) * bit<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\"> <span style=\"color: #e06c75;\">@position<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/span><\/p><p>  <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #d19a66;\">1<\/span> <span style=\"color: #7f848e;\"># move to the next bit position: 0 becomes 1, 1 becomes 2, etc.<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Process ID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #e06c75;\">sleep<\/span>\n<\/p><\/code><\/pre>\n<p><em>Read that code and its comments. It\u2019s very important. Do not continue reading until you really get what\u2019s happening here.<\/em><\/p>\n<ul>\n<li>Whenever we get <code>SIGUSR1<\/code>, we accumulate the bit <code>0<\/code><\/li>\n<li>When getting <code>SIGUSR2<\/code>, accumulate then the bit <code>1<\/code><\/li>\n<li>When accumulator reaches  the position<code>8<\/code>, it means we have a byte. At this moment we should print the ASCII representation using the <code>.chr<\/code> we seen earlier. Then, reset bit position and accumulator<\/li>\n<\/ul>\n<p>Let\u2019s see our receiver in action! Start the receiver in one terminal:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">ruby<\/span> <span style=\"color: #e06c75;\">receiver.rb<\/span>\n<\/p><p><span style=\"color: #61afef;\">Process<\/span> <span style=\"color: #e06c75;\">ID:<\/span> <span style=\"color: #d19a66;\">58219<\/span>\n<\/p><\/code><\/pre>\n<p>Great! Now the receiver is listening for signals. In another terminal, let\u2019s manually send signals<br \/>to form the letter \u201ch\u201d (which is <code>01101000<\/code> in binary, remember?):<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>  # Sending from LSB to MSB: 0, 0, 0, 1, 0, 1, 1, 0\n<\/p><p>  $ kill -SIGUSR1 58219  # 0\n<\/p><p>  $ kill -SIGUSR1 58219  # 0\n<\/p><p>  $ kill -SIGUSR1 58219  # 0\n<\/p><p>  $ kill -SIGUSR2 58219  # 1\n<\/p><p>  $ kill -SIGUSR1 58219  # 0\n<\/p><p>  $ kill -SIGUSR2 58219  # 1\n<\/p><p>  $ kill -SIGUSR2 58219  # 1\n<\/p><p>  $ kill -SIGUSR1 58219  # 0\n<\/p><\/code><\/pre>\n<p>And in the receiver terminal, we should see:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>Received byte: 104 (h)\n<\/p><\/code><\/pre>\n<p><em>How amazing is that?<\/em> We just sent the letter \u201ch\u201d using only two UNIX signals!<\/p>\n<p>But wait. Manually sending 8 signals for each character? That\u2019s tedious and error-prone. What if we wanted to send the word \u201chello\u201d? That\u2019s 5 characters \u00d7 8 bits = 40 signals to send manually. No way.<\/p>\n<p><em>We need a sender.<\/em><\/p>\n<h3><a target=\"_blank\" href=\"#building-the-sender\" aria-hidden=\"true\" class=\"anchor\" id=\"building-the-sender\"\/>Building the sender<\/h3>\n<p>The sender\u2019s job is the opposite of the receiver: it should encode a message (string) into bits and send them as signals to the receiver process.<\/p>\n<p>Let\u2019s think about what we need:<\/p>\n<ol>\n<li>Take a message as input (like \u201chello\u201d)<\/li>\n<li>Convert each character to its byte representation<\/li>\n<li>Extract the 8 bits from each byte<\/li>\n<li>Send <code>SIGUSR1<\/code> for bit 0, <code>SIGUSR2<\/code> for bit 1<\/li>\n<li>Repeat for all characters<\/li>\n<\/ol>\n<p>The tricky part here is the step 3: <strong>how do we extract individual bits from a byte?<\/strong> To extract the bit at position <code>i<\/code>, we can use the following formula:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>bit = (byte &gt;&gt; i) &amp; 1\n<\/p><\/code><\/pre>\n<p>Let me break this down:<\/p>\n<ul>\n<li><code>byte &gt;&gt; i<\/code> performs a <em>right shift<\/em> by <code>i<\/code> positions<\/li>\n<li><code>&amp; 1<\/code> is a bitwise <code>AND<\/code> operation that extracts only the <em>rightmost<\/em> bit<\/li>\n<\/ul>\n<p>For the letter \u201ch\u201d (<code>01101000<\/code> in binary, <code>104<\/code> in decimal):<\/p>\n<p><strong>Position 0 (LSB):<\/strong><\/p>\n<ul>\n<li><code>(104 &gt;&gt; 0)<\/code> = <code>104 \/ (2 ** 0)<\/code> = <code>104 \/ 1<\/code> = 104<\/li>\n<li><code>01101000<\/code> &gt;&gt; 0 = <code>01101000<\/code><\/li>\n<li><code>01101000<\/code> &amp; <code>00000001<\/code> = 0 (<em>one<\/em> AND <em>zero<\/em> is <em>zero<\/em>)<\/li>\n<\/ul>\n<p><strong>Position 1:<\/strong><\/p>\n<ul>\n<li><code>(104 &gt;&gt; 1)<\/code> = <code>104 \/ (2 ** 1)<\/code> = <code>104 \/ 2<\/code> = 52<\/li>\n<li><code>01101000<\/code> &gt;&gt; 1 = <code>00110100<\/code><\/li>\n<li><code>00110100<\/code> &amp; <code>00000001<\/code> = 0<\/li>\n<\/ul>\n<p><strong>Position 2:<\/strong><\/p>\n<ul>\n<li><code>(104 &gt;&gt; 2)<\/code> = <code>104 \/ (2 ** 2)<\/code> = <code>104 \/ 4<\/code> = 26<\/li>\n<li><code>01101000<\/code> &gt;&gt; 2 = <code>00011010<\/code><\/li>\n<li><code>00011010<\/code> &amp; <code>00000001<\/code> = 0<\/li>\n<\/ul>\n<p><strong>Position 3:<\/strong><\/p>\n<ul>\n<li><code>(104 &gt;&gt; 3)<\/code> = <code>104 \/ (2 ** 3)<\/code> = <code>104 \/ 8<\/code> = 13<\/li>\n<li><code>01101000<\/code> &gt;&gt; 3 = <code>00001101<\/code><\/li>\n<li><code>00001101<\/code> &amp; <code>00000001<\/code> = 1 (<em>one<\/em> AND <em>one<\/em> equals <em>one<\/em>)<\/li>\n<\/ul>\n<p>And so on for positions 4, 5, 6, and 7. This gives us: <code>0, 0, 0, 1, 0, 1, 1, 0<\/code> \u2014 exactly the bits we need from LSB to MSB!<\/p>\n<ul>\n<li><code>(104 &gt;&gt; 0) &amp; 1<\/code> = <code>104 &amp; 1<\/code> = 0<\/li>\n<li><code>(104 &gt;&gt; 1) &amp; 1<\/code> = <code>52 &amp; 1<\/code> = 0<\/li>\n<li><code>(104 &gt;&gt; 2) &amp; 1<\/code> = <code>26 &amp; 1<\/code> = 0<\/li>\n<li><code>(104 &gt;&gt; 3) &amp; 1<\/code> = <code>13 &amp; 1<\/code> = 1<\/li>\n<li><code>(104 &gt;&gt; 4) &amp; 1<\/code> = <code>6 &amp; 1<\/code> = 0<\/li>\n<li><code>(104 &gt;&gt; 5) &amp; 1<\/code> = <code>3 &amp; 1<\/code> = 1<\/li>\n<li><code>(104 &gt;&gt; 6) &amp; 1<\/code> = <code>1 &amp; 1<\/code> = 1<\/li>\n<li><code>(104 &gt;&gt; 7) &amp; 1<\/code> = <code>0 &amp; 1<\/code> = 0<\/li>\n<\/ul>\n<blockquote>\n<p>Pay close attention to this technique. It\u2019s a fundamental operation in low-level programming.<\/p>\n<\/blockquote>\n<p>So now time to build the <code>sender.rb<\/code> which is pretty simple:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">receiver_pid<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">ARGV<\/span><span style=\"color: #c678dd;\">[<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">]<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">to_i<\/span>\n<\/p><p><span style=\"color: #e06c75;\">message<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">ARGV<\/span><span style=\"color: #c678dd;\">[<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #56b6c2;\">..<\/span><span style=\"color: #56b6c2;\">-<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">]<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">join<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\"> <\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">encode_byte<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #d19a66;\">8<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">times<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">map<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">i<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>    <span style=\"color: #7f848e;\"># Extract each bit from the byte, starting from the LSB<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span> <span style=\"color: #56b6c2;\">&gt;&gt;<\/span> <span style=\"color: #e06c75;\">i<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #56b6c2;\">&amp;<\/span> <span style=\"color: #d19a66;\">1<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">bytes<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">each<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">encode_byte<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">each<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">signal<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #56b6c2;\">?<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span> <span style=\"color: #56b6c2;\">:<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p>    <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">kill<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">signal<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">receiver_pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">0.001<\/span> <span style=\"color: #7f848e;\"># Delay to allow the receiver to process the signal<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><\/code><\/pre>\n<p>For each byte (8-bit structure) we extract the bit performing the <em>right shift<\/em> + <em>AND<\/em> oprerations. The result is the extracted bit.<\/p>\n<p>In the receiver window:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">ruby<\/span> <span style=\"color: #e06c75;\">receiver.rb<\/span>\n<\/p><p><span style=\"color: #61afef;\">Process<\/span> <span style=\"color: #e06c75;\">ID:<\/span> <span style=\"color: #d19a66;\">68968<\/span>\n<\/p><\/code><\/pre>\n<p>And in the sender window:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">ruby<\/span> <span style=\"color: #e06c75;\">sender.rb<\/span> <span style=\"color: #d19a66;\">68968<\/span> <span style=\"color: #e06c75;\">h<\/span>\n<\/p><\/code><\/pre>\n<p>The receiver will print:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">ruby<\/span> <span style=\"color: #e06c75;\">receiver.rb<\/span>\n<\/p><p><span style=\"color: #61afef;\">Process<\/span> <span style=\"color: #e06c75;\">ID:<\/span> <span style=\"color: #d19a66;\">68968<\/span>\n<\/p><p><span style=\"color: #61afef;\">Received<\/span> <span style=\"color: #e06c75;\">byte:<\/span> <span style=\"color: #d19a66;\">104<\/span><span style=\"color: #abb2bf;\"\/> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #61afef;\">h<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><\/code><\/pre>\n<p><em>Processes sending messages with only two signals!<\/em> How wonderful is that?<\/p>\n<h3><a target=\"_blank\" href=\"#sending-the-hello-message\" aria-hidden=\"true\" class=\"anchor\" id=\"sending-the-hello-message\"\/>Sending the \u201chello\u201d message<\/h3>\n<p>Now, sending the hello message is super easy. The sender is already able to send not only a letter but any message using signals:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">ruby<\/span> <span style=\"color: #e06c75;\">sender.rb<\/span> <span style=\"color: #d19a66;\">68968<\/span> <span style=\"color: #e06c75;\">hello<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># And the receiver:<\/span>\n<\/p><p><span style=\"color: #61afef;\">Received<\/span> <span style=\"color: #e06c75;\">byte:<\/span> <span style=\"color: #d19a66;\">104<\/span><span style=\"color: #abb2bf;\"\/> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #61afef;\">h<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">Received<\/span> <span style=\"color: #e06c75;\">byte:<\/span> <span style=\"color: #d19a66;\">101<\/span><span style=\"color: #abb2bf;\"\/> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #61afef;\">e<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">Received<\/span> <span style=\"color: #e06c75;\">byte:<\/span> <span style=\"color: #d19a66;\">108<\/span><span style=\"color: #abb2bf;\"\/> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #61afef;\">l<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">Received<\/span> <span style=\"color: #e06c75;\">byte:<\/span> <span style=\"color: #d19a66;\">108<\/span><span style=\"color: #abb2bf;\"\/> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #61afef;\">l<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">Received<\/span> <span style=\"color: #e06c75;\">byte:<\/span> <span style=\"color: #d19a66;\">111<\/span><span style=\"color: #abb2bf;\"\/> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #61afef;\">o<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><\/code><\/pre>\n<p>Just change the <code>receiver<\/code> implementation a little bit:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">return<\/span> <span style=\"color: #c678dd;\">unless<\/span> <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">8<\/span> <span style=\"color: #7f848e;\"># if not yet accumulated a byte, keep accumulating<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">print<\/span> <span style=\"color: #e06c75;\">@accumulator<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span> <span style=\"color: #7f848e;\"># print the byte as a character<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># reset the accumulator<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># reset position for the next byte<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><\/code><\/pre>\n<p>And then:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-bash\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #abb2bf;\">$<\/span> <span style=\"color: #e06c75;\">ruby<\/span> <span style=\"color: #e06c75;\">sender.rb<\/span> <span style=\"color: #d19a66;\">96875<\/span> <span style=\"color: #e06c75;\">Hello<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># In the receiver's terminal<\/span>\n<\/p><p><span style=\"color: #61afef;\">Process<\/span> <span style=\"color: #e06c75;\">ID:<\/span> <span style=\"color: #d19a66;\">96875<\/span>\n<\/p><p><span style=\"color: #61afef;\">Hello<\/span>\n<\/p><\/code><\/pre>\n<p>However, if we send the message again, the receiver will print everything in the same line:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p>$ <span style=\"color: #61afef;\">ruby<\/span> <span style=\"color: #e06c75;\">sender<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">rb<\/span> <span style=\"color: #d19a66;\">96875<\/span> <span style=\"color: #e5c07b;\">Hello<\/span>\n<\/p><p>$ <span style=\"color: #61afef;\">ruby<\/span> <span style=\"color: #e06c75;\">sender<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">rb<\/span> <span style=\"color: #d19a66;\">96875<\/span> <span style=\"color: #e5c07b;\">Hello<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># In the receiver's terminal<\/span>\n<\/p><p><span style=\"color: #e5c07b;\">Process<\/span> <span style=\"color: #e06c75;\">ID<\/span><span style=\"color: #abb2bf;\">:<\/span> <span style=\"color: #d19a66;\">96875<\/span>\n<\/p><p><span style=\"color: #e5c07b;\">HelloHello<\/span>\n<\/p><\/code><\/pre>\n<p>It\u2019s obvious: the receiver doesn\u2019t know where the sender finished the message, so it\u2019s impossible to know where we should stop one message and print the next one on a new line with <code>\\n<\/code>.<\/p>\n<p>We should then determine how the sender indicates the end of the message. How about being it all <em>zeroes<\/em> (<code>0000 0000<\/code>)?<\/p>\n<ul>\n<li>We send the message: first 5 bytes representing the \u201chello\u201d message<\/li>\n<li>Then we send a \u201cNULL terminator\u201d, just one byte <em>0<\/em> (<code>0000 0000<\/code>)<\/li>\n<\/ul>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>0110 1000 # h\n<\/p><p>0110 0101 # e\n<\/p><p>0110 1000 # l\n<\/p><p>0110 1000 # l\n<\/p><p>0110 1111 # o\n<\/p><p>0000 0000 # NULL\n<\/p><\/code><\/pre>\n<p>Hence, when the <em>receiver<\/em> gets a NULL terminator, it will print a line feed <code>\\n<\/code>. Let\u2019s change the <code>sender.rb<\/code> first:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">receiver_pid<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">ARGV<\/span><span style=\"color: #c678dd;\">[<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">]<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">to_i<\/span>\n<\/p><p><span style=\"color: #e06c75;\">message<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">ARGV<\/span><span style=\"color: #c678dd;\">[<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #56b6c2;\">..<\/span><span style=\"color: #56b6c2;\">-<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">]<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">join<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\"> <\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">encode_byte<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #d19a66;\">8<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">times<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">map<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">i<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>    <span style=\"color: #7f848e;\"># Extract each bit from the byte, starting from the LSB<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span> <span style=\"color: #56b6c2;\">&gt;&gt;<\/span> <span style=\"color: #e06c75;\">i<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #56b6c2;\">&amp;<\/span> <span style=\"color: #d19a66;\">1<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">bytes<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">each<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">encode_byte<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">each<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">signal<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #56b6c2;\">?<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span> <span style=\"color: #56b6c2;\">:<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p>    <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">kill<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">signal<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">receiver_pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">0.001<\/span> <span style=\"color: #7f848e;\"># Delay to allow the receiver to process the signal<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #7f848e;\"># Send NULL terminator (0000 0000)<\/span>\n<\/p><p><span style=\"color: #d19a66;\">8<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">times<\/span> <span style=\"color: #c678dd;\">do<\/span>\n<\/p><p>  <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">kill<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">receiver_pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">0.001<\/span> <span style=\"color: #7f848e;\"># Delay to allow the receiver to process the signal<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Message sent to receiver (PID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">receiver_pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">)<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><\/code><\/pre>\n<p>Then, the <code>receiver.rb<\/code>:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># start with the LSB<\/span>\n<\/p><p><span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p><span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">decode_signal<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">return<\/span> <span style=\"color: #c678dd;\">unless<\/span> <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">8<\/span> <span style=\"color: #7f848e;\"># if not yet accumulated a byte, keep accumulating<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">@accumulator<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">zero?<\/span> <span style=\"color: #7f848e;\"># NULL terminator received<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">print<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #56b6c2;\">\\n<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">else<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">print<\/span> <span style=\"color: #e06c75;\">@accumulator<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">chr<\/span> <span style=\"color: #7f848e;\"># print the byte as a character<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># reset the accumulator<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #7f848e;\"># reset position for the next byte<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\"># The left shift operator (\n<\/span><\/p><p>  <span style=\"color: #7f848e;\"># shift the bits of the number to the left.<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\">#<\/span>\n<\/p><p>  <span style=\"color: #7f848e;\"># This is equivalent of: (2 ** @position) * bit<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\"> <span style=\"color: #e06c75;\">@position<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/span><\/p><p>  <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #d19a66;\">1<\/span> <span style=\"color: #7f848e;\"># move to the next bit position: 0 becomes 1, 1 becomes 2, etc.<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Process ID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #e06c75;\">sleep<\/span>\n<\/p><\/code><\/pre>\n<p>Output:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-plaintext\" translate=\"no\" tabindex=\"0\"><p>$ ruby sender.rb 96875 Hello, World!\n<\/p><p>$ ruby sender.rb 96875 You're welcome\n<\/p><p>$ ruby sender.rb 96875 How are you?\n<\/p><p># Receiver\n<\/p><p>Process ID: 97176\n<\/p><p>Hello, World!\n<\/p><p>You're welcome\n<\/p><p>How are you?\n<\/p><\/code><\/pre>\n<blockquote>\n<p>OMG Leandro! That\u2019s amazing!<\/p>\n<\/blockquote>\n<p><em>Amazing, right?<\/em> We just built an entire communication system between two processes using one of the most primitive methods available: <strong>UNIX signals.<\/strong><\/p>\n<p>The sky\u2019s the limit now! Why not build a <em>full-fledged message broker<\/em> using this crazy technique?<\/p>\n<h2><a target=\"_blank\" href=\"#a-modest-message-broker-using-unix-signals\" aria-hidden=\"true\" class=\"anchor\" id=\"a-modest-message-broker-using-unix-signals\"\/>A modest message broker using UNIX signals<\/h2>\n<p>We\u2019ll break down the development into three components:<\/p>\n<ol>\n<li><strong>Broker<\/strong>: the intermediary that routes messages<\/li>\n<li><strong>Consumer<\/strong>: processes that receive messages<\/li>\n<li><strong>Producer<\/strong>: processes that send messages<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/leandronsp.com\/uploads\/3395.png\" alt=\"image\"\/><\/p>\n<ol>\n<li>Let\u2019s start with the Broker. It should register itself with the producer, then trap incoming signals, decode them, and enqueue the messages for delivery to consumers via outgoing signals:<\/li>\n<\/ol>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #7f848e;\">#!\/usr\/bin\/env ruby<\/span>\n<\/p><p><span style=\"color: #c678dd;\">require_relative<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">signal_codec<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p><span style=\"color: #c678dd;\">require_relative<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">consumer<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p><span style=\"color: #c678dd;\">class<\/span> <span style=\"color: #e5c07b;\">Broker<\/span> \n<\/p><p>  <span style=\"color: #d19a66;\">PID<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">broker.pid<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">freeze<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">initialize<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@codec<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">SignalCodec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@queue<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">Queue<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@consumer_index<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">start<\/span> \n<\/p><p>    <span style=\"color: #e06c75;\">register_broker<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">process_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">process_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Broker PID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Waiting for messages...<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">distribute_messages<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">sleep<\/span> <span style=\"color: #7f848e;\"># Keep alive<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span> \n<\/p><p>  <span style=\"color: #c678dd;\">private<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">process_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@codec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>      <span style=\"color: #e06c75;\">@queue<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">push<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">unless<\/span> <span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">empty?<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">register_broker<\/span> \n<\/p><p>    <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">write<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">PID<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">at_exit<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">delete<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">PID<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">exist?<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">PID<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">distribute_messages<\/span>\n<\/p><p>    <span style=\"color: #e5c07b;\">Thread<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span> <span style=\"color: #c678dd;\">do<\/span>\n<\/p><p>      <span style=\"color: #61afef;\">loop<\/span> <span style=\"color: #c678dd;\">do<\/span>\n<\/p><p>        <span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">0.1<\/span>\n<\/p><p>        <span style=\"color: #c678dd;\">next<\/span> <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">@queue<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">empty?<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">consumers<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">exist?<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e5c07b;\">Consumer<\/span><span style=\"color: #abb2bf;\">::<\/span><span style=\"color: #d19a66;\">FILE<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #56b6c2;\">?<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">readlines<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e5c07b;\">Consumer<\/span><span style=\"color: #abb2bf;\">::<\/span><span style=\"color: #d19a66;\">FILE<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">map<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #56b6c2;\">&amp;<\/span><span style=\"color: #e06c75;\">:to_i<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #56b6c2;\">:<\/span> <span style=\"color: #c678dd;\">[<\/span><span style=\"color: #c678dd;\">]<\/span>\n<\/p><p>        <span style=\"color: #c678dd;\">next<\/span> <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">consumers<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">empty?<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">message<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e06c75;\">@queue<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">pop<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">true<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">rescue<\/span> <span style=\"color: #c678dd;\">next<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">consumer_pid<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e06c75;\">consumers<\/span><span style=\"color: #c678dd;\">[<\/span><span style=\"color: #e06c75;\">@consumer_index<\/span> <span style=\"color: #56b6c2;\">%<\/span> <span style=\"color: #e06c75;\">consumers<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">size<\/span><span style=\"color: #c678dd;\">]<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">@consumer_index<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #d19a66;\">1<\/span>\n<\/p><p>        <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">[SEND] <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\"> \u2192 Consumer <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">consumer_pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">@codec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">send_message<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">consumer_pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>      <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #c678dd;\">__FILE__<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #e06c75;\">$0<\/span> \n<\/p><p>  <span style=\"color: #e06c75;\">broker<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">Broker<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">broker<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">start<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><\/code><\/pre>\n<ul>\n<li>The broker registers itself<\/li>\n<li>Traps incoming signals <code>USR1<\/code> (bit 0) and <code>USR2<\/code> (bit 1)<\/li>\n<li>Enqueues the messages<\/li>\n<li>Send messages to consumers using outgoing signals (<code>USR1<\/code> and <code>USR2<\/code> too)<\/li>\n<\/ul>\n<p><em>Note that we\u2019re using a module called <code>SignalCodec<\/code> which will be explained soon. Basically this module contains all core components to encode\/decode signals and perform bitwise operations.<\/em><\/p>\n<ol start=\"2\">\n<li>Now the <code>Consumer<\/code> implementation:<\/li>\n<\/ol>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #7f848e;\">#!\/usr\/bin\/env ruby<\/span>\n<\/p><p><span style=\"color: #c678dd;\">require_relative<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">signal_codec<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p><span style=\"color: #c678dd;\">class<\/span> <span style=\"color: #e5c07b;\">Consumer<\/span>\n<\/p><p>  <span style=\"color: #d19a66;\">FILE<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">consumers.txt<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">freeze<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">initialize<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@codec<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">SignalCodec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">start<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">register_consumer<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">process_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">0<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">trap<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #61afef;\">process_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">1<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Consumer PID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Waiting for messages...<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">sleep<\/span> <span style=\"color: #7f848e;\"># Keep alive<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">private<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">process_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@codec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>      <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">[RECEIVE] <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">register_consumer<\/span>\n<\/p><p>    <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">open<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">FILE<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">a<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">f<\/span><span style=\"color: #c678dd;\">|<\/span> <span style=\"color: #e06c75;\">f<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>    <span style=\"color: #61afef;\">at_exit<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #e06c75;\">deregister_consumer<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">deregister_consumer<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">exist?<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">FILE<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>      <span style=\"color: #e06c75;\">consumers<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">readlines<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">FILE<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">map<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #56b6c2;\">&amp;<\/span><span style=\"color: #e06c75;\">:strip<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">reject<\/span> <span style=\"color: #c678dd;\">&amp;lbrace;<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #c678dd;\">|<\/span> <span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">to_i<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">pid<\/span> <span style=\"color: #c678dd;\">&amp;rbrace;<\/span>\n<\/p><p>      <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">write<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #d19a66;\">FILE<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">consumers<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">join<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">\"<\/span><span style=\"color: #56b6c2;\">\\n<\/span><span style=\"color: #98c379;\">\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #c678dd;\">__FILE__<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #e06c75;\">$0<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">consumer<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">Consumer<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span>\n<\/p><p>  <span style=\"color: #e06c75;\">consumer<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">start<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><\/code><\/pre>\n<ul>\n<li>The consumer starts and registers itself with the broker<\/li>\n<li>Consumer then traps incoming signals (bit 0 and bit 1)<\/li>\n<li>Decodes and prints messages<\/li>\n<\/ul>\n<ol start=\"3\">\n<li>Last but not least, the <code>Producer<\/code> implementation, which is pretty straightforward:<\/li>\n<\/ol>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #c678dd;\">#!\/usr\/bin\/env ruby<\/span>\n<\/p><p><span style=\"color: #c678dd;\">require_relative<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">signal_codec<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p><span style=\"color: #c678dd;\">require_relative<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">broker<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p><span style=\"color: #c678dd;\">unless<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">exist?<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e5c07b;\">Broker<\/span><span style=\"color: #abb2bf;\">::<\/span><span style=\"color: #d19a66;\">PID<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">abort<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Error: Broker not running (<\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e5c07b;\">Broker<\/span><span style=\"color: #abb2bf;\">::<\/span><span style=\"color: #d19a66;\">PID<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\"> not found)<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #e06c75;\">broker_pid<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">File<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">read<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e5c07b;\">Broker<\/span><span style=\"color: #abb2bf;\">::<\/span><span style=\"color: #d19a66;\">PID<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">strip<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">to_i<\/span>\n<\/p><p><span style=\"color: #e06c75;\">message<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">ARGV<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">join<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\"> <\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">empty?<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Usage: ruby producer.rb <message\/><\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p>  <span style=\"color: #61afef;\">exit<\/span> <span style=\"color: #d19a66;\">1<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #e06c75;\">codec<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e5c07b;\">SignalCodec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">new<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Sending: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><p><span style=\"color: #e06c75;\">codec<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">send_message<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">broker_pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p><span style=\"color: #61afef;\">puts<\/span> <span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">Message sent to broker (PID: <\/span><span style=\"color: #abb2bf;\">#&amp;lbrace;<\/span><span style=\"color: #e06c75;\">broker_pid<\/span><span style=\"color: #abb2bf;\">&amp;rbrace;<\/span><span style=\"color: #98c379;\">)<\/span><span style=\"color: #98c379;\">\"<\/span>\n<\/p><\/code><\/pre>\n<ul>\n<li>Producer receives a ASCII message from the <em>STDIN<\/em><\/li>\n<li>Encode and sends the message to the broker via outgoing signals<\/li>\n<\/ul>\n<p>So far, this architecture should look familiar. Many broker implementations follow these basic foundations.<\/p>\n<blockquote>\n<p>Of course, production-ready implementations are far more robust than this one. Here, we\u2019re just poking around with hacking and experimentation<\/p>\n<\/blockquote>\n<p>The coolest part is the <code>SignalCodec<\/code> though:<\/p>\n<pre class=\"athl\" style=\"color: #abb2bf; background-color: #282c34;\"><code class=\"language-ruby\" translate=\"no\" tabindex=\"0\"><p><span style=\"color: #c678dd;\">class<\/span> <span style=\"color: #e5c07b;\">SignalCodec<\/span> \n<\/p><p>  <span style=\"color: #d19a66;\">SIGNAL_DELAY<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0.001<\/span> <span style=\"color: #7f848e;\"># Delay between signals to allow processing<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">initialize<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@buffer<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #c678dd;\">[<\/span><span style=\"color: #c678dd;\">]<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">accumulate_bit<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\"> <span style=\"color: #e06c75;\">@position<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/span><\/p><p>    <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">+=<\/span> <span style=\"color: #d19a66;\">1<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">8<\/span> <span style=\"color: #7f848e;\"># Byte is complete<\/span>\n<\/p><p>      <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #e06c75;\">@accumulator<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">zero?<\/span> <span style=\"color: #7f848e;\"># Message complete - NULL terminator<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">decoded<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e06c75;\">@buffer<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">pack<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">\"<\/span><span style=\"color: #98c379;\">C*<\/span><span style=\"color: #98c379;\">\"<\/span><span style=\"color: #c678dd;\">)<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">force_encoding<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">UTF-8<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>        <span style=\"color: #c678dd;\">yield<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">decoded<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #c678dd;\">if<\/span> <span style=\"color: #61afef;\">block_given?<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">@buffer<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">clear<\/span>\n<\/p><p>      <span style=\"color: #c678dd;\">else<\/span> \n<\/p><p>        <span style=\"color: #e06c75;\">@buffer<\/span> <span style=\"color: #56b6c2;\"> <span style=\"color: #e06c75;\">@accumulator<\/span>\n<\/span><\/p><p>      <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>      <span style=\"color: #e06c75;\">@position<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p>      <span style=\"color: #e06c75;\">@accumulator<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #d19a66;\">0<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">def<\/span> <span style=\"color: #61afef;\">send_message<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>    <span style=\"color: #e06c75;\">message<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">each_byte<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">byte<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>      <span style=\"color: #d19a66;\">8<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">times<\/span> <span style=\"color: #c678dd;\">do<\/span> <span style=\"color: #c678dd;\">|<\/span><span style=\"color: #e06c75;\">i<\/span><span style=\"color: #c678dd;\">|<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">byte<\/span> <span style=\"color: #56b6c2;\">&gt;&gt;<\/span> <span style=\"color: #e06c75;\">i<\/span><span style=\"color: #c678dd;\">)<\/span> <span style=\"color: #56b6c2;\">&amp;<\/span> <span style=\"color: #d19a66;\">1<\/span>\n<\/p><p>        <span style=\"color: #e06c75;\">signal<\/span> <span style=\"color: #56b6c2;\">=<\/span> <span style=\"color: #e06c75;\">bit<\/span> <span style=\"color: #56b6c2;\">==<\/span> <span style=\"color: #d19a66;\">0<\/span> <span style=\"color: #56b6c2;\">?<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span> <span style=\"color: #56b6c2;\">:<\/span> <span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR2<\/span><span style=\"color: #98c379;\">'<\/span>\n<\/p><p>        <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">kill<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #e06c75;\">signal<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>        <span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">SIGNAL_DELAY<\/span>\n<\/p><p>      <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>    <span style=\"color: #7f848e;\"># Send NULL terminator (0000 0000)<\/span>\n<\/p><p>    <span style=\"color: #d19a66;\">8<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #61afef;\">times<\/span> <span style=\"color: #c678dd;\">do<\/span>\n<\/p><p>      <span style=\"color: #e5c07b;\">Process<\/span><span style=\"color: #abb2bf;\">.<\/span><span style=\"color: #e06c75;\">kill<\/span><span style=\"color: #c678dd;\">(<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #98c379;\">SIGUSR1<\/span><span style=\"color: #98c379;\">'<\/span><span style=\"color: #abb2bf;\">,<\/span> <span style=\"color: #e06c75;\">pid<\/span><span style=\"color: #c678dd;\">)<\/span>\n<\/p><p>      <span style=\"color: #61afef;\">sleep<\/span> <span style=\"color: #d19a66;\">SIGNAL_DELAY<\/span>\n<\/p><p>    <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p>  <span style=\"color: #c678dd;\">end<\/span>\n<\/p><p><span style=\"color: #c678dd;\">end<\/span>\n<\/p><\/code><\/pre>\n<p>If you\u2019ve been following along, this shouldn\u2019t be hard to understand, but I\u2019ll break down how this beautiful piece of code works:<\/p>\n<ul>\n<li>The codec is initialized with the bit position at zero, as well as the accumulator<\/li>\n<li>A buffer is also initialized to store accumulated bits until a complete byte is formed<\/li>\n<li>The <code>accumulate_bit<\/code> method should be familiar from our earlier implementation, but it now accepts a closure (block) that lets the caller decide what to do with each decoded byte<\/li>\n<li><code>send_message<\/code> encodes a message into bits and sends them via UNIX signals<\/li>\n<\/ul>\n<p>Everything in action:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/leandronsp.com\/uploads\/3170.png\" alt=\"image\"\/><\/p>\n<p><em>How cool, amazing, wonderful, impressive, astonishing is that?<\/em><\/p>\n<h2><a target=\"_blank\" href=\"#conclusion\" aria-hidden=\"true\" class=\"anchor\" id=\"conclusion\"\/>Conclusion<\/h2>\n<p>Yes, we built a message broker using nothing but <strong>UNIX signals<\/strong> and a bit of Ruby magic. Sure, <strong>it\u2019s not production-ready<\/strong>, and you definitely shouldn\u2019t use this in your next startup (please don\u2019t), but that was never the point.<\/p>\n<p>The real takeaway here isn\u2019t the broker itself: it\u2019s understanding how the fundamentals work. We explored binary operations, UNIX signals, and IPC in a hands-on way that most people never bother with.<\/p>\n<p>We took something \u201cuseless\u201d and made it work, just for fun. So next time someone asks you about message brokers, you can casually mention that you once built (or saw) one using just two signals. And if they look at you weird, well, that\u2019s their problem. Now go build something equally useless and amazing. The world needs more hackers who experiment just for the fun of it.<\/p>\n<p><em>Happy hacking!<\/em><\/p>\n<\/p><\/div>\n\n<br \/><a href=\"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals\">\u5143\u306e\u8a18\u4e8b\u3092\u78ba\u8a8d\u3059\u308b <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"Have you ever asked yourself what if we could replace any message broker with a very simple one using only two [&hellip;]","protected":false},"author":1,"featured_media":10584,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-10583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hatena-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>You don&#039;t need Kafka: Building a message queue with only two UNIX signals - \u30dd\u30b1\u30b3\u30f3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals\" \/>\n<meta property=\"og:locale\" content=\"ja_JP\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"You don&#039;t need Kafka: Building a message queue with only two UNIX signals - \u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"og:description\" content=\"Have you ever asked yourself what if we could replace any message broker with a very simple one using only two [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals\" \/>\n<meta property=\"og:site_name\" content=\"\u30dd\u30b1\u30b3\u30f3\" \/>\n<meta property=\"article:published_time\" content=\"2025-10-22T20:31:37+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/3491.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1876\" \/>\n\t<meta property=\"og:image:height\" content=\"744\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"info@pokecon.jp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u57f7\u7b46\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"info@pokecon.jp\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593\" \/>\n\t<meta name=\"twitter:data2\" content=\"19\u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/10583\\\/\"},\"author\":{\"name\":\"info@pokecon.jp\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"headline\":\"You don&#8217;t need Kafka: Building a message queue with only two UNIX signals\",\"datePublished\":\"2025-10-22T20:31:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/10583\\\/\"},\"wordCount\":2330,\"image\":{\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/3491.png\",\"articleSection\":[\"\u306f\u3066\u306a\u30d6\u30ed\u30b0\"],\"inLanguage\":\"ja\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/10583\\\/\",\"url\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals\",\"name\":\"You don't need Kafka: Building a message queue with only two UNIX signals - \u30dd\u30b1\u30b3\u30f3\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/3491.png\",\"datePublished\":\"2025-10-22T20:31:37+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#breadcrumb\"},\"inLanguage\":\"ja\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/3491.png\",\"contentUrl\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/wp-content\\\/uploads\\\/2025\\\/10\\\/3491.png\",\"width\":1876,\"height\":744},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/leandronsp.com\\\/articles\\\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u30db\u30fc\u30e0\",\"item\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"You don&#8217;t need Kafka: Building a message queue with only two UNIX signals\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#website\",\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/\",\"name\":\"\u30dd\u30b1\u30b3\u30f3\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ja\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/#\\\/schema\\\/person\\\/16c9f07b1ba984d165d9aee259bda997\",\"name\":\"info@pokecon.jp\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ja\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g\",\"caption\":\"info@pokecon.jp\"},\"url\":\"https:\\\/\\\/pokecon.jp\\\/job\\\/author\\\/infopokecon-jp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"You don't need Kafka: Building a message queue with only two UNIX signals - \u30dd\u30b1\u30b3\u30f3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals","og_locale":"ja_JP","og_type":"article","og_title":"You don't need Kafka: Building a message queue with only two UNIX signals - \u30dd\u30b1\u30b3\u30f3","og_description":"Have you ever asked yourself what if we could replace any message broker with a very simple one using only two [&hellip;]","og_url":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals","og_site_name":"\u30dd\u30b1\u30b3\u30f3","article_published_time":"2025-10-22T20:31:37+00:00","og_image":[{"width":1876,"height":744,"url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/3491.png","type":"image\/png"}],"author":"info@pokecon.jp","twitter_card":"summary_large_image","twitter_misc":{"\u57f7\u7b46\u8005":"info@pokecon.jp","\u63a8\u5b9a\u8aad\u307f\u53d6\u308a\u6642\u9593":"19\u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#article","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/10583\/"},"author":{"name":"info@pokecon.jp","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"headline":"You don&#8217;t need Kafka: Building a message queue with only two UNIX signals","datePublished":"2025-10-22T20:31:37+00:00","mainEntityOfPage":{"@id":"https:\/\/pokecon.jp\/job\/10583\/"},"wordCount":2330,"image":{"@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/3491.png","articleSection":["\u306f\u3066\u306a\u30d6\u30ed\u30b0"],"inLanguage":"ja"},{"@type":"WebPage","@id":"https:\/\/pokecon.jp\/job\/10583\/","url":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals","name":"You don't need Kafka: Building a message queue with only two UNIX signals - \u30dd\u30b1\u30b3\u30f3","isPartOf":{"@id":"https:\/\/pokecon.jp\/job\/#website"},"primaryImageOfPage":{"@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage"},"image":{"@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage"},"thumbnailUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/3491.png","datePublished":"2025-10-22T20:31:37+00:00","author":{"@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997"},"breadcrumb":{"@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#breadcrumb"},"inLanguage":"ja","potentialAction":[{"@type":"ReadAction","target":["https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals"]}]},{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#primaryimage","url":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/3491.png","contentUrl":"https:\/\/pokecon.jp\/job\/wp-content\/uploads\/2025\/10\/3491.png","width":1876,"height":744},{"@type":"BreadcrumbList","@id":"https:\/\/leandronsp.com\/articles\/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u30db\u30fc\u30e0","item":"https:\/\/pokecon.jp\/job\/"},{"@type":"ListItem","position":2,"name":"You don&#8217;t need Kafka: Building a message queue with only two UNIX signals"}]},{"@type":"WebSite","@id":"https:\/\/pokecon.jp\/job\/#website","url":"https:\/\/pokecon.jp\/job\/","name":"\u30dd\u30b1\u30b3\u30f3","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/pokecon.jp\/job\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ja"},{"@type":"Person","@id":"https:\/\/pokecon.jp\/job\/#\/schema\/person\/16c9f07b1ba984d165d9aee259bda997","name":"info@pokecon.jp","image":{"@type":"ImageObject","inLanguage":"ja","@id":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2b0549cd9f7907c092ca5fbb283baf72337f235726e4b46fa39ec0b701ac2fe2?s=96&d=wavatar&r=g","caption":"info@pokecon.jp"},"url":"https:\/\/pokecon.jp\/job\/author\/infopokecon-jp\/"}]}},"_links":{"self":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/10583","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/comments?post=10583"}],"version-history":[{"count":1,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/10583\/revisions"}],"predecessor-version":[{"id":10585,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/posts\/10583\/revisions\/10585"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media\/10584"}],"wp:attachment":[{"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/media?parent=10583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/categories?post=10583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pokecon.jp\/job\/wp-json\/wp\/v2\/tags?post=10583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}