s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

ftrig.html (7779B)


      1 <html>
      2   <head>
      3     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      5     <meta http-equiv="Content-Language" content="en" />
      6     <title>s6: libftrig</title>
      7     <meta name="Description" content="s6 libftrig" />
      8     <meta name="Keywords" content="s6 libftrig" />
      9     <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
     10   </head>
     11 <body>
     12 
     13 <p>
     14 <a href="index.html">s6</a><br />
     15 <a href="//skarnet.org/software/">Software</a><br />
     16 <a href="//skarnet.org/">skarnet.org</a>
     17 </p>
     18 
     19 <h1> libftrig </h1>
     20 
     21 <p>
     22 <tt>libftrig</tt> is a portable Unix C programming interface allowing a
     23 process (the <em>subscriber</em> or <em>listener</em>) to be instantly
     24 notified when another process (the <em>notifier</em> or <em>writer</em>)
     25 signals an event.
     26 </p>
     27 
     28 <a name="notification">
     29 <h2> What is notification&nbsp;? </h2>
     30 </a>
     31 
     32 <h3> Notification vs. polling </h3>
     33 
     34 <p>
     35  Process A is <em>notified</em> of an event E when it gets a instant
     36 notice that event E has happened; the notice may disrupt A's execution
     37 flow. Notification is the opposite of <em>polling</em>, where A has to
     38 periodically (every T milliseconds) check whether E happened and has no
     39 other way to be informed of it.
     40 </p>
     41 
     42 <p>
     43  Polling is generally considered bad practice - and is inferior to
     44 notification in practically every case - for three reasons:
     45 </p>
     46 
     47 <ul>
     48  <li> Reaction time. When event E happens, process A does not know it
     49 instantly. It will only learn of E, and be able to react to it, when
     50 it explicitly checks for E; and if E happened right after A performed
     51 the check, this can take as long as T milliseconds (the <em>polling
     52 period</em>). Polling processes have reaction delays due to the polling
     53 periods. </li>
     54  <li> Resource consumption. Even if <em>no</em> event ever happens, process A
     55 will still wake up needlessly every T milliseconds. This might not seem like
     56 a problem, but it is a serious one in energy-critical environments. Polling
     57 processes use more CPU time than is necessary and are not energy-friendly. </li>
     58  <li> Conflict between the two above reasons. The longer the polling period,
     59 the more energy-friendly the process, but the longer the reaction time. The
     60 shorter the polling period, the shorter the reaction time, but the more
     61 resource-consuming the process. A delicate balance has to be found, and
     62 acceptable behaviour is different in every case, so there's no general rule
     63 of optimization. </li>
     64 </ul>
     65 
     66 <p>
     67  Notification, on the other hand, is generally optimal: reaction time is
     68 zero, and resource consumption is minimal - a process can sleep as soon as
     69 it's not handling an event, and only wake up when needed.
     70 </p>
     71 
     72 <p>
     73  Of course, the problem of notification is that it's often more difficult
     74 to implement. Notification frameworks are generally more complex, involving
     75 lots of asynchronism; polling is widely used
     76 <a href="https://lib.store.yahoo.net/lib/demotivators/mediocritydemotivationalposter.jpg">because
     77 it's easy.</a>
     78 </p>
     79 
     80 <h3> Notifications and Unix </h3>
     81 
     82 <p>
     83  Unix provides several frameworks so that a process B (or the kernel) can
     84 notify process A.
     85 </p>
     86 
     87 <ul>
     88  <li> Signals. The simplest Unix notification mechanism. Sending events amounts
     89 to a <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html">kill()</a>
     90 call, and receiving events amounts to installing a signal handler (preferably
     91 using a <a href="//skarnet.org/software/skalibs/libstddjb/selfpipe.html">self-pipe</a>
     92 if mixing signals with an event loop). Unfortunately, Unix signals, even the more
     93 recent and powerful real-time POSIX signals, have important limitations when it's
     94 about generic notification:
     95  <ul>
     96   <li> non-root processes can only send signals to a very restricted and
     97 implementation-dependent set of processes (roughly, processes with the same UID). This is a problem when
     98 designing secure programs that make use of the Unix privilege separation. </li>
     99   <li> you need to know the PID of a process to send it signals. This is generally
    100 impractical; process management systems that do not use supervisor processes have
    101 to do exactly that, and they resort to unreliable, ugly hacks (.pid files) to track
    102 down process PIDs. </li>
    103  </ul> </li>
    104  <li> BSD-style IPCs, i.e. file descriptors to perform select()/poll() system
    105 calls on, in an <em>asynchronous event loop</em>. This mechanism is very widely used,
    106 and rightly so, because it's extremely generic and works in every ordinary situation;
    107 you have to be doing <a href="http://www.kegel.com/c10k.html">very specific stuff</a>
    108 to reach its limits. If process A is reading on
    109 fd <em>f</em>, it is notified everytime another process makes <em>f</em> readable -
    110 for instance by writing a byte to the other end if <em>f</em> is the reading end
    111 of a pipe. And indeed, this is how libftrig works internally; but libftrig is needed
    112 because direct use of BSD-style IPCs also has limitations.
    113  <ul>
    114   <li> Anonymous pipes are the simplest and most common BSD-style IPC. If there is a
    115 pipe from process B to process A, then B can notify A by writing to the pipe. The
    116 limitation is that A and B must have a common ancestor that created the pipe; two
    117 unrelated processes cannot communicate this way. </li>
    118  <li> Sockets are a good many-to-one notification system: once a server is up, it
    119 can be notified by any client, and notify all its clients. The limitation of sockets
    120 is that the server must be up before the client, which prevents us from using them
    121 in a general notification scheme. </li>
    122  </ul> </li>
    123  <li> System V IPCs, i.e. message queues and semaphores. The interfaces to those IPCs
    124 are quite specific and can't mix with select/poll loops, that's why nobody in their
    125 right mind uses them. </li>
    126 </ul>
    127 
    128 <h3> What we want </h3>
    129 
    130 <p>
    131  We need a general framework to:
    132 </p>
    133 
    134 <ul>
    135  <li> Allow an event-generating process to broadcast notifications to every process
    136 that asked for one, without having to know their PIDs </li>
    137  <li> Allow a process to subscribe to a "notification channel" and be instantly,
    138 asynchronously notified when an event occurs on this channel. </li>
    139 </ul>
    140 
    141 <p>
    142  This requires a many-to-many approach that Unix does not provide natively, and
    143 that is what libftrig does.
    144 </p>
    145 
    146 <a name="bus">
    147 <h2> That's what a bus is for. D-Bus already does all this. </h2>
    148 </a>
    149 
    150 <p>
    151  Yes, a bus is a good many-to-many notification mechanism indeed. However,
    152 a Unix bus can only be implemented via a daemon - you need a long-running
    153 process, i.e. a <em>service</em>, to implement a bus. And s6 is a
    154 <em>supervision suite</em>, i.e. a set of programs designed to manage
    155 services; we would like to be able to use notifications in the supervision
    156 suite, to be able to wait for a service to be up or down... <em>without</em>
    157 relying on a particular service to be up. libftrig provides a notification
    158 mechanism that <em>does not need</em> a bus service to be up, that's its
    159 main advantage over a bus.
    160 </p>
    161 
    162 <p>
    163  If you are not concerned with supervision and can depend on a bus service,
    164 though, then yes, by all means, use a bus for your notification needs.
    165 There is a <a href="//skarnet.org/software/skabus/">skabus</a>
    166 project in the making, which aims to be simpler, smaller and more
    167 maintainable than D-Bus.
    168 </p>
    169 
    170 <h2> How to use libftrig </h2>
    171 
    172 <p>
    173  <tt>libftrig</tt> is really a part of <a href="libs6/">libs6</a>: all the functions
    174 are implemented in the <tt>libs6.a</tt> archive, or the <tt>libs6.so</tt>
    175 dynamic shared object. However, the interfaces are different for notifiers
    176 and listeners:
    177 </p>
    178 
    179 <ul>
    180 <li> Notifiers use the <a href="libs6/ftrigw.html">ftrigw</a> interface. </li>
    181 <li> Listeners use the <a href="libs6/ftrigr.html">ftrigr</a> interface. </li>
    182 </ul>
    183 
    184 </body>
    185 </html>