Using Devices¶
To use a device, we need to get a handle (i.e., a reference) on it that we will pass to every function applicable to it. See the code here.
This code reads a 64-bit word from the urandom
device that returns random data
and another from the zero
device that returns bytes set to 0. Finally, we
write a string into the null
device that discards what is written into it.
These three devices are virtual and are always available with Linux’s default
configuration.
Device Specific Interfaces
In the previous code example we have used read and write methods as if the
device handle had been a normal file handle. Indeed Linux device drivers define
the operational semantics they want to give to each system call applicable to a
file handle: read
, write
, fseek
, mmap
, close
, etc. Some
system calls may be invalid with some device handles (e.g., write
with the
urandom
driver).
This gives a weak unified interface to device drivers: the system calls are the
same but the operational semantics depends on the driver. Moreover there are a
lot of corner cases, such as system call parameters or flags only valid for some
drivers. Finally, as there aren’t enough “generic” system calls to cover the
whole spectrum of device features, the ioctl
system call is used to send
device specific commands to drivers. In practice you really have to know which
device driver you’re working with to ensure that you use appropriate system
calls.
To catch up as many errors at compile time as possible, in haskus-system
we
provide device specific interfaces that hide all this complexity. If you use
them, you minimise the risk of accidentally using an invalid system call. Some
of these interfaces are presented in the next chapters. Nevertheless you will
have to use the low-level interface presented in this chapter if you want to
write your own high-level interface to a device class not supported by
haskus-system
or if you want to extend an existing one.