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 ? </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>