We develop a character driver because this class is suitable for most simple hardware devices. Char drivers are also easier to understand than block drivers or network drivers.we present code fragments extracted from a real device driver: scull (Simple Character Utility for Loading Localities). scull is a char driverthat acts on a memory area as though it were a device.The advantage of scull is that it isn’t hardware dependent. scull just acts on somememory, allocated from the kernel. Anyone can compile and run scull, and scull is portable across the computer architectures on which Linux runs.
The Design of scull
struct scull_dev {
struct scull_qset *data; /* Pointer to first quantum set */
int quantum;
/* the current quantum size */
int qset;
/* the current array size */
unsigned long size;
/* amount of data stored here */
unsigned int access_key; /* used by sculluid and scullpriv */
struct semaphore sem;
/* mutual exclusion semaphore
*/
struct cdev cdev;
/* Char device structure
*/
};
Allocating and Freeing Device Numbers
One of the first things your driver will need to do when setting up a char device is to
obtain one or more device numbers to work with. The necessary function for this
task is register_chrdev_region, which is declared in <linux/fs.h>:
int register_chrdev_region(dev_t first, unsigned int count,
char *name);
Here, first is the beginning device number of the range you would like to allocate.
The minor number portion of first is often 0, but there is no requirement to that
effect. count is the total number of contiguous device numbers you are requesting.
Note that, if count is large, the range you request could spill over to the next major
number; but everything will still work properly as long as the number range you
request is available. Finally, name is the name of the device that should be associated
with this number range; it will appear in /proc/devices and sysfs.
The kernelwill happily allocate a major number for you on the fly, but you must request this allocation by using a different function:
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,
unsigned int count, char *name);
Regardless of how you allocate your device numbers, you should free them when
they are no longer in use. Device numbers are freed with:
void unregister_chrdev_region(dev_t first, unsigned int count);
File Operations
The scull device driver implements only the most important device methods. Its
file_operations structure is initialized as follows:
struct file_operations scull_fops = {
.owner =
THIS_MODULE,
.llseek =
scull_llseek,
.read =
scull_read,
.write =
scull_write,
.ioctl =
scull_ioctl,
.open =
scull_open,
.release = scull_release,
};