Introduce the new method for chardev registration

Instead of using the old register_chrdev / unregister_chrdev API,
cdev interface which is newer and would be better for new driver programmers
in most cases. This commit is trying to give the brief overview for
this different interface.
This commit is contained in:
RinHizakura 2021-12-22 00:06:05 +08:00
parent e4016013b2
commit 2cc4264f72

View File

@ -896,6 +896,43 @@ First, the driver itself can print the newly assigned number and we can make the
Second, the newly registered device will have an entry in \verb|/proc/devices|, and we can either make the device file by hand or write a shell script to read the file in and make the device file.
The third method is that we can have our driver make the device file using the \cpp|device_create| function after a successful registration and \cpp|device_destroy| during the call to \cpp|cleanup_module|.
However, \cpp|register_chrdev()| would occupy a range of minor numbers associated with the given major.
The recommended way to reduce waste for char device registration is using cdev interface.
The newer interface completes the char device registration in two distinct steps.
First, we should register a range of device numbers, which can be completed with \cpp|register_chrdev_region| or \cpp|alloc_chrdev_region|.
\begin{code}
int register_chrdev_region(dev_t from, unsigned count, const char *name);
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);
\end{code}
The choose of two different functions depend on whether you know the major numbers for your device.
Using \cpp|register_chrdev_region| if you know the device major number and \cpp|alloc_chrdev_region| if you would like to allocate a dynamicly-allocated major number.
Second, we should initialize the data structure \cpp|struct cdev| for our char device and associate it with the device numbers.
To initialize the \cpp|struct cdev|, we can achieve by the similar sequence of the following codes.
\begin{code}
struct cdev *my_dev = cdev_alloc();
my_cdev->ops = &my_fops;
\end{code}
However, the common usage pattern will embed the \cpp|struct cdev| within a device-specific structure of your own.
In this case, we'll need \cpp|cdev_init| for the initialization.
\begin{code}
void cdev_init(struct cdev *cdev, const struct file_operations *fops);
\end{code}
Once we finish the initialization, we can add the char device to the system by using the \cpp|cdev_add|.
\begin{code}
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
\end{code}
To find a example using the interface, you can see \verb|ioctl.c| described in section \ref{sec:device_files}.
\subsection{Unregistering A Device}
\label{sec:unregister_device}
We can not allow the kernel module to be \sh|rmmod|'ed whenever root feels like it.