What’s a character file?
In UNIX-like systems, everything is treated as a file (unix-everything-is-a-file) and devices are also files. The OS, kernel, and devices interact through the file_operations structurewhich holds pointers to functions defined by the device driver.
UNIX has two types of device drivers:
- Character: “slow”, manages small amount of data, data is accessed sequentially, search is not common. eg: keyboard, mouse
- Block: “fast”, manages large amount of data, data is accessed in fixed-sized blocks, search is common. eg: hard drives, ram
When you $ls -la /dev/hda? /dev/ttyS? you will see the devices and their identifiers. The output shows a character file with a c and a block file with a b in the first column. Each device has a unique ID made up of two parts: major and minor numbers.
$ ls -la /dev/hda? /dev/ttyS?
brw-rw---- 1 root disk 3, 1 2004-09-18 14:51 /dev/hda1
brw-rw---- 1 root disk 3, 2 2004-09-18 14:51 /dev/hda2
crw-rw---- 1 root dialout 4, 64 2004-09-18 14:52 /dev/ttyS0
crw-rw---- 1 root dialout 4, 65 2004-09-18 14:52 /dev/ttyS1
From the example above the majors are: 3 (for hard disks) & 4 (for TTY devices). The minor are: 1,2,64,65. The major identifies the device driver, while the minor identifies a specific device instance managed by that driver. The full device list is here.
So how does this work?
Hardware devices are accessed by the user through special device files grouped in the /dev directory. The device driver is the software that handles the low-level interaction with the hardware.
When a system call is made (e.g.: open, read, write), the kernel looks up the devices’s inode (a data structure that stores file metadata) and finds the corresponding function via the file_operations structure within the device driver and calls that function.
For example, calling an open function from the OS:
- The kernel will identify the character device by looking up at the file’s metadata (inode)
- Use the major/minor numbers from the inode to find the exact device driver’s registration within the kernel
- Access the
file_operationsstructure that the driver provides. This structure acts as a bridge between the high-level system call and the low-level driver functions. - The kernel then calls the function pointed to by the
openfield in thefile_operationsstructure
References
https://www.linuxdoc.org/LDP/lkmpg/node14.html https://linux-kernel-labs.github.io/refs/heads/master/labs/device_drivers.html https://tldp.org/LDP/lkmpg/2.4/html/c577.htm https://www.kernel.org/doc/Documentation/admin-guide/devices.txt