The most exciting thing about this world is its ever changing quality.

Tuesday, June 30, 2009

/proc vs. /dev

/dev and /proc files are both means for user space programs to communicate with linux kernel but for different purposes.

/dev: file system for devices and stored in hard drive (not the same to DevFS which is also in RAM). (Static)
/proc: file system for processes stored in memory. /proc is an in-memory file system used to provide file based communication with the kernel. Also, to provide the user space applications the information about kernel, modules in the kernel sometimes create entries in /proc about their state information. Often, entries (files and directories) under /proc will refer to (or explain) files under /dev. /proc/devices lists all of the devices (divided into the "block" and "character" categories) available on the system. Any kernel component that wants to communicate with the user can create a file under the /proc and that can be used to exchange data. (Otherwise, it will have to create a system call.) (Dynamic) The sysctl command is another option for dynamic kernel configuration. Here is a good and simpler example of how to create and use entry defined in /proc from a loadable kernel module, and how the memory should be handled. In fact, /proc/devices will always provide you a list of available devices in the system (dynamically updated). This is often being used to create (mknod) /dev file automatically after loadable module is installed via insmod.

Interact with kernel processes

1. via /proc (with kernel): Processes can using files in /proc as media to communicate, between user space and kernel space. Parameters in /proc are used for tuning hardware and kernel internal settings. The reading and writing handlers are the channels for this communication to happen. They could be either blocking or non-blocking mode. This entry can be used by fread and fwrite from user space programs. User program <-> /proc <-> kernel components. /proc file can also be used for hardware configuration.

2. via /dev (with kernel): Processes access /dev file with the intention to issue I/O control or receive I/O data via read, write or mmap. Kernel will recognise these I/O requests and call requested device drivers (kernel modules), which will then communicate with the hardware. Compared with /proc, which could also be used to change hardware configuration, /dev files focus on using configured hardware device rather than configuring. User program <-> /dev/* <-> device driver <-> hardware I/O. Although there is not a one to one relationship between /dev file and hardware piece in the system (except network interface cards). When an user program accesses a /dev file, kernel recognise the device driver based on the /dev file major and minor number (the kernel module numer).
  • Major number identify the device driver and the minor number is used to identify one of the possible multiple devices managed by this device driver. The kernel uses the major number to redirect an I/O request to the appropriate driver, and the driver uses the minor number to figure out which specific device to access.
  • You can also access one device module from another kernel device module using try_module_get/module_put/symbol_get/symbol_put/symbol_request, for ensuring loading of the other module, and the fact that it is not unloaded during usage. As long as the functions in the first module has been exposed via EXPORT_SYMBOL (or EXPORT_SYMBOL_GPL) macros.
  • User space linux APIs applied on /dev files will invoke system calls which will then be passed to device drivers, if the operation is supported. The supported system calls are implemented as file operations, defined in file_operations structure within linux/fs.h , as a collection of function pointers, need to be implemented for device driver to be invoked correctly. There is a good analogy between available system calls applicable for a file and the file operations in the file_operations structure. (Am I just repeating myself? :))
  • Device driver is one type of kernel module. This means kernel module does not have to implement any of the file operations other than module_init and module_exit.
  • Of course the beloved ioctl provides all the freedom you need if you do not like any restriction as to the number of functions you want to implement.

On slightly different subject, some special /dev files also can be used solely for IPC between user space programs such as /dev/null, /dev/full, /dev/zero. Particularly, you can create named pipe using mkfifo, which will internally call mknod to create a special /dev file until explicitly deletion. Once created, /dev fifo file can be used for IPC communication between two processes no matter which spaces they live in. Fifo /dev file requires two parties to join the communication with support for both blocking and non-blocking mode accesses.

Implementation

1. /proc entry: to create an entry under /proc in your kernel module, use create_proc_entry().
  • Normally, there is only read_proc and write_proc for you to create a /proc entry in the kernel module.
2. /dev file: mknod or MAKEDEV or mkfifo to creates a FIFO (pipe), character special file, or block special file with the specified name. "special file" means something that can generate or receive data.
  • Unfortunately, you have to do this manually when you implement your own new device driver in the linux kernel. Of course you will also be responsible for the module major and minor number allocation although there are kernel APIs which can help you find available numbers. mknod -m permissions name type major minor
  • You can change the permission of /dev files after creation but need to be careful as you are opening a window to the underneath world!
  • To support a /dev file to access hardware devices, we need to implement device driver.

No comments: