fusd.tex 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012
  1. %
  2. %
  3. % FUSD - Framework for User-Space Devices
  4. % Programming Manual & Tutorial
  5. %
  6. % Jeremy Elson, (c) 2001 Sensoria Corporation, 2003 UCLA
  7. % Released under open-source, BSD license
  8. % See LICENSE file for full license
  9. %
  10. \documentclass{article}
  11. \addtolength{\topmargin}{-.5in} % repairing LaTeX's huge margins...
  12. \addtolength{\textheight}{1in} % more margin hacking
  13. \addtolength{\textwidth}{1.5in}
  14. \addtolength{\oddsidemargin}{-0.75in}
  15. \addtolength{\evensidemargin}{-0.75in}
  16. \usepackage{graphicx,float,alltt,tabularx}
  17. \usepackage{wrapfig,floatflt}
  18. \usepackage{amsmath}
  19. \usepackage{latexsym}
  20. \usepackage{moreverb}
  21. \usepackage{times}
  22. \usepackage{html}
  23. %\usepackage{draftcopy}
  24. %\setcounter{bottomnumber}{3}
  25. %\renewcommand{\topfraction}{0}
  26. %\renewcommand{\bottomfraction}{0.7}
  27. %\renewcommand{\textfraction}{0}
  28. %\renewcommand{\floatpagefraction}{2.0}
  29. \renewcommand{\topfraction}{1.0}
  30. \renewcommand{\bottomfraction}{1.0}
  31. \renewcommand{\textfraction}{0.0}
  32. \renewcommand{\floatpagefraction}{0.9}
  33. \floatstyle{ruled}
  34. \newfloat{Program}{tp}{lop}
  35. \title{FUSD:
  36. A Linux {\bf F}ramework for {\bf U}ser-{\bf S}pace {\bf D}evices}
  37. \author{Jeremy Elson\\
  38. jelson@circlemud.org\\
  39. http://www.circlemud.org/\tilde{}jelson/software/fusd}
  40. \date{19 August 2003, Documentation for FUSD 1.10}
  41. \begin{document}
  42. %%%%%%%%%%%%%%%%%%%%%%%%% Title Page %%%%%%%%%%%%%%%%%%%%%%%%%
  43. \begin{center}
  44. \begin{latexonly}\vspace*{2in}\end{latexonly}
  45. {\Huge FUSD:} \\
  46. \vspace{2\baselineskip}
  47. {\huge A Linux {\bf F}ramework for {\bf U}ser-{\bf S}pace {\bf D}evices}
  48. \begin{latexonly}\vspace{2in}\end{latexonly}
  49. \vspace{\baselineskip}
  50. \vfill
  51. {\large Jeremy Elson \\
  52. \begin{latexonly}\vspace{.5\baselineskip}\end{latexonly}}
  53. \vspace{\baselineskip}
  54. {\tt jelson@circlemud.org\\
  55. http://www.circlemud.org/jelson/software/fusd}
  56. \vspace{2\baselineskip}
  57. 19 August 2003\\
  58. Documentation for FUSD 1.10\\
  59. \end{center}
  60. \thispagestyle{empty}
  61. \clearpage
  62. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  63. \begin{latexonly}
  64. \pagenumbering{roman}
  65. \tableofcontents
  66. \bigskip
  67. \listof{Program}{List of Example Programs}
  68. \setlength{\parskip}{10pt}
  69. \clearpage
  70. \end{latexonly}
  71. % This resets the page counter to 1
  72. \pagenumbering{arabic}
  73. \addtolength{\parskip}{0.5\baselineskip}
  74. \section{Introduction}
  75. \subsection{What is FUSD?}
  76. FUSD (pronounced {\em fused}) is a Linux framework for proxying device
  77. file callbacks into user-space, allowing device files to be
  78. implemented by daemons instead of kernel code. Despite being
  79. implemented in user-space, FUSD devices can look and act just like any
  80. other file under /dev which is implemented by kernel callbacks.
  81. A user-space device driver can do many of the things that kernel
  82. drivers can't, such as perform a long-running computation, block while
  83. waiting for an event, or read files from the file system. Unlike
  84. kernel drivers, a user-space device driver can {\em use other device
  85. drivers}---that is, access the network, talk to a serial port, get
  86. interactive input from the user, pop up GUI windows, or read from
  87. disks. User-space drivers implemented using FUSD can be much easier
  88. to debug; it is impossible for them to crash the machine, are easily
  89. traceable using tools such as {\tt gdb}, and can be killed and
  90. restarted without rebooting even if they become corrupted. FUSD
  91. drivers don't have to be in C---Perl, Python, or any other language
  92. that knows how to read from and write to a file descriptor can work
  93. with FUSD. User-space drivers can be swapped out, whereas kernel
  94. drivers lock physical memory.
  95. Of course, as with almost everything, there are trade-offs.
  96. User-space drivers are slower than kernel drivers because they require
  97. three times as many system calls, and additional memory copies (see
  98. section~\ref{performance}). User-space drivers can not receive
  99. interrupts, and do not have the full power to modify arbitrary kernel
  100. data structures as kernel drivers do. Despite these limitations, we
  101. have found user-space device drivers to be a powerful programming
  102. paradigm with a wide variety of uses (see Section~\ref{use-cases}).
  103. FUSD is free software, distributed under a GPL-compatible license (the
  104. ``new'' BSD license, with the advertising clause removed).
  105. \subsection{How does FUSD work?}
  106. FUSD drivers are conceptually similar to kernel drivers: a set of
  107. callback functions called in response to system calls made on file
  108. descriptors by user programs. FUSD's C library provides a device
  109. registration function, similar to the kernel's {\tt
  110. devfs\_register\_chrdev()} function, to create new devices. {\tt
  111. fusd\_register()} accepts the device name and a structure full of
  112. pointers. Those pointers are callback functions which are called in
  113. response to certain user system calls---for example, when a process
  114. tries to open, close, read from, or write to the device file. The
  115. callback functions should conform to the standard definitions of POSIX
  116. system call behavior. In many ways, the user-space FUSD callback
  117. functions are identical to their kernel counterparts.
  118. Perhaps the best way to show what FUSD does is by example.
  119. Program~\ref{helloworld.c} is a simple FUSD device driver. When the
  120. program is run, a device called {\tt /dev/hello-world} appears under
  121. the {\tt /dev} directory. If that device is read (e.g., using {\tt
  122. cat}), the read returns {\tt Hello, world!} followed by an EOF.
  123. Finally, when the driver is stopped (e.g., by hitting Control-C), the
  124. device file disappears.
  125. \begin{Program}
  126. \listinginput[5]{1}{helloworld.c.example}
  127. \caption{helloworld.c: A simple program using FUSD to
  128. create {\tt /dev/hello-world}}
  129. \label{helloworld.c}
  130. \end{Program}
  131. On line 40 of the source, we use {\tt fusd\_register()} to create the
  132. {\tt /dev/hello-world} device, passing pointers to callbacks for the
  133. open(), close() and read() system calls. (Lines 36--39 use the GNU C
  134. extension that allows initializer field naming; the 2.4 series of
  135. Linux kernels use also that extension for the same purpose.) The
  136. ``Hello, World'' read() callback itself is virtually identical to what
  137. a kernel driver for this device would look like. It can inspect and
  138. modify the user's file pointer, copy data into the user-provided
  139. buffer, control the system call return value (either positive, EOF, or
  140. error), and so forth.
  141. The proxying of kernel system calls that makes this kind of program
  142. possible is implemented by FUSD, using a combination of a kernel
  143. module and cooperating user-space library. The kernel module
  144. implements a character device, {\tt /dev/fusd}, which is used as a
  145. control channel between the two. fusd\_register() uses this channel
  146. to send a message to the FUSD kernel module, telling the name of the
  147. device the user wants to register. The kernel module, in turn,
  148. registers that device with the kernel proper using devfs. devfs and
  149. the kernel don't know anything unusual is happening; it appears from
  150. their point of view that the registered devices are simply being
  151. implemented by the FUSD module.
  152. Later, when kernel makes a callback due to a system call (e.g.\ when
  153. the character device file is opened or read), the FUSD kernel module's
  154. callback blocks the calling process, marshals the arguments of the
  155. callback into a message and sends it to user-space. Once there, the
  156. library half of FUSD unmarshals it and calls whatever user-space
  157. callback the FUSD driver passed to fusd\_register(). When that
  158. user-space callback returns a value, the process happens in reverse:
  159. the return value and its side-effects are marshaled by the library
  160. and sent to the kernel. The FUSD kernel module unmarshals this
  161. message, matches it up with a corresponding outstanding request, and
  162. completes the system call. The calling process is completely unaware
  163. of this trickery; it simply enters the kernel once, blocks, unblocks,
  164. and returns from the system call---just as it would for any other
  165. blocking call.
  166. One of the primary design goals of FUSD is {\em stability}. It should
  167. not be possible for a FUSD driver to corrupt or crash the kernel,
  168. either due to error or malice. Of course, a buggy driver itself may
  169. corrupt itself (e.g., due to a buffer overrun). However, strict error
  170. checking is implemented at the user-kernel boundary which should
  171. prevent drivers from corrupting the kernel or any other user-space
  172. process---including the errant driver's own clients, and other FUSD
  173. drivers.
  174. \subsection{What FUSD {\em Isn't}}
  175. FUSD looks similar to certain other Linux facilities that are already
  176. available. It also skirts near a few of the kernel's hot-button
  177. political issues. So, to avoid confusion, we present a list of
  178. things that FUSD is {\em not}.
  179. \begin{itemize}
  180. \item {\bf A FUSD driver is not a kernel module.} Kernel modules
  181. allow---well, modularity of kernel code. They let you insert and
  182. remove kernel modules dynamically after the kernel boots. However,
  183. once inserted, the kernel modules are actually part of the kernel
  184. proper. They run in the kernel's address space, with all the same
  185. privileges and restrictions that native kernel code does. A FUSD
  186. device driver, in contrast, is more similar to a daemon---a program
  187. that runs as a user-space process, with a process ID.
  188. \item {\bf FUSD is not, and doesn't replace, devfs.} When a FUSD
  189. driver registers a FUSD device, it automatically creates a device file
  190. in {\tt /dev}. However, FUSD is not a replacement for devfs---quite
  191. the contrary, FUSD creates those device files by {\em using} devfs.
  192. In a normal Linux system, only kernel modules proper---not user-space
  193. programs---can register with devfs (see above).
  194. \item {\bf FUSD is not UDI.} UDI, the \htmladdnormallinkfoot{Uniform
  195. Driver Interface}{http://www.projectudi.org}, aims to create a binary
  196. API for drivers that is uniform across operating systems. It's true
  197. that FUSD could conceivably be used for a similar purpose (inasmuch as
  198. it defines a system call messaging structure). However, this was not
  199. the goal of FUSD as much as an accidental side effect. We do not
  200. advocate publishing drivers in binary-only form, even though FUSD does
  201. make this possible in some cases.
  202. \item {\bf FUSD is not an attempt to turn Linux into a microkernel.}
  203. We aren't trying to port existing drivers into user-space for a
  204. variety of reasons (not the least of which is performance). We've
  205. used FUSD as a tool to write new drivers that are much easier from
  206. user-space than they would be in the kernel; see
  207. Section~\ref{use-cases} for use cases.
  208. \end{itemize}
  209. \subsection{Related Work}
  210. FUSD is a new implementation, but certainly not a new idea---the
  211. theory of its operation is the same as any microkernel operating
  212. system. A microkernel (roughly speaking) is one that implements only
  213. very basic resource protection and message passing in the kernel.
  214. Implementation of device drivers, file systems, network stacks, and so
  215. forth are relegated to userspace. Patrick Bridges maintains a list of
  216. such \htmladdnormallinkfoot{microkernel operating systems}{http://www.cs.arizona.edu/people/bridges/os/microkernel.html}.
  217. Also related is the idea of a user-space filesystem, which has been
  218. implemented in a number of contexts. Some examples include Klaus
  219. Schauser's \htmladdnormallinkfoot{UFO
  220. Project}{http://www.cs.ucsb.edu/projects/ufo/index.html} for Solaris,
  221. and Jeremy Fitzhardinge's (no longer maintained)
  222. \htmladdnormallinkfoot{UserFS}{http://www.goop.org/~jeremy/userfs/}
  223. for Linux 1.x. The \htmladdnormallinkfoot{UFO
  224. paper}{http://www.cs.ucsb.edu/projects/ufo/97-usenix-ufo.ps} is also
  225. notable because it has a good survey of similar projects that
  226. integrate user-space code with system calls.
  227. \subsection{Limitations and Future Work}
  228. In its current form, FUSD is useful and has proven to be quite
  229. stable---we use it in production systems. However, it does have some
  230. limitations that could benefit from the attention of developers.
  231. Contributions to correct any of these deficiencies are welcomed!
  232. (Many of these limitations will not make sense without having read the
  233. rest of the documentation first.)
  234. \begin{itemize}
  235. \item Currently, FUSD only supports implementation of character
  236. devices. Block devices and network devices are not supported yet.
  237. \item The kernel has 15 different callbacks in its {\tt
  238. file\_operations} structure. The current version of FUSD does not
  239. proxy some of the more obscure ones out to userspace.
  240. \item Currently, all system calls that FUSD understands are proxied
  241. from the FUSD kernel module to userspace. Only the userspace library
  242. knows which callbacks have actually been registered by the FUSD
  243. driver. For example, the kernel may proxy a write() system call to
  244. user-space even if the driver has not registered a write() callback
  245. with fusd\_register().
  246. fusd\_register() should, but currently does not, tell the kernel
  247. module which callbacks it wants to receive, per-device. This will be
  248. more efficient because it will prevent useless system calls for
  249. unsupported operations. In addition, it will lead to more logical and
  250. consistent behavior by allowing the kernel to use its default
  251. implementations of certain functions such as writev(), instead of
  252. being fooled into thinking the driver has an implementation of it in
  253. cases where it doesn't.
  254. \item It should be possible to write a FUSD library in any language
  255. that supports reads and writes on raw file descriptors. In the
  256. future, it might be possible to write FUSD device drivers in a variety
  257. of languages---Perl, Python, maybe even Java. However, the current
  258. implementation has only a C library.
  259. \item It's possible for drivers that use FUSD to deadlock---for
  260. example, if a driver tries to open itself. In this one case, FUSD
  261. returns {\tt -EDEADLOCK}. However, deadlock protection should be
  262. expanded to more general detection of cycles of arbitrary length.
  263. \item FUSD should provide a /proc interface that gives debugging and
  264. status information, and allows parameter tuning.
  265. \item FUSD was written with efficiency in mind, but a number of
  266. important optimizations have not yet been implemented. Specifically,
  267. we'd like to try to reduce the number of memory copies by using a
  268. buffer shared between user and kernel space to pass messages.
  269. \item FUSD currently requires devfs, which is used to dynamically
  270. create device files under {\tt /dev} when a FUSD driver registers
  271. itself. This is, perhaps, the most convenient and useful paradigm
  272. for FUSD. However, some users have asked if it's possible to use FUSD
  273. without devfs. This should be possible if FUSD drivers bind to device
  274. major numbers instead of device file names.
  275. \end{itemize}
  276. \subsection{Author Contact Information and Acknowledgments}
  277. The original version of FUSD was written by Jeremy Elson
  278. \htmladdnormallink{(jelson@circlemud.org)}{mailto:jelson@circlemud.org}
  279. and Lewis Girod at Sensoria Corporation.
  280. Sensoria no longer maintains public releases of FUSD, but the same
  281. authors have since forked the last public release and continue to
  282. maintain FUSD from the University of California, Los Angeles.
  283. If you have bug reports, patches, suggestions, or any other comments,
  284. please feel free to contact the authors.
  285. FUSD has two
  286. \htmladdnormallinkfoot{SourceForge}{http://www.sourceforge.net}-host
  287. mailing lists: a low-traffic list for announcements ({\tt fusd-announce})
  288. and a list for general discussion ({\tt fusd-devel}). Subscription
  289. information for both lists is available at the
  290. \htmladdnormallink{SourceForge's FUSD mailing list
  291. page}{http://sourceforge.net/mail/?group_id=36326}.
  292. For the latest releases and information about FUSD, please see the
  293. \htmladdnormallinkfoot{official FUSD home
  294. page}{http://www.circlemud.org/jelson/software/fusd}.
  295. \subsection{Licensing Information}
  296. FUSD is free software, distributed under a GPL-compatible license (the
  297. ``new'' BSD license, with the advertising clause removed). The
  298. license is enumerated in its entirety below.
  299. Copyright (c) 2001, Sensoria Corporation; (c) 2003 University of
  300. California, Los Angeles. All rights reserved.
  301. Redistribution and use in source and binary forms, with or without
  302. modification, are permitted provided that the following conditions are
  303. met:
  304. \begin{itemize}
  305. \item Redistributions of source code must retain the above copyright
  306. notice, this list of conditions and the following disclaimer.
  307. \item Redistributions in binary form must reproduce the above
  308. copyright notice, this list of conditions and the following disclaimer
  309. in the documentation and/or other materials provided with the
  310. distribution.
  311. \item Neither the names of Sensoria Corporation or UCLA, nor the
  312. names of other contributors may be used to endorse or promote products
  313. derived from this software without specific prior written permission.
  314. \end{itemize}
  315. THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  316. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  317. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  318. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
  319. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  320. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  321. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  322. BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  323. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  324. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  325. IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  326. \section{Why use FUSD?}
  327. \label{use-cases}
  328. One basic question about FUSD that one might ask is: what is it good
  329. for? Why use it? In this section, we describe some of the situations
  330. in which FUSD has been the solution for us.
  331. \subsection{Device Driver Layering}
  332. A problem that comes up frequently in modern operating systems is
  333. contention for a single resource by multiple competing processes. In
  334. UNIX, it's the job of a device driver to coordinate access to such
  335. resources. By accepting requests from user processes and (for
  336. example) queuing and serializing them, it becomes safe for processes
  337. that know nothing about each other to make requests in parallel to the
  338. same resource. Of course, kernel drivers do this job already, but
  339. they typically operate on top of hardware directly. However, kernel
  340. drivers can't easily be layered on top of {\em other device drivers}.
  341. For example, consider a device such as a modem that is connected to a
  342. host via a serial port. Let's say we want to implement a device
  343. driver that allows multiple users to dial the telephone (e.g., {\tt
  344. echo 1-310-555-1212 > /dev/phone-dialer}). Such a driver should be
  345. layered {\em on top of} the serial port driver---that is, it most
  346. likely wants to write to {\tt /dev/ttyS0}, not directly to the UART
  347. hardware itself.
  348. While it is possible to write to a logical file from within a kernel
  349. device driver, it is both tricky and considered bad practice. In the
  350. \htmladdnormallinkfoot{words of kernel hacker Dick Johnson}
  351. {http://www.uwsg.indiana.edu/hypermail/linux/kernel/0005.3/0061.html},
  352. ``You should never write a [kernel] module that requires reading or
  353. writing to any logical device. The kernel is the thing that translates
  354. physical I/O to logical I/O. Attempting to perform logical I/O in the
  355. kernel is effectively going backwards.''
  356. With FUSD, it's possible to layer device drivers because the driver is
  357. a user-space process, not a kernel module. A FUSD implementation of
  358. our hypothetical {\tt /dev/phone-dialer} can open {\tt /dev/ttyS0}
  359. just as any other process would.
  360. Typically, such layering is accomplished by system daemons. For
  361. example, the {\tt lpd} daemon manages printers at a high level. Since
  362. it is a user-space process, it can access the physical printer devices
  363. using kernel device drivers (for example, using printer or network
  364. drivers). There a number of advantages to using FUSD instead:
  365. \begin{itemize}
  366. \item Using FUSD, a daemon/driver can create a standard device file
  367. which is accessible by any program that knows how to use the POSIX
  368. system call interface. Some trickery is possible using named
  369. pipes and FIFOs, but quickly becomes difficult because of multiplexed
  370. writes from multiple processes.
  371. \item FUSD drivers receive the UID, GID, and process ID along with
  372. every file operation, allowing the same sorts of security policies to
  373. be implemented as would be possible with a real kernel driver. In
  374. contrast, writes to a named pipe, UDP, and so forth are ``anonymous.''
  375. \end{itemize}
  376. \subsection{Use of User-Space Libraries}
  377. Since a FUSD driver is just a regular user-space program, it can
  378. naturally use any of the enormous body of existing libraries that
  379. exist for almost any task. FUSD drivers can easily incorporate user
  380. interfaces, encryption, network protocols, threads, and almost
  381. anything else. In contrast, porting arbitrary C code into the kernel
  382. is difficult and usually a bad idea.
  383. \subsection{Driver Memory Protection}
  384. Since FUSD drivers run in their own process space, the rest of the
  385. system is protected from them. A buggy or malicious FUSD driver, at
  386. the very worst, can only corrupt itself. It's not possible for it to
  387. corrupt the kernel, other FUSD drivers, or even the processes that are
  388. using its devices. In contrast, a buggy kernel module can bring down
  389. any process in the system, or the entire kernel itself.
  390. \subsection{Giving libraries language independence and standard
  391. notification interfaces}
  392. One particularly interesting application of FUSD that we've found very
  393. useful is as a way to let regular user-space libraries export device
  394. file APIs. For example, imagine you had a library which factored
  395. large composite numbers. Typically, it might have a C
  396. interface---say, a function called {\tt int\ *factorize(int\ bignum)}.
  397. With FUSD, it's possible to create a device file interface---say, a
  398. device called {\tt /dev/factorize} to which clients can {\tt write(2)}
  399. a big number, then {\tt read(2)} back its factors.
  400. This may sound strange, but device file APIs have at least three
  401. advantages over a typical library API. First, it becomes much more
  402. language independent---any language that can make system calls can
  403. access the factorization library. Second, the factorization code is
  404. running in a different address space; if it crashes, it won't crash or
  405. corrupt the caller. Third, and most interestingly, it is possible to
  406. use {\tt select(2)} to wait for the factorization to complete. {\tt
  407. select(2)} would make it easy for a client to factor a large number
  408. while remaining responsive to {\em other} events that might happen in
  409. the meantime. In other words, FUSD allows normal user-space libraries
  410. to integrate seamlessly with UNIX's existing, POSIX-standard event
  411. notification interface: {\tt select(2)}.
  412. \subsection{Development and Debugging Convenience}
  413. FUSD processes can be developed and debugged with all the normal
  414. user-space tools. Buggy drivers won't crash the system, but instead
  415. dump cores that can be analyzed. All of your favorite visual
  416. debuggers, memory bounds checkers, leak detectors, profilers, and
  417. other tools can be applied to FUSD drivers as they would to any other
  418. program.
  419. \section{Installing FUSD}
  420. This section describes the installation procedure for FUSD. It
  421. assumes a good working knowledge of Linux system administration.
  422. \subsection{Prerequisites}
  423. Before installing FUSD, make sure you have all of the following
  424. packages installed and working correctly:
  425. \begin{itemize}
  426. \item {\bf Linux kernel 2.4.0 or later}. FUSD was developed under
  427. 2.4.0 and should work with any kernel in the 2.4 series.
  428. \item {\bf devfs installed and running.} FUSD dynamically registers
  429. devices using devfs, the Linux device filesystem by Richard Gooch.
  430. For FUSD to work, devfs must be installed and running on your system.
  431. For more information about devfs installation, see the
  432. \htmladdnormallinkfoot{devfs home
  433. page}{http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.html}.
  434. Note that some distributions make installation devfs easier. RedHat
  435. 7.1, for example, already has all of the necessary daemons and
  436. configuration changes integrated. devfs can be installed simply by
  437. recompiling the kernel with devfs support enabled and reconfiguring
  438. LILO to pass {\tt "devfs=mount"} to the kernel.
  439. \end{itemize}
  440. \subsection{Compiling FUSD as a Kernel Module}
  441. Before compiling anything, take a look at the Makefile in FUSD's home
  442. directory. Adjust any constants that are not correct. In particular,
  443. make sure {\tt KERNEL\_HOME} correctly reflects the place where your
  444. kernel sources are installed, if they aren't in the default location
  445. of {\tt /usr/src/linux}.
  446. Then, type {\tt make}. It should generate a directory whose name
  447. looks something like {\tt obj.i686-linux}, or some variation depending
  448. on your architecture. Inside of that directory will be a number of
  449. files, including:
  450. \begin{itemize}
  451. \item kfusd.o -- The FUSD kernel module
  452. \item libfusd.a -- The C library used to talk to the kernel module
  453. \item Example programs -- linked against libfusd.a
  454. \end{itemize}
  455. Compilation of the kernel module will fail if the dependencies
  456. described in the previous section are not satisfied. The module must
  457. be compiled again Linux kernel must be v2.4.0 or later, and the kernel
  458. must have devfs support enabled.
  459. \subsection{Testing and Troubleshooting}
  460. Once everything has been compiled, give it a try to see if it actually
  461. does something. First, use {\tt insmod} to insert the FUSD kernel
  462. module, e.g. {\tt insmod obj.i686-linux/kfusd.o}. A greeting message
  463. similar to ``{\tt fusd: starting, Revision: 1.50}'' should appear in
  464. the kernel log (accessed using the {\tt dmesg} command, or by typing
  465. {\tt cat /proc/kmsg}). You can verify the module has been inserted by
  466. typing {\tt lsmod}, or alternatively {\tt cat /proc/modules}.
  467. Once the module has been inserted successfully, trying running the
  468. {\tt helloworld} example program. When run, the program should print
  469. a greeting message similar to {\tt /dev/hello-world should now exist -
  470. calling fusd\_run}. This means everything is working; the daemon is
  471. now blocked, waiting for requests to the new device. From another
  472. shell, type {\tt cat /dev/hello-world}. You should see {\tt Hello,
  473. world!} printed in response. Try killing the test program; the
  474. corresponding device file should disappear.
  475. If nothing seems to be working, try looking at the kernel message log
  476. (type {\tt dmesg} or {\tt cat /proc/kmsg}) to see if there are any
  477. errors. If nothing seems obviously wrong, try turning on FUSD kernel
  478. module debugging by defining {\tt CONFIG\_FUSD\_DEBUG} in kfusd.c,
  479. then recompiling and reinserting the module.
  480. \subsection{Installation}
  481. Typing {\tt make install} will copy the FUSD library, header files,
  482. and man pages into {\tt /usr/local}. The FUSD kernel module is {\em
  483. not} installed automatically because of variations among different
  484. Linux distributions in how this is accomplished. You may want to
  485. arrange to have the module start automatically on boot by (for
  486. example) copying it into {\tt /lib/modules/your-kernel-version}, and
  487. adding it to {\tt /etc/modules.conf}.
  488. \subsection{Making FUSD Part of the Kernel Proper}
  489. The earlier instructions, by default, create a FUSD kernel module.
  490. If desired, it's also very easy to build FUSD right into the kernel,
  491. instead:
  492. \begin{enumerate}
  493. \item Unpack the 2.4 kernel sources and copy all the files in the {\tt
  494. include} and {\tt kfusd} directories into your kernel source tree,
  495. under {\tt drivers/char}. For example, if FUSD is in
  496. your home directory, and your kernel is in {\tt /usr/src/linux}:
  497. \begin{verbatim}
  498. cp ~/fusd/kfusd/* ~/fusd/include/* /usr/src/linux/drivers/char
  499. \end{verbatim}
  500. \item Apply the patch found in FUSD's {\tt patches} directory to your
  501. kernel source tree. For example:
  502. \begin{verbatim}
  503. cd /usr/src/linux
  504. patch -p0 < ~/fusd/patches/fusd-inkernel.patch
  505. \end{verbatim}
  506. The FUSD in-kernel patch doesn't actually change any kernel sources
  507. proper; it just adds FUSD to the kernel configuration menu and
  508. Makefile.
  509. \item Using your kernel configurator of choice (e.g. {\tt make
  510. menuconfig}), turn on the FUSD options. It will be under the
  511. ``Character devices'' menu.
  512. \item Build and install the kernel as usual.
  513. \end{enumerate}
  514. \section{Basic Device Creation}
  515. Enough introduction---it's time to actually create a basic device
  516. driver using FUSD!
  517. This following sections will illustrate various techniques using
  518. example programs. To save space, interesting excerpts are shown
  519. instead of entire programs. However, the {\tt examples} directory
  520. of the FUSD distribution contains all the examples in their
  521. entirety. They can actually be compiled and run on a system with the
  522. FUSD kernel module installed.
  523. Where this text refers to example program line numbers, it refers to
  524. the line numbers printed alongside the excerpts in the manual---not
  525. the line numbers of the actual programs in the {\tt examples}
  526. directory.
  527. \subsection{Using {\tt fusd\_register} to create a new device}
  528. \label{using-fusd-register}
  529. We saw an example of a simple driver, helloworld.c, in
  530. Program~\ref{helloworld.c} on page~\pageref{helloworld.c}. Let's go
  531. back and examine that program now in more detail.
  532. The FUSD ball starts rolling when the {\tt fusd\_register} function is
  533. called, as shown on line 40. This function tells the FUSD kernel
  534. module:
  535. \begin{itemize}
  536. \item {\tt char *name}---The name of the device being created. The
  537. prefix (such as {\tt /dev/}) must match the location where devfs has
  538. been mounted. Names containing slashes (e.g., {\tt
  539. /dev/my-devices/dev1}) are legal; devfs creates subdirectories
  540. automatically.
  541. \item {\tt mode\_t mode}---The device's default permissions. This is
  542. usually specified using an octal constant with a leading 0---{\tt 0666}
  543. (readable and writable by everyone) instead of the incorrect decimal
  544. constant {\tt 666}.
  545. \item {\tt void *device\_info}---Private data that should be passed to
  546. callback functions for this device. The use of this field is
  547. described in Section~\ref{device-info}.
  548. \item {\tt struct fusd\_file\_operations *fops}---A structure containing
  549. pointers to the callback functions that should be called by FUSD
  550. in response to certain events.
  551. \end{itemize}
  552. If device registration is successful, {\tt fusd\_register} returns a
  553. {\em device handle}---a small integer $\ge0$. On errors, it returns
  554. -1 and sets the global variable {\tt errno} appropriately. In
  555. reality, the device handle you get is a plain old file descriptor,
  556. as we'll see in Section~\ref{selecting}.
  557. Although Program~\ref{helloworld.c} only calls {\tt fusd\_register}
  558. once, it can be called multiple times if the FUSD driver is handling
  559. more than one device as we'll see in Program~\ref{drums.c}.
  560. There is intentional similarity between {\tt fusd\_register()} and the
  561. kernel's device registration functions, such as {\tt
  562. devfs\_register()} and {\tt register\_chrdev()}. In many ways, FUSD's
  563. interface is meant to mirror the kernel interface as closely as
  564. possible.
  565. The {\tt fusd\_file\_operations} structure, defined in {\tt fusd.h},
  566. contains a list of callbacks that are used in response to different
  567. system calls executed on a file. It is similar to the kernel's {\tt
  568. file\_operations} structure, accepting callbacks for system calls such
  569. as {\tt open()}, {\tt close()}, {\tt read()}, {\tt write()}, and {\tt
  570. ioctl()}. For the most part, the prototypes of FUSD file operation
  571. callbacks are the same as their kernel cousins, with one important
  572. exception. The first argument of FUSD callbacks is always a pointer
  573. to a {\tt fusd\_file\_info} structure; it contains information that
  574. can be used to identify the file. This structure is used instead of
  575. the kernel's {\tt file} and {\tt inode} structures, and will be
  576. described in more detail later.
  577. In lines 35--38 of Program~\ref{helloworld.c}, we create and
  578. initialize a {\tt fusd\_file\_operations} structure. A GCC-specific C
  579. extension allows us to name structure fields explicitly in the
  580. initializer. This style may look strange, but it guards against
  581. errors in the future in case the order of fields in the structure ever
  582. changes. The 2.4 kernel series uses the same trick.
  583. After calling {\tt fusd\_register()} on line 40, the example program
  584. calls {\tt fusd\_run()} on line 44. This function turns control over
  585. to the FUSD framework. fusd\_run blocks the driver until one of the
  586. devices it registered needs to be serviced. Then, it calls the
  587. appropriate callback and blocks again until the next event.
  588. Now, imagine that a user types {\tt cat /dev/hello-world}. What
  589. happens? Recall first what the {\tt cat} program itself does: opens a
  590. file, reads from it until it receives an EOF (printing whatever it
  591. reads to stdout), then closes it. {\tt cat} works the same way
  592. regardless of what it's reading---be it a a FUSD device, a regular
  593. file, a serial port, or anything else. The {\tt strace} program is a
  594. great way to see this in action; see Appendix~\ref{strace} for
  595. details.
  596. \subsection{The {\tt open} and {\tt close} callbacks}
  597. \label{open-close}
  598. The first two callbacks that most drivers typically implement are {\tt
  599. open} and {\tt close}. Each of these two functions are passed just
  600. one argument---the {\tt fusd\_file\_info} structure that describes the
  601. instance of the file being opened or closed. Use of the information
  602. in that structure will be covered in more detail in
  603. Section~\ref{fusd-file-info}.
  604. The semantics of an {\tt open} callback's return value are exactly the
  605. same as inside the kernel:
  606. \begin{itemize}
  607. \item 0 means success, and the file is opened. If the file is allowed
  608. to open, the kernel returns a valid file descriptor to the client.
  609. Using that descriptor, other callbacks may be called for that file,
  610. including (at least) a {\tt close} callback.
  611. \item A negative number indicates a failure, and that the file should
  612. not be opened. Such return values should {\em always} be the
  613. specified as a negative {\tt errno} value such as {\tt -EPERM}, {\tt
  614. -EBUSY}, {\tt -ENODEV}, {\tt -ENOMEM}, and so on. For example, if the
  615. callback returns {\tt -EPERM}, the caller's {\tt open()} will return
  616. -1, with {\tt errno} set to {\tt EPERM}. A complete list of possible
  617. return values can be found in the Linux kernel sources, under {\tt
  618. include/asm/errno.h}.
  619. \end{itemize}
  620. If an {\tt open} callback returns 0 (success), a driver is {\em
  621. guaranteed} to receive exactly one {\tt close} callback for that file
  622. later. By the same token, the close callback {\em will not} be called
  623. if the open fails. Therefore, {\tt open} callbacks that can return
  624. failure must be sure to deallocate any resources they might have
  625. allocated before returning a failure.
  626. Let's return to our example in Program~\ref{helloworld.c}, which
  627. creates the {\tt /dev/hello-world} device. If a user types {\tt cat
  628. /dev/hello-world}, {\tt cat} will will use the {\tt open(2)} system
  629. call to open the file. FUSD will then proxy that system call to the
  630. driver and activate the callback that was registered as the {\tt open}
  631. callback. Recall from line 36 of Program~\ref{helloworld.c} that we
  632. registered {\tt do\_open\_or\_close}, which appears on line 8.
  633. In {\tt helloworld.c}, the {\tt open} callback always returns 0, or
  634. success. However, in a real driver, something more interesting will
  635. probably happen---permissions checks, memory allocation for
  636. state-keeping, and so forth. The corresponding {\em de}-allocation of
  637. those resources should occur in the {\tt close} callback, which is
  638. called when a user application calls {\tt close} on their file
  639. descriptor. {\tt close} callbacks are allowed to return error values,
  640. but this does not prevent the file from actually closing.
  641. \subsection{The {\tt read} callback}
  642. \label{read-callback}
  643. Returning to our {\tt cat /dev/hello-world} example, what happens
  644. after the {\tt open} is successful? Next, {\tt cat} will try to use
  645. {\tt read(2)}, which will get proxied by FUSD to the function {\tt
  646. do\_read} on line 13. This function takes some additional arguments
  647. that we didn't see in the open and close callbacks:
  648. \begin{itemize}
  649. \item {\tt struct fusd\_file\_info *file}---The first argument to all
  650. callbacks, containing information which describes the file; see
  651. Section~\ref{fusd-file-info}.
  652. \item {\tt char *user\_buffer}---The buffer that the callback should use to
  653. write data that it is returning to the user.
  654. \item {\tt size\_t user\_length}---The maximum number of bytes
  655. requested by the user. The driver is allowed to return fewer bytes,
  656. but should never write more then {\tt user\_length} bytes into {\tt
  657. user\_buffer}.
  658. \item {\tt loff\_t *offset}---A pointer to an integer which represents
  659. the caller's offset into the file (i.e., the user's file pointer).
  660. This value can be modified by the callback; any change will be
  661. propagated back to the user's file pointer inside the kernel.
  662. \end{itemize}
  663. The semantics of the return value are the same as if the
  664. callback were being written inside the kernel itself:
  665. \begin{itemize}
  666. \item Positive return values indicate success. If the call is
  667. successful, and the driver has copied data into {\tt buffer}, the
  668. return value indicates how many bytes were copied. This number should
  669. never be greater than the {\tt user\_length} argument.
  670. \item A 0 return value indicates EOF has been reached on the file.
  671. \item As in the {\tt open} and {\tt close} callbacks, negative values
  672. (such as -EPERM, -EPIPE, or -ENOMEM) indicate errors. Such values will
  673. cause the user's {\tt read()} to return -1 with errno set
  674. appropriately.
  675. \end{itemize}
  676. The first time a read is done on a device file, the user's file
  677. pointer ({\tt *offset}) is 0. In the case of this first read, a
  678. greeting message of {\tt Hello, world!} is copied back to the user, as
  679. seen on line 24. The user's file pointer is then advanced. The next
  680. read therefore fails the comparison at line 20, falling straight
  681. through to return 0, or EOF.
  682. In this simple program, we also see an example of an error return on
  683. line 22: if the user tries to do a read smaller than the length of the
  684. greeting message, the read will fail with -EINVAL. (In an actual
  685. driver, it would normally not be an error for a user to provide a
  686. smaller read buffer than the size of the available data. The right
  687. way for drivers to handle this situation is to return partial data,
  688. then move {\tt *offset} forward so that the remainder is returned on
  689. the next {\tt read()}. We see an example of this in
  690. Program~\ref{echo.c}.)
  691. \subsection{The {\tt write} callback}
  692. Program~\ref{helloworld.c} illustrated how a driver could return data
  693. {\em to} a client using the {\tt read} callback. As you might expect, there
  694. is a corresponding {\tt write} callback that allows the driver to
  695. receive data {\em from} a client. {\tt write} takes four arguments,
  696. similar to the {\tt read} callback:
  697. \begin{itemize}
  698. \item {\tt struct fusd\_file\_info *file}---The first argument to all
  699. callbacks, containing information which describes the file; see
  700. Section~\ref{fusd-file-info}.
  701. \item {\tt const char *user\_buffer}---Pointer to data being written
  702. by the client (read-only).
  703. \item {\tt size\_t user\_length}---The number of bytes pointed to by
  704. {\tt user\_buffer}.
  705. \item {\tt loff\_t *offset}---A pointer to an integer which represents
  706. the caller's offset into the file (i.e., the user's file pointer).
  707. This value can be modified by the callback; any change will be
  708. propagated back to the user's file pointer inside the kernel.
  709. \end{itemize}
  710. The semantics of {\tt write}'s return value are the same as in a
  711. kernel callback:
  712. \begin{itemize}
  713. \item Positive return values indicate success and indicate how many
  714. bytes of the user's buffer were successfully written (i.e.,
  715. successfully processed by the driver in some way). The return value
  716. may be less than or equal to the {\tt user\_length} argument, but
  717. should never be greater.
  718. \item 0 should only be returned in response to a {\tt write} of length
  719. 0.
  720. \item Negative values (such as -EPERM, -EPIPE, or -ENOMEM) indicate
  721. errors. Such values will cause the user's {\tt write()} to return -1
  722. with errno set appropriately.
  723. \end{itemize}
  724. Program~\ref{echo.c}, echo.c, is an example implementation of a device
  725. ({\tt /dev/echo}) that uses both {\tt read()} and {\tt write()}
  726. callbacks. A client that tries to {\tt read()} from this device will
  727. get the contents of the most recent {\tt write()}. For example:\\
  728. \begin{minipage}{\textwidth}
  729. \vspace{\baselineskip}
  730. \begin{verbatim}
  731. % echo Hello there > /dev/echo
  732. % cat /dev/echo
  733. Hello there
  734. % echo Device drivers are fun > /dev/echo
  735. % cat /dev/echo
  736. Device drivers are fun
  737. \end{verbatim}
  738. \end{minipage}
  739. \begin{Program}
  740. \listinginput[5]{1}{echo.c.example}
  741. \caption{echo.c: Using both {\tt read} and {\tt write} callbacks}
  742. \label{echo.c}
  743. \end{Program}
  744. The implementation of {\tt /dev/echo} keeps a global variable, {\tt
  745. data}, which serves as a cache for the data most recently written to
  746. the driver by a client program. The driver does not assume the data
  747. is null-terminated, so it also keeps track of the number of bytes of
  748. data available. (These two variables appear on lines 1--2.)
  749. The driver's {\tt write} callback first frees any data which might
  750. have been allocated by a previous call to write (lines 26--29). Next,
  751. on line 33, it attempts to allocate new memory for the new data
  752. arriving. If the allocation fails, {\tt -ENOMEM} is returned to the
  753. client. If the allocation is successful, the driver copies the data
  754. into its local buffer and stores its length (lines 37--38). Finally,
  755. the driver tells the user that the entire buffer was consumed by
  756. returning a value equal to the number of bytes the user tried to write
  757. ({\tt user\_length}).
  758. The {\tt read} callback has some extra features that we did not see in
  759. Program~\ref{helloworld.c}'s {\tt read()} callback. The most
  760. important is that it allows the driver to read the available data {\em
  761. incrementally}, instead of requiring that the first {\tt read()}
  762. executed by the client has enough space for all the data the driver
  763. has available. In other words, a client can do two 50-byte reads,
  764. and expect the same effect as if it had done a single 100-byte read.
  765. This is implemented using {\tt *offset}, the user's file pointer. If
  766. the user is trying to read past the amount of data we have available,
  767. the driver returns EOF (lines 8--9). Normally, this happens after the
  768. client has finished reading data. However, in this driver, it might
  769. happen on a client's first read if nothing has been written to the
  770. driver yet or if the most recent write's memory allocation failed.
  771. If there is data to return, the driver computes the number of bytes
  772. that should be copied back to the client---the minimum of the number
  773. of bytes the user asked for, and the number of bytes of data that this
  774. client hasn't seen yet (line 12). This data is copied back to the
  775. user's buffer (line 15), and the user's file pointer is advanced
  776. accordingly (line 16). Finally, on line 19, the client is told how
  777. many bytes were copied to its buffer.
  778. \subsection{Unregistering a device with {\tt fusd\_unregister()}}
  779. All devices registered by a driver are unregistered automatically when
  780. the program exits (or crashes). However, the {\tt fusd\_unregister()}
  781. function can be used to unregister a device without terminating the
  782. entire driver. {\tt fusd\_unregister} takes one argument: a device
  783. handle (i.e., the return value from {\tt fusd\_register()}).
  784. A device can be unregistered at any time. Any client system calls
  785. that are pending when a device is unregistered will return immediately
  786. with an error. In this case, {\tt errno} will be set to {\tt -EPIPE}.
  787. \section{Using Information in {\tt fusd\_file\_info}}
  788. \label{fusd-file-info}
  789. We mentioned in the previous sections that the first argument to every
  790. callback is a pointer to a {\tt fusd\_file\_info} structure. This
  791. structure contains information that can be useful to driver
  792. implementers in deciding how to respond to a system call request.
  793. The fields of {\tt fusd\_file\_info} structures fall into several
  794. categories:
  795. \begin{itemize}
  796. \item {\em Read-only.} The driver can inspect the value, but changing
  797. it will have no effect.
  798. \begin{itemize}
  799. \item {\tt pid\_t pid}: The process ID of the process making the
  800. request
  801. \item {\tt uid\_t uid}: The user ID of the owner of the process making
  802. the request
  803. \item {\tt gid\_t gid}: The group ID of the owner of the process making
  804. the request
  805. \end{itemize}
  806. \item {\em Read-write.} Any changes to the value will be propagated
  807. back to the kernel and be written to the appropriate in-kernel
  808. structure.
  809. \begin{itemize}
  810. \item {\tt unsigned int flags}: A copy of the {\tt f\_flags} field in
  811. the kernel's {\tt file} structure. The flags are an or'd-together set
  812. of the kernel's {\tt O\_} series of flags: {\tt O\_NONBLOCK}, {\tt
  813. O\_APPEND}, {\tt O\_SYNC}, etc.
  814. \item {\tt void *device\_info}: The data passed to {\tt
  815. fusd\_register} when the device was registered; see
  816. Section~\ref{device-info} for details
  817. \item {\tt void *private\_data}: A generic per-file-descriptor pointer
  818. usable by the driver for its own purposes, such as to keep state (or a
  819. pointer to state) that should be maintained between operations on the
  820. same instance of an open file. It is guaranteed to be NULL when the
  821. file is first opened. See Section~\ref{private-data} for more
  822. details.
  823. \end{itemize}
  824. \item {\em Hidden fields.} The driver should not touch these fields
  825. (such as {\tt fd}). They contain state used by the FUSD library to
  826. generate the reply sent to the kernel.
  827. \end{itemize}
  828. {\bf Important note:} the value of the {\tt fusd\_file\_info} pointer
  829. itself has {\em no meaning}. Repeated requests on the same file
  830. descriptor {\em will not} generate callbacks with identical {\tt
  831. fusd\_file\_info} pointer values, as would be the case with an
  832. in-kernel driver. In other words, if a driver needs to keep state in
  833. between successive system calls on a user's file descriptor, it {\em
  834. must} store that state using the {\tt private\_data} field. The {\tt
  835. fusd\_file\_info} pointer itself is ephemeral; the data to which it
  836. points is persistent.
  837. Program~\ref{uid-filter.c} shows an example of how a driver might make
  838. use of the data in the {\tt fusd\_file\_info} structure. Much of the
  839. driver is identical to helloworld.c. However, instead of printing a
  840. static greeting, this new program generates a custom message each time
  841. the device file is read, as seen on line 25. The message contains the
  842. PID of the user process that requested the read ({\tt file->pid}).
  843. \begin{Program}
  844. \listinginput[5]{1}{uid-filter.c.example}
  845. \caption{uid-filter.c: Inspecting data in {\tt fusd\_file\_info} such
  846. as UID and PID of the calling process}
  847. \label{uid-filter.c}
  848. \end{Program}
  849. In addition, Program~\ref{uid-filter.c}'s {\tt open} callback does not
  850. return 0 (success) unconditionally as it did in
  851. Program~\ref{helloworld.c}. Instead, it checks (on line 7) to make
  852. sure the UID of the process trying to read from the device ({\tt
  853. file->uid}) matches the UID under which the driver itself is running
  854. ({\tt getuid()}). If they don't match, -EPERM is returned. In other
  855. words, only the user who ran the driver is allowed to read from the
  856. device that it creates. If any other user---including root!---tries
  857. to open it, a ``Permission denied'' error will be generated.
  858. \subsection{Registration of Multiple Devices, and Passing Data to Callbacks}
  859. \label{device-info}
  860. Device drivers frequently expose several different ``flavors'' of a
  861. device. For example, a single magnetic tape drive will often have
  862. many different device files in {\tt /dev}. Each device file
  863. represents a different combination of options such as
  864. rewind/no-rewind, or compressed/uncompressed. However, they access
  865. the same physical tape drive.
  866. Traditionally, the device file's {\em minor number} was used to
  867. communicate the desired options with device drivers. But, since devfs
  868. dynamically (and unpredictably) generates both major and minor numbers
  869. every time a device is registered, a different technique was
  870. developed. When using devfs, drivers are allowed to associate a value
  871. (of type {\tt void *}) with each device they register. This facility
  872. takes the place of the minor number.
  873. The devfs solution is also used by FUSD. The mysterious third
  874. argument to {\tt fusd\_register} that we mentioned in
  875. Section~\ref{using-fusd-register} is an arbitrary piece of data that
  876. can be passed to FUSD when a device is registered. Later, when a
  877. callback is activated, the contents of that argument are available in
  878. the {\tt device\_info} member of the {\tt fusd\_file\_info} structure.
  879. Program~\ref{drums.c} shows an example of this technique, inspired by
  880. Alessandro Rubini's similar devfs tutorial
  881. \htmladdnormallinkfoot{published in Linux
  882. Magazine}{http://www.linux.it/kerneldocs/devfs/}. It creates a number
  883. of devices in the {\tt /dev/drums} directory, each of which is useful
  884. for generating a different kind of ``sound''---{\tt /dev/drums/bam},
  885. {\tt /dev/drums/boom}, and so on. Reading from any of these devices
  886. will return a string equal to the device's name.
  887. \begin{Program}
  888. \listinginput[5]{1}{drums.c.example}
  889. \caption{drums.c: Passing private data to {\tt fusd\_register} and
  890. retrieving it from {\tt device\_info}}
  891. \label{drums.c}
  892. \end{Program}
  893. The first thing to notice about {\tt drums.c} is that it registers
  894. more than one FUSD device. In the loop starting in line 31, it calls
  895. {\tt fusd\_register()} once for every device named in {\tt
  896. drums\_strings} on line 1. When {\tt fusd\_run()} is called, it
  897. automatically watches every device the driver registered, and
  898. activates the callbacks associated with each device as needed.
  899. Although {\tt drums.c} uses the same set of callbacks for every device
  900. it registers (as can be seen on line 33), each device could have
  901. different callbacks if desired. (Not shown is the initialization of
  902. {\tt drums\_fops}, which assigns {\tt drums\_read} to be the {\tt
  903. read} callback.)
  904. If {\tt drums\_read} is called for all 6 types of drums, how does it
  905. know which device it's supposed to be servicing when it gets called?
  906. The answer is in the third argument of {\tt fusd\_register()}, which
  907. we were previously ignoring. Whatever value is passed to {\tt
  908. fusd\_register()} will be passed back to the callback in the {\tt
  909. device\_info} field of the {\tt fusd\_file\_info} structure. The name
  910. of the drum sound is passed to {\tt fusd\_register} on line 33, and
  911. later retrieved by the driver on line 12.
  912. Although this example uses a string as its {\tt device\_info}, the
  913. pointer can be used for anything---a mode number, a pointer to a
  914. configuration structure, and so on.
  915. \subsection{The difference between {\tt device\_info} and {\tt
  916. private\_data}}
  917. \label{private-data}
  918. As we mentioned in Section~\ref{fusd-file-info}, the {\tt
  919. fusd\_file\_info} structure has two seemingly similar fields, both of
  920. which can be used by drivers to store their own data: {\tt
  921. device\_info} and {\tt private\_data}. However, there is an important
  922. difference between them:
  923. \begin{itemize}
  924. \item {\tt private\_data} is stored {\em per file descriptor}. If 20
  925. processes open a FUSD device (or, one process opens a FUSD device 20
  926. times), each of those 20 file descriptors will have their own copy of
  927. {\tt private\_data} associated with them. This field is therefore
  928. useful to drivers that need to differentiate multiple requests to a
  929. single device that might be serviced in parallel. (Note that most
  930. UNIX variants, including Linux, do allow multiple processes to share a
  931. single file descriptor---specifically, if a process {\tt open}s a
  932. file, then {\tt fork}s. In this case, processes will also share a
  933. single copy of {\tt private\_data}.)
  934. The first time a FUSD driver sees {\tt private\_data} (in the {\tt
  935. open} callback), it is guaranteed to be NULL. Any changes to it by a
  936. driver callback will only affect the state associated with that single
  937. file descriptor.
  938. \item {\tt device\_info} is kept {\em per device}. That is, {\em all}
  939. clients of a device share a {\em single} copy of {\tt device\_info}.
  940. Unlike {\tt private\_data}, which is always initialized to NULL, {\tt
  941. device\_info} is always initialized to whatever value the driver
  942. passed to {\tt fusd\_register} as described in the previous section.
  943. If a callback changes the copy of {\tt device\_info} in the {\tt
  944. fusd\_file\_info} structure, this has no effect; {\tt device\_info}
  945. can only be set at registration time, with {\tt fusd\_register}.
  946. \end{itemize}
  947. In short, {\tt device\_info} is used to differentiate {\em devices}.
  948. {\tt private\_data} is used to differentiate {\em users of those
  949. devices}.
  950. Program~\ref{drums2.c}, drums2.c, illustrates the difference between
  951. {\tt device\_info} and {\tt private\_data}. Like the original
  952. drums.c, it creates a bunch of devices in {\tt /dev/drums/}, each of
  953. which ``plays'' a different sound. However, it also does something
  954. new: keeps track of how many times each device has been opened. Every
  955. read to any drum gives you the name of its sound as well as your
  956. unique ``user number''. And, instead of returning just a single line
  957. (as drums.c did), it will keep generating more ``sound'' every time a
  958. {\tt read()} system call arrives.
  959. \begin{Program}
  960. \listinginput[5]{1}{drums2.c.example}
  961. \caption{drums2.c: Using both {\tt device\_info} and {\tt private\_data}}
  962. \label{drums2.c}
  963. \end{Program}
  964. The trick is that we want to keep users separate from each other. For
  965. example, user one might type:\\
  966. \begin{minipage}{\textwidth}
  967. \vspace{\baselineskip}
  968. \begin{verbatim}
  969. % more /dev/drums/bam
  970. You are user 1 to hear a drum go 'bam'!
  971. You are user 1 to hear a drum go 'bam'!
  972. You are user 1 to hear a drum go 'bam'!
  973. ...
  974. \end{verbatim}
  975. \end{minipage}
  976. Meanwhile, another user in a different shell might type the same
  977. command at the same time, and get different results:\\
  978. \begin{minipage}{\textwidth}
  979. \vspace{\baselineskip}
  980. \begin{verbatim}
  981. % more /dev/drums/bam
  982. You are user 2 to hear a drum go 'bam'!
  983. You are user 2 to hear a drum go 'bam'!
  984. You are user 2 to hear a drum go 'bam'!
  985. ...
  986. \end{verbatim}
  987. \end{minipage}
  988. The idea is that no matter how long those two users go on reading
  989. their devices, the driver always generates a message that is specific
  990. to that user. The two users' data are not intermingled.
  991. To implement this, Program~\ref{drums2.c} introduces a new {\tt
  992. drum\_info} structure (lines 1-4), which keeps track of both the
  993. drum's name, and the number of time each drum device has been opened.
  994. An instance of this structure, {\tt drums}, is initialized on lines
  995. 4-8. Note that the call to {\tt fusd\_register} (line 45) now passes
  996. a pointer to a {\tt drum\_info} structure. (This {\tt drum\_info *}
  997. pointer is shared by every instance of a client that opens a
  998. particular type of drum.)
  999. Each time a drum device is opened, its {\tt drum\_info} structure is
  1000. retrieved from {\tt device\_info} (line 15). Then, on line 18, the
  1001. {\tt num\_users} field is incremented and the new user number is
  1002. stored in {\tt fusd\_file\_info}'s {\tt private\_data} field. To
  1003. reiterate our earlier point: {\em {\tt device\_info} contains
  1004. information global to all users of a device, while {\tt private\_data}
  1005. has information specific to a particular user of the device.}
  1006. It's also worthwhile to note that when we increment {\tt num\_users}
  1007. on line 18, a simple {\tt num\_users++} is correct. If this was a
  1008. driver inside the kernel, we'd have to use something like {\tt
  1009. atomic\_inc()} because a plain {\tt i++} is not atomic. Such a
  1010. non-atomic statement will result in a race condition on SMP platforms,
  1011. if an interrupt handler also touches {\tt num\_users}, or in some
  1012. future Linux kernel that is preemptive. Since this FUSD driver is
  1013. just a plain, single-threaded user-space application, good old {\tt
  1014. ++} still works.
  1015. \section{Writing {\tt ioctl} Callbacks}
  1016. The POSIX API provides for a function called {\tt ioctl}, which allows
  1017. ``out-of-band'' configuration information to be passed to a device
  1018. driver through a file descriptor. Using FUSD, you can write a device
  1019. driver with a callback to handle {\tt ioctl} requests from clients.
  1020. For the most part, it's just like writing a callback for {\tt read} or
  1021. {\tt write}, as we've seen in previous sections. From the client's
  1022. point of view, {\tt ioctl} traditionally takes three arguments: a file
  1023. descriptor, a command number, and a pointer to any additional data
  1024. that might be required for the command.
  1025. \subsection{Using macros to generate {\tt ioctl} command numbers}
  1026. The Linux header file {\tt /usr/include/asm/ioctl.h} defines macros
  1027. that {\em must} be used to create the {\tt ioctl} command number.
  1028. These macros take various combinations of three arguments:
  1029. \begin{itemize}
  1030. \item {\tt type}---an 8-bit integer selected to be specific to the
  1031. device driver. {\tt type} should be chosen so as not to conflict with
  1032. other drivers that might be ``listening'' to the same file descriptor.
  1033. (Inside the kernel, for example, the TCP and IP stacks use distinct
  1034. numbers since an {\tt ioctl} sent to a socket file descriptor might be
  1035. examined by both stacks.)
  1036. \item {\tt number}---an 8-bit integer ``command number.'' Within a
  1037. driver, distinct numbers should be chosen for each different kind of
  1038. {\tt ioctl} command that the driver services.
  1039. \item {\tt data\_type}---The name of a type used to compute how many
  1040. bytes are exchanged between the client and the driver. This argument
  1041. is, for example, the name of a structure.
  1042. \end{itemize}
  1043. The macros used to generate command numbers are:
  1044. \begin{itemize}
  1045. \item {\tt \_IO(int type, int number)} -- used for a simple ioctl that
  1046. sends nothing but the type and number, and receives back nothing but
  1047. an (integer) retval.
  1048. \item {\tt \_IOR(int type, int number, data\_type)} -- used for an
  1049. ioctl that reads data {\em from} the device driver. The driver will
  1050. be allowed to return {\tt sizeof(data\_type)} bytes to the user.
  1051. \item {\tt \_IOW(int type, int number, data\_type)} -- similar to
  1052. \_IOR, but used to write data {\em to} the driver.
  1053. \item {\tt \_IORW(int type, int number, data\_type)} -- a combination
  1054. of {\tt \_IOR} and {\tt \_IOW}. That is, data is both written to the
  1055. driver and then read back from the driver by the client.
  1056. \end{itemize}
  1057. \begin{Program}
  1058. \listinginput[5]{1}{ioctl.h.example}
  1059. \caption{ioctl.h: Using the {\tt \_IO} macros to generate {\tt ioctl}
  1060. command numbers}
  1061. \label{ioctl.h}
  1062. \end{Program}
  1063. Program~\ref{ioctl.h} is an example header file showing the use of
  1064. these macros. In real programs, the client executing an ioctl and the
  1065. driver that services it must share the same header file.
  1066. \subsection{Example client calls and driver callbacks}
  1067. Program~\ref{ioctl-client.c} shows a client program that executes {\tt
  1068. ioctl}s using the ioctl command numbers defined in
  1069. Program~\ref{ioctl.h}. The {\tt ioctl\_data\_t} is
  1070. application-specific; our simple test program defines it as a
  1071. structure containing two arrays of characters. The first {\tt ioctl}
  1072. call (line 10) sends the command {\tt IOCTL\_TEST3}, which retrieves
  1073. strings {\em from} the driver. The second {\tt ioctl} uses the
  1074. command {\tt IOCTL\_TEST4} (line 18), which sends strings {\em to} the
  1075. driver.
  1076. \begin{Program}
  1077. \listinginput[5]{1}{ioctl-client.c.example}
  1078. \caption{ioctl-client.c: A program that makes {\tt ioctl} requests on
  1079. a file descriptor}
  1080. \label{ioctl-client.c}
  1081. \end{Program}
  1082. The portion of the FUSD driver that services these calls is shown in
  1083. Program~\ref{ioctl-server.c}.
  1084. \begin{Program}
  1085. \listinginput[5]{1}{ioctl-server.c.example}
  1086. \caption{ioctl-server.c: A driver that handles {\tt ioctl} requests}
  1087. \label{ioctl-server.c}
  1088. \end{Program}
  1089. The ioctl example header file and test programs shown in this document
  1090. (Programs~\ref{ioctl.h}, \ref{ioctl-client.c}, and
  1091. \ref{ioctl-server.c}) are actually contained in a larger, single
  1092. example program included in the FUSD distribution called {\tt
  1093. ioctl.c}. That source code shows other variations on calling and
  1094. servicing {\tt ioctl} commands.
  1095. \section{Integrating FUSD With Your Application Using {\tt fusd\_dispatch()}}
  1096. \label{selecting}
  1097. The example applications we've seen so far have something in common:
  1098. after initialization and device registration, they call {\tt
  1099. fusd\_run()}. This gives up control of the program's flow, turning it
  1100. over to the FUSD library instead. This worked fine for our simple
  1101. example programs, but doesn't work in a real program that needs to
  1102. wait for events other than FUSD callbacks. For this reason, our
  1103. framework provides another way to activate callbacks that does not
  1104. require the driver to give up control of its {\tt main()}.
  1105. \subsection{Using {\tt fusd\_dispatch()}}
  1106. Recall from Section~\ref{using-fusd-register} that {\tt
  1107. fusd\_register} returns a {\em file descriptor} for every device that
  1108. is successfully registered. This file descriptor can be used to
  1109. activate device callbacks ``manually,'' without passing control of the
  1110. application to {\tt fusd\_run()}. Whenever the file descriptor
  1111. becomes readable according to {\tt select(2)}, it should be passed to
  1112. {\tt fusd\_dispatch()}, which in turn will activate callbacks in the
  1113. same way that {\tt fusd\_run()} does. In other words, an application
  1114. can:
  1115. \begin{enumerate}
  1116. \item Save the file descriptors returned by {\tt fusd\_register()};
  1117. \item Add those FUSD file descriptors to an {\tt fd\_set} that is
  1118. passed to {\tt select}, along with any other file
  1119. descriptors that might be interesting to the application; and
  1120. \item Pass every FUSD file descriptor that {\tt select} indicates is
  1121. readable to {\tt fusd\_dispatch}.
  1122. \end{enumerate}
  1123. {\tt fusd\_dispatch()} returns 0 if at least one callback was
  1124. successfully activated. On error, -1 is returned with {\tt errno} set
  1125. appropriately. {\tt fusd\_dispatch()} will never block---if no
  1126. messages are available from the kernel, it will return -1 with {\tt
  1127. errno} set to {\tt EAGAIN}.
  1128. \subsection{Helper Functions for Constructing an {\tt fd\_set}}
  1129. The FUSD library provides two (optional) utility functions that can
  1130. make it easier to write applications that integrate FUSD into their
  1131. own {\tt select()} loops. Specifically:
  1132. \begin{itemize}
  1133. \item {\tt void fusd\_fdset\_add(fd\_set *set, int *max)}---is meant
  1134. to help construct an {\tt fd\_set} that will be passed as the
  1135. ``readable fds'' set to select. This function adds the file
  1136. descriptors of all previously registered FUSD devices to the fd\_set
  1137. {\tt set}. It assumes that {\tt set} has already been initialized by
  1138. the caller. The integer {\tt max} is updated to reflect the largest
  1139. file descriptor number in the set. {\tt max} is not changed if the
  1140. value passed to {\tt fusd\_fdset\_add} is already larger than the
  1141. largest FUSD file descriptor added to the set.
  1142. \item {\tt void fusd\_dispatch\_fdset(fd\_set *set)}---is meant to be
  1143. called on the {\tt fd\_set} that is {\em returned} by select. It
  1144. assumes that {\tt set} contains a set file descriptors that {\tt
  1145. select()} has indicated are readable. {\tt fusd\_dispatch\_fdset()}
  1146. calls {\tt fusd\_dispatch} on every descriptor in {\tt set} that is a
  1147. valid FUSD descriptor. Non-FUSD descriptors in {\tt set} are
  1148. ignored.
  1149. \end{itemize}
  1150. \begin{Program}
  1151. \listinginput[5]{1}{drums3.c.example}
  1152. \caption{drums3.c: Waiting for both FUSD and non-FUSD events in a
  1153. {\tt select} loop}
  1154. \label{drums3.c}
  1155. \end{Program}
  1156. The excerpt of {\tt drums3.c} shown in Program~\ref{drums3.c}
  1157. demonstrates the use of these helper functions. This program is
  1158. similar to the earlier drums.c example: it creates a number of musical
  1159. instruments such as {\tt /dev/drums/bam} and {\tt /dev/drums/boom}.
  1160. However, in addition to servicing its musical callbacks, the driver
  1161. also prints a prompt to standard input asking how ``loud'' the drums
  1162. should be. Instead of turning control of {\tt main()} over to {\tt
  1163. fusd\_run()} as in the previous examples, {\tt drums3} uses {\tt
  1164. select()} to simultaneously watch its FUSD file descriptors and standard
  1165. input. It responds to input from both sources.
  1166. On lines 2--5, an {\tt fd\_set} and its associated ``max'' value are
  1167. initialized to contain stdin's file descriptor. On line 9, we use
  1168. {\tt fusd\_fdset\_add} to add the FUSD file descriptors for all
  1169. registered devices. (Not shown in this excerpt is the device
  1170. registration, which is the same as the registration code we saw in
  1171. {\tt drums.c}.) On line 13 we call select, which blocks until one of
  1172. the fd's in the set is readable. On lines 17 and 18, we check to see
  1173. if standard input is readable; if so, a function is called which reads
  1174. the user's response from standard input and prints a new prompt.
  1175. Finally, on line 21, we call {\tt fusd\_dispatch\_fdset}, which in
  1176. turn will activate the callbacks for devices that have pending system
  1177. calls waiting to be serviced.
  1178. It's worth reiterating that drivers are not required to use the FUSD
  1179. helper functions {\tt fusd\_fdset\_add} and {\tt
  1180. fusd\_dispatch\_fdset}. If it's more convenient, a driver can
  1181. manually save all of the file descriptors returned by {\tt
  1182. fusd\_register}, construct its own {\tt fd\_set}, and then call {\tt
  1183. fusd\_dispatch} on each descriptor that is readable. This method is
  1184. sometimes required for integration with other frameworks that want to
  1185. take over your {\tt main()}. For example, the
  1186. \htmladdnormallinkfoot{GTK user interface
  1187. framework}{http://www.gtk.org} is event-driven and requires that you
  1188. pass control of your {\tt main} to it. However, it does allow you to
  1189. give it a file descriptor and a function pointer, saying ``Call this
  1190. callback when {\tt select} indicates this file descriptor has become
  1191. readable.'' A GTK application that implements FUSD devices can work
  1192. by giving GTK all the FUSD file descriptors individually, and calling
  1193. {\tt fusd\_dispatch()} when GTK calls the associated callbacks.
  1194. \section{Implementing Blocking System Calls}
  1195. All of the example drivers that we've seen until now have had an
  1196. important feature missing: they never had to {\em wait} for anything.
  1197. So far, a driver's response to a system call has always been
  1198. immediately available---allowing the driver to response immediately.
  1199. However, real devices are often not that lucky: they usually have to
  1200. wait for something to happen before completing a client's system call.
  1201. For example, a driver might be waiting for data to arrive from the
  1202. serial port or over the network, or even waiting for a user action.
  1203. In situations like this, a basic capability most device drivers must
  1204. have is the ability to {\em block} the caller. Blocking operations
  1205. are important because they provide a simple interface to user programs
  1206. that does flow control, rather than something more expensive like
  1207. continuous polling. For example, user programs expect to be able to
  1208. execute a statement like {\tt read(fd, buf, sizeof(buf))}, and expect
  1209. the read call to block (stop the flow of the calling program) until
  1210. data is available. This is much simpler and more efficient than
  1211. polling repeatedly.
  1212. In the following sections, we'll describe how to block and unblock
  1213. system calls for devices that use FUSD.
  1214. \subsection{Blocking the caller by blocking the driver}
  1215. The easiest (but least useful) way to block a client's system call is
  1216. simply to block the driver, too. For example, consider
  1217. Program~\ref{console-read.c}, which implements a device called {\tt
  1218. /dev/console-read}. Whenever a process tries to read from this
  1219. device, the driver prints a prompt to standard input, asking for a
  1220. reply. (The prompt appears in the shell the driver was run in, not
  1221. the shell that's trying to read from the device.) When the user
  1222. enters a line of text, the response is returned to the client that did
  1223. the original {\tt read()}. By blocking the driver waiting for the
  1224. reply, the client that issued the system call is blocked as well.
  1225. \begin{Program}
  1226. \listinginput[5]{1}{console-read.c.example}
  1227. \caption{console-read.c: A simple blocking system call}
  1228. \label{console-read.c}
  1229. \end{Program}
  1230. Blocking the driver this way is safe---unlike programming in the
  1231. kernel proper, where doing something like this would block the entire
  1232. system. It's also easy to implement, as seen from the example above.
  1233. However, it makes the driver unresponsive to system call requests that
  1234. might be coming from other clients. If another process tries to do
  1235. anything at all with a blocked driver's device---even an {\tt
  1236. open()}---it will block until the driver wakes up again. This
  1237. limitation makes blocking drivers inappropriate for any device driver
  1238. that expects to service more than one client at a time.
  1239. \subsection{Blocking the caller using {\tt -FUSD\_NOREPLY};
  1240. unblocking it using {\tt fusd\_return()}}
  1241. \label{fusd-noreply}
  1242. If a device driver expects more than one client at a time---as is
  1243. often the case---a slightly different programming model is needed for
  1244. system calls that can potentially block. Instead of blocking, the
  1245. driver immediately sends a message to the FUSD framework that says, in
  1246. essence, ``Don't unblock the client that issued this system call, but
  1247. continue sending additional system call requests that might be coming
  1248. from other clients.'' Driver callbacks can send this message to FUSD
  1249. by returning the special value {\tt -FUSD\_NOREPLY} instead of a
  1250. normal system call return value.
  1251. Before a callback blocks the caller by returning {\tt -FUSD\_NOREPLY},
  1252. it must save the {\tt fusd\_file\_info} pointer that was provided to
  1253. the callback as its first argument. Later, when an event occurs which
  1254. allows the client's blocked system call to complete, the driver should
  1255. call {\tt fusd\_return()}, which will unblock the calling process and
  1256. complete its system call. {\tt fusd\_return()} takes two arguments:
  1257. \begin{itemize}
  1258. \item The {\tt fusd\_file\_info} pointer that the callback saved
  1259. earlier; and
  1260. \item The system call's return value (in other words, the value that
  1261. would have been returned by the callback function had it not returned
  1262. {\tt -FUSD\_NOREPLY}). FUSD itself {\em does not} examine the return
  1263. value passed as the second argument to {\tt fusd\_return}; it simply
  1264. propagates that value back to the kernel as the return value of the
  1265. blocked system call.
  1266. \end{itemize}
  1267. Drivers should never call {\tt fusd\_return} more than once on a
  1268. single {\tt fusd\_file\_info} pointer. Doing so will have undefined
  1269. results, similar to calling {\tt free()} twice on the same pointer.
  1270. It also bears repeating that a callback can call {\em either} call
  1271. fusd\_return() explicitly {\em or} return a normal return value (i.e.,
  1272. not {\tt -FUSD\_NOREPLY}), but not both.
  1273. {\tt -FUSD\_NOREPLY} and {\tt fusd\_return()} make it easy for a
  1274. driver to block a process, then unblock it later when data becomes
  1275. available. When the callback returns {\tt -FUSD\_NOREPLY}, the driver
  1276. is freed up to wait for other events, even though the process making
  1277. the system call is still blocked. The driver can then wait for
  1278. something to happen that unblocks the original caller---for example,
  1279. another FUSD event, data from a serial port, or data from the network.
  1280. (Recall from Section~\ref{selecting} that a FUSD driver can
  1281. simultaneously wait for both FUSD and non-FUSD events.)
  1282. FUSD includes an example program, {\tt pager.c}, which demonstrates
  1283. these techniques. The pager driver implements a simple notification
  1284. interface which lets any number of ``waiters'' wait for a signal from
  1285. a ``notifier.'' All the waiters wait by trying to read from {\tt
  1286. /dev/pager/notify}. Those reads will block until a notifier writes
  1287. the string {\tt page} to {\tt /dev/pager/input}. It's easy to try
  1288. the application out---run the driver, and then open three other
  1289. shells. In two of them, type {\tt cat /dev/pager/notify}. The reads
  1290. will block. Then, in the third shell, type {\tt echo page >
  1291. /dev/pager/input}---the other two shells should become unblocked.
  1292. Let's take a look at how this application is implemented, step by
  1293. step.
  1294. \subsubsection{Keeping Per-Client State}
  1295. The first thing to notice about {\tt pager.c} is that it keeps {\em
  1296. per-client state}. That is, for every file descriptor open to the
  1297. driver, a structure is allocated that has information relating to that
  1298. file descriptor. Previous driver examples were, for the most part,
  1299. {\em reactive}---they received requests, and immediately generated
  1300. responses. Since there was never more than one request outstanding,
  1301. there was no need to keep a list of them. The pager application is
  1302. the first one that must keep track of an arbitrary number of requests
  1303. that might be outstanding at the same time. The first excerpt of {\tt
  1304. pager.c}, which appears in Program~\ref{pager-open.c}, shows the code
  1305. which creates this per-client state. Lines 1--6 define a structure,
  1306. {\tt pager\_client}, which keeps all the information we need about
  1307. each client attached to the driver. The {\tt open} callback for {\tt
  1308. /dev/pager/notify}, shown on lines 12--31, allocates memory for an
  1309. instance of this structure and adds it to a linked list. (If the
  1310. memory allocation fails, an error is returned to the client on line
  1311. 18; this will prevent the file from opening.) Note on line 25 that we
  1312. use the {\tt private\_data} field to store a pointer to the client
  1313. state; this allows the structure to be retrieved when later callbacks
  1314. on this file descriptor arrive. The memory is deallocated when the
  1315. file is closed; we'll see that in a later section.
  1316. \begin{Program}
  1317. \listinginput[5]{1}{pager-open.c.example}
  1318. \caption{pager.c (Part 1): Creating state for every client using the
  1319. driver}
  1320. \label{pager-open.c}
  1321. \end{Program}
  1322. Another thing to notice about the open callback is the use of the {\tt
  1323. last\_page\_seen} variable. The driver gives a sequence number to
  1324. every page it receives; {\tt last\_page\_seen} stores the number of
  1325. the most recent page seen by a client. When a new client arrives
  1326. (i.e., it opens {\tt /dev/pager/notify}), its {\tt last\_page\_seen}
  1327. state is set equal to the page that has most recently arrived; this
  1328. forces a new client to wait for the {\em next} page, rather than
  1329. immediately being notified of a page that has arrived in the past.
  1330. \subsubsection{Blocking and completing reads}
  1331. The next part of {\tt pager.c} is shown in Program~\ref{pager-read.c}.
  1332. The {\tt pager\_notify\_read} function seen on line 1 is registered as
  1333. the {\tt read} callback for the {\tt /dev/pager/notify} device. It
  1334. blocks the read request using the technique we described earlier: it
  1335. stores the {\tt fusd\_file\_info} pointer in that client's state
  1336. structure, and returns {\tt -FUSD\_NOREPLY}. (Note that the pointer
  1337. to the client's state structure comes from the {\tt private\_data}
  1338. field of {\tt fusd\_file\_info}, where the open callback stored it.)
  1339. \begin{Program}
  1340. \listinginput[5]{1}{pager-read.c.example}
  1341. \caption{pager.c (Part 2): Block clients' {\tt read} requests, and later
  1342. completing the blocked reads}
  1343. \label{pager-read.c}
  1344. \end{Program}
  1345. {\tt pager\_notify\_complete\_read} {\em unblocks} previously blocked
  1346. reads. This function first checks to see that there is, in fact, a blocked
  1347. read (line 19). It then checks to see if a page has arrived that the
  1348. client hasn't seen yet (line 23). Finally, it updates the client
  1349. state and unblocks the blocked read by calling {\tt fusd\_return}.
  1350. Note the second argument to {\tt fusd\_return} is a 0; as we
  1351. saw in Section~\ref{read-callback}, a 0 return value to a {\tt read}
  1352. system call means EOF. (The system call will be unblocked regardless
  1353. of the return value.)
  1354. {\tt pager\_notify\_complete\_read} is called every time a new page
  1355. arrives. New pages are processed by {\tt pager\_input\_write} (line
  1356. 34), which is the {\tt write} callback for {\tt /dev/pager/input}.
  1357. After recording the fact that a new page has arrived, it calls {\tt
  1358. pager\_notify\_complete\_read} for each client that has an open file
  1359. descriptor. This will complete the reads of any clients who have not
  1360. yet seen this new data, and have no effect on clients that don't have
  1361. outstanding reads.
  1362. There is another interesting point to notice about {\tt
  1363. pager\_notify\_read}. On line 12, after it stores the blocked system
  1364. call's pointer, but before we return {\tt -FUSD\_NOREPLY}, it calls
  1365. the completion function. This has the effect of returning any data
  1366. that might already be available back to the caller immediately. If
  1367. that happens, we will end up calling {\tt fusd\_return} {\em before}
  1368. we return {\tt -FUSD\_NOREPLY}. This probably seems strange, but it's
  1369. legal. Recall that a callback can call fusd\_return() explicitly {\em
  1370. or} return a normal (not {\tt -FUSD\_NOREPLY}) return value, but not
  1371. both; the order doesn't matter.
  1372. \subsubsection{Using {\tt fusd\_destroy()} to clean up client state}
  1373. \label{fusd-destroy}
  1374. Finally, let's take a look at one last aspect of the pager program:
  1375. how it cleans up the per-client state when a client leaves. This is
  1376. mostly straightforward, with one exception: a client may have an
  1377. outstanding read request out when a close request comes in. Normally,
  1378. a client can't make another system call request while a previous
  1379. system call is still blocked. However, the {\tt close} system call is
  1380. an exception: it gets called when a client dies (for example, if it
  1381. receives an interrupt signal). If a {\tt close} comes in while
  1382. another system call is still outstanding, the state associated with
  1383. the outstanding request should be freed to avoid a memory leak. The
  1384. {\tt fusd\_destroy} function is used to do this, seen on linen 12-14
  1385. of Program~\ref{pager-close.c}.
  1386. \begin{Program}
  1387. \listinginput[5]{1}{pager-close.c.example}
  1388. \caption{pager.c (Part 3): Cleaning up when a client leaves}
  1389. \label{pager-close.c}
  1390. \end{Program}
  1391. \subsection{Retrieving a blocked system call's arguments from a {\tt
  1392. fusd\_file\_info} pointer}
  1393. \label{logring}
  1394. In the previous section, we showed how the {\tt fusd\_return} function
  1395. can be used to specify the return value of a system call that was
  1396. previously blocked. However, many system calls have side effects in
  1397. addition to returning a value---for example, in a {\tt read()}
  1398. request, the data being returned has to be copied into the caller's
  1399. buffer. To facilitate this, FUSD provides accessor functions that let
  1400. drivers retrieve the arguments that had been passed to its callbacks
  1401. at the time the call was originally issued. For example, the {\tt
  1402. fusd\_get\_read\_buffer()} function will return a pointer to the data
  1403. buffer that is provided with {\tt read()} callbacks. Drivers can use
  1404. these accessor functions to affect change to a client {\em before}
  1405. calling {\tt fusd\_return()}.
  1406. The following accessor functions are available, all of which take a
  1407. single {\tt fusd\_file\_info *} argument:
  1408. \begin{itemize}
  1409. \item {\tt int char *fusd\_get\_read\_buffer}---The destination buffer
  1410. for data that a driver is returning to a process doing a {\tt read()}.
  1411. \item {\tt const char *fusd\_get\_write\_buffer}---The source buffer
  1412. containing data sent to the driver by a process doing a {\tt write()}.
  1413. \item {\tt fusd\_get\_length}---The length (in bytes) of the buffer
  1414. for either a {\tt read()} or a {\tt write()}.
  1415. \item {\tt loff\_t fusd\_get\_offset}---The file descriptor's byte
  1416. offset, typically used in {\tt read()} and {\tt write()} callbacks.
  1417. \item {\tt int fusd\_get\_ioctl\_request}---An ioctl's request
  1418. ``command number'' (i.e., the first argument of an ioctl).
  1419. \item {\tt int fusd\_get\_ioctl\_arg}---The second argument of an
  1420. ioctl for non-data-bearing {\tt ioctl} requests (i.e., {\tt \_IO}
  1421. commands).
  1422. \item {\tt void *fusd\_get\_ioctl\_buffer}---The data buffer for
  1423. data-bearing {\tt ioctl} requests ({\tt \_IOR}, {\tt \_IOW}, and
  1424. {\tt \_IORW} commands).
  1425. \item {\tt int fusd\_get\_poll\_diff\_cached\_state}---See
  1426. Section~\ref{selectable}.
  1427. \end{itemize}
  1428. We got away without using these accessor functions in our {\tt
  1429. pager.c} example because the pager doesn't actually return data---it
  1430. just blocks and unblocks {\tt read} calls. However, the FUSD
  1431. distribution contains another example program, {\tt logring}, that
  1432. demonstrates their use.
  1433. {\tt logring} makes it easy to access the most recent (and only the most
  1434. recent) output from a process. It works just like {\tt tail -f} on a
  1435. log file, except that the storage required never grows. This can be
  1436. useful in embedded systems where there isn't enough memory or disk
  1437. space for keeping complete log files, but the most recent debugging
  1438. messages are sometimes needed (e.g., after an error is observed).
  1439. {\tt logring} uses FUSD to implement a character device, {\tt
  1440. /dev/logring}, that acts like a named pipe that has a finite, circular
  1441. buffer. The size of the buffer is given as a command-line argument.
  1442. As more data is written into the buffer, the oldest data is discarded.
  1443. A process that reads from the logring device will first read the
  1444. existing buffer, then block and see new data as it's written, similar
  1445. to monitoring a log file using {\tt tail -f}.
  1446. You can run this example program by typing {\tt logring <logsize>},
  1447. where {\tt logsize} is the size of the circular buffer in bytes.
  1448. Then, type {\tt cat /dev/logring} in a shell. The {\tt cat} process
  1449. will block, waiting for data. From another shell, write to the
  1450. logring (e.g., {\tt echo Hi there > /dev/logring}). The {\tt cat}
  1451. process will see the message appear.
  1452. (This example program is based on {\em emlog}, a (real) Linux kernel
  1453. module with identical functionality. If you find logring useful, but
  1454. want to use it on a system that does not have FUSD, check out the
  1455. original
  1456. \htmladdnormallinkfoot{emlog}{http://www.circlemud.org/jelson/software/emlog}.)
  1457. \section{Implementing {\tt select}able Devices}
  1458. \label{selectable}
  1459. One important feature that almost every device driver in a system
  1460. should have is support for the {\tt select(2)} system call. {\tt
  1461. select} allows clients to assemble a set of file descriptors and ask
  1462. to be notified when one of them becomes readable or writable. This
  1463. simple feature is deceptively powerful---it allows clients to wait for
  1464. any number of a set of possible events to occur. This is
  1465. fundamentally different than (for example) a blocking read, which only
  1466. unblocks on one kind of event. In this section, we'll describe how
  1467. FUSD can be used to create a device whose state can be queried by a
  1468. client's call to {\tt select(2)}.
  1469. This section is limited to a discussion what a FUSD driver writer
  1470. needs to know to implement a selectable device. Details of the FUSD
  1471. implementation required to support this feature are described in
  1472. Section~\ref{poll-diff-implementation}
  1473. \subsection{Poll state and the {\tt poll\_diff} callback}
  1474. FUSD's implementation of selectable devices depends on the concept of
  1475. {\em poll state}. A file descriptor's poll state is a bitmask that
  1476. describes its current properties---readable, writable, or exception
  1477. raised. These three states correspond to {\tt select(2)}'s three
  1478. {\tt fd\_set}s. FUSD has constants used to describe these states:
  1479. \begin{itemize}
  1480. \item {\tt FUSD\_NOTIFY\_INPUT}---Input is available; a read will not
  1481. block.
  1482. \item {\tt FUSD\_NOTIFY\_OUTPUT}---Output space is available; a write
  1483. will not block.
  1484. \item {\tt FUSD\_NOTIFY\_EXCEPT}---An exception has occurred.
  1485. \end{itemize}
  1486. These constants can be combined with C's bitwise-or operator. For
  1487. example, a descriptor that is both readable and writable is expressed
  1488. as {\tt FUSD\_NOTIFY\_INPUT | FUSD\_NOTIFY\_OUTPUT}. 0 means a file
  1489. descriptor is not readable, not writable, and not in the exception
  1490. set.
  1491. For a FUSD device to be selectable, its driver must implement a
  1492. callback called {\tt poll\_diff}. This callback is very different
  1493. than the others; it is not a ``direct line'' between the client and
  1494. the driver as is the case with a call such as {\tt ioctl}. A driver's
  1495. response to {\tt poll\_diff} is {\em not} the return value seen by a
  1496. client's call to {\tt select}. When a client tries to {\tt select} on
  1497. a set of file descriptors, the kernel collects the responses from all
  1498. the appropriate callbacks---{\tt poll} for file descriptors managed by
  1499. kernel drivers, and {\tt poll\_diff} callbacks those managed by FUSD
  1500. drivers---and synthesizes all of that information into the return
  1501. value seen by the client.
  1502. FUSD keeps a cache of the poll state it has most recently received
  1503. from each FUSD device driver, initially assumed to be 0. This state
  1504. is returned to clients trying to {\tt select()} on devices managed by
  1505. those drivers. Under certain conditions, FUSD sends a query to the
  1506. driver in order to ensure that the kernel's poll state cache is up to
  1507. date. This query takes the form of a {\tt poll\_diff} callback
  1508. activation, which is given a single argument: the poll state that FUSD
  1509. currently has cached. The driver should consult its internal data
  1510. structures to determine the actual, current poll state (i.e., whether
  1511. or not buffers have readable data). Then:
  1512. \begin{itemize}
  1513. \item If the FUSD cache is incorrect (that is, the current true poll
  1514. state is different than FUSD's cached state), the current poll state
  1515. should be returned immediately.
  1516. \item If the FUSD cache is up to date (that is, it matches the real
  1517. current state), the callback should save the {\tt fusd\_file\_info}
  1518. pointer and return {\tt -FUSD\_NOREPLY}. Later, when the poll
  1519. state changes, the driver can call {\tt fusd\_return()} to update
  1520. FUSD's cache.
  1521. \end{itemize}
  1522. In other words, when a driver's {\tt poll\_diff} callback is
  1523. activated, the kernel is effectively saying to the driver, ``Here is
  1524. what I think the current poll state of this file descriptor is; let me
  1525. know when that state {\em changes}.'' The driver can either respond
  1526. immediately (if the kernel's cache is already known to be out of
  1527. date), or return {\tt -FUSD\_NOREPLY} if no update is immediately
  1528. necessary. Later, when the poll state changes (for example, if new
  1529. data arrives that makes a device readable), the driver can used its
  1530. saved {\tt fusd\_file\_info} pointer to send a poll state update to
  1531. the kernel.
  1532. When a FUSD driver sends a poll state update, it might (or might not)
  1533. have the effect of waking up a client that was blocked in {\tt
  1534. select(2)}. On the same note, it's worth reiterating that a {\tt
  1535. -FUSD\_NOREPLY} response to a {\tt poll\_diff} callback {\em does not}
  1536. necessarily block the client---other descriptors in the client's {\tt
  1537. select} set might be readable, for example.
  1538. \subsection{Receiving a {\tt poll\_diff} request when the previous one
  1539. has not been returned yet}
  1540. \label{multiple-polldiffs}
  1541. Calls such as {\tt read} and {\tt write} are synchronous from the
  1542. standpoint of an individual client---a request is made, and the
  1543. requester blocks until a reply is received. This means that there
  1544. can't ever be more than a single {\tt read} request outstanding for a
  1545. single client at a time. (The driver as a whole may be keeping track
  1546. of many outstanding {\tt read} requests in parallel, but no two of them will
  1547. be from the same client file descriptor.)
  1548. As we mentioned in the previous section, the {\tt poll\_diff} callback
  1549. is different from other callbacks. It is not part of a synchronous
  1550. request/reply sequence that causes the client to block. It is also an
  1551. interface to the {\em kernel}, not directly to the client. So, it
  1552. {\em is} possible to receive a {\tt poll\_diff} request while there is
  1553. already one outstanding. This happens if the kernel's poll state
  1554. cache changes, causing it to notify the driver that it has a new
  1555. cached value.
  1556. This is easy to handle; the client should simply
  1557. \begin{enumerate}
  1558. \item Destroy the old (now out-of-date) {\tt poll\_diff} request
  1559. using the {\tt fusd\_destroy} function we saw in
  1560. Section~\ref{fusd-destroy}.
  1561. \item Either respond to or save the new {\tt poll\_diff} request,
  1562. exactly as described in the previous section.
  1563. \end{enumerate}
  1564. The next section will show an example of this technique.
  1565. \subsection{Adding {\tt select} support to {\tt pager.c}}
  1566. Given the explanation of {\tt poll\_diff} in the previous sections, it
  1567. might seem that implementing a selectable device is a daunting task.
  1568. It's actually not as bad as it sounds---the example code may well be
  1569. shorter than its explanation!
  1570. \begin{Program}
  1571. \listinginput[5]{1}{pager-polldiff.c.example}
  1572. \caption{pager.c (Part 4): Supporting {\tt select(2)} by implementing a
  1573. {\tt poll\_diff} callback}
  1574. \label{pager-polldiff.c}
  1575. \end{Program}
  1576. Program~\ref{pager-polldiff.c} shows the implementation of {\tt
  1577. poll\_diff} in {\tt pager.c}, which makes its notification interface
  1578. ({\tt /dev/pager/notify}) selectable. It is decomposed into a ``top
  1579. half'' and ``bottom half'' function, exactly as we did for the
  1580. blocking {\tt read} implementation in Program~\ref{pager-read.c}.
  1581. First, on lines 1--20, we see the the callback for {\tt poll\_diff}
  1582. callback itself. It is virtually identical to the {\tt read} callback
  1583. in Program~\ref{pager-read.c}. The main difference is that it first
  1584. checks (on line 12) to see if a {\tt poll\_diff} request is already
  1585. outstanding when a new request comes in. If so, the out-of-date
  1586. request is destroyed using {\tt fusd\_destroy}, as we described in
  1587. Section~\ref{multiple-polldiffs}.
  1588. The bottom half is shown on lines 22-46. First, on lines 32--35, it
  1589. computes the current poll state---if a page has arrived that the
  1590. client hasn't seen yet, the file is readable; otherwise, it isn't.
  1591. Next, the driver compares the current poll state with the poll state
  1592. that the kernel has cached. If the kernel's cache is out of date, the
  1593. current state is returned to the kernel. Otherwise, it does nothing.
  1594. As with the {\tt read} callback we saw previously, notice that {\tt
  1595. pager\_notify\_complete\_polldiff} is called in two different cases:
  1596. \begin{enumerate}
  1597. \item It is called immediately from the {\tt pager\_notify\_polldiff}
  1598. callback itself. This causes the current poll state to be returned to
  1599. the kernel immediately when the request arrives if the driver already
  1600. knows the kernel's state needs to be updated.
  1601. \item It is called when new data arrives that causes the poll state to
  1602. change. Refer back to Program~\ref{pager-read.c} on
  1603. page~\pageref{pager-read.c}; in the callback that receives new pages,
  1604. notice on line 45 that the {\tt poll\_diff} completion function is called
  1605. alongside the {\tt read} completion function.
  1606. \end{enumerate}
  1607. With this {\tt poll\_diff} implementation, it is possible for a client
  1608. to open {\tt /dev/pager/notify}, and block in a {\tt select(2)} system
  1609. call. If another client writes {\tt page} to {\tt /dev/pager/input},
  1610. the first client's {\tt select} will unblock, indicating the file has
  1611. become readable.
  1612. For additional example code, take a look at the {\tt logring} example
  1613. program we first mentioned in Section~\ref{logring}. It also supports
  1614. {\tt select} by implementing a similar {\tt poll\_diff} callback.
  1615. \section{Performance of User-Space Devices}
  1616. \label{performance}
  1617. This section hasn't been written yet. I have some pretty graphs and
  1618. whatnot, but no time to write about them here before the release.
  1619. \section{FUSD Implementation Notes}
  1620. In this section, we describe some of the details of how FUSD is
  1621. implemented. It's not necessary to understand these details in order
  1622. to use FUSD. However, these notes can be useful for people who are
  1623. trying to understand the FUSD framework itself---hackers, debuggers,
  1624. or the generally curious.
  1625. \subsection{The situation with {\tt poll\_diff}}
  1626. \label{poll-diff-implementation}
  1627. In-kernel device drivers support select by implementing a callback
  1628. called {\tt poll}. This driver's callback is supposed to do two
  1629. things. First, it should return the current state of a file
  1630. descriptor---a combination of being readable, writable, or having
  1631. exceptions. Second, it should provide a pointer to one of the
  1632. driver's internal wait queues that will be awakened whenever the state
  1633. changes. The {\tt poll} call itself should never block---it should
  1634. just instantaneously report what the {\em current} state is.
  1635. FUSD's implementation of selectable devices is different, but attempts
  1636. to maintain three properties that we thought to be most important from
  1637. the point of view of a client using {\tt select}. Specifically:
  1638. \begin{enumerate}
  1639. \item The {\tt select(2)} call itself should never become blocked.
  1640. For example, if one file descriptor in its set isn't readable, that
  1641. shouldn't prevent it from reporting other file descriptors that are.
  1642. \item If {\tt select(2)} indicates a file descriptor is readable (or
  1643. writable), a read (or write) on that file descriptor shouldn't block.
  1644. \item Clients should be allowed to seamlessly {\tt select} on any set
  1645. of file descriptors, even if that set contains a mix of both FUSD and
  1646. non-FUSD devices.
  1647. \end{enumerate}
  1648. The FUSD kernel module keeps a cache of the driver's most recent
  1649. answer for each file descriptor, initially assumed to be 0. When the
  1650. kernel module's internal {\tt poll} callback is activated, it:
  1651. \begin{enumerate}
  1652. \item Dispatches a {\em non-}blocking {\tt poll\_diff} to the
  1653. associated user-space driver, asking for a cache update---if and only
  1654. if there isn't already an outstanding poll diff request out that has
  1655. the same value.
  1656. \item Immediately returns the cached value to the kernel
  1657. \end{enumerate}
  1658. In addition, the cached value's readable bit is cleared on every read;
  1659. the writable bit is cleared on every write. This is necessary to
  1660. prevent old poll state---which says ``device is readable''---from
  1661. being returned out of the cache when it might be invalid. FUSD
  1662. assumes that any read to a device can make it potentially unreadable.
  1663. This mechanism is what causes an updated poll diff to be sent to a
  1664. client before the previous one has been returned.
  1665. (this section isn't finished yet; fancy time diagrams coming someday)
  1666. \subsection{Restartable System Calls}
  1667. No time to write this section yet...
  1668. \appendix
  1669. \section{Using {\tt strace}}
  1670. \label{strace}
  1671. This section hasn't been written yet. Contributions are welcome.
  1672. \end{document}