LDD-Basics

Device registeration

 The kernel uses structures of type struct cdev to represent char devices internally. Include <linux/cdev.h> so that you can use the following structures functions.
1 struct cdev *cdev_alloc(void);  //allocate a cdev
2 void cdev_init(struct cdev *cdev, struct file_operations *fops);  //initialize it
3 int cdev_add(sturct cdev *cdev, dev_t num, unsigned int count);  //add it to kernel
4 void cdev_del(struct cdev *dev);  //remove it
Example of setuping a cdev(scull):
 1 static void scull_setup_cdev(struct scull_dev *dev, int index)
 2 {
 3     int err, devno = MKDEV(scull_major, scull_minor + index);
 4     cdev_init(&dev->cdev, &scull_fops);
 5     dev->cdev.owner = THIS_MODULE;
 6     dev->cdev.ops = &scull_fops;
 7     err = cdev_add (&dev->cdev, devno, 1);
 8     /* Fail gracefully if need be */ 
 9     if (err)
10         printk(KERN_NOTICE "Error %d adding scull%d", err, index);
11 }

The older way to register and unregister a cdev is with:

1 int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
2 int unregister_chrdev(unsigned int major, const char *name);
 
Major and minor numbers

The major nuber is the driver associated with the device, while the minor number is used by the kernel to determine which device is being referrd to. You can use the minor number as an index into a local array of devices.
Use dev_t type to hold device number with the help of MACROS defined in <linux/kdev_t.h>. You can obtain major or minor numbers with the following codes:
1 MAJOR(dev_t dev);
2 MINOR(dev_t dev);
Instead, use the following codes to make a dev_t:
MKDEV(int major, int minor);
Before setting up a char device, your driver need to obtain a device number to work with using register_chrdev_regiondeclared 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 your equest is available. Finally, name is the name of the device that should be associatedwith this number range; it will appear in /proc/devices and sysfs."
However, if you have no idea about which number you want, use alloc_chrdev_region to gain a device number:
int alloc_chrdev_region(dev_t *dev, unsigned in firstminor, unsigned int count, char *name);
If successfully completed, dev, as an output-only para, will hold the first number in the allocated range. firstminor should be the requested first minor number to use, always 0.
When device numbers are no longer used, remember to free them with:
void unregister_chrdev_region(dev_t first, unsigned int count);
 
Module parameters

Parameter values can be assigned at load time by insmod or modprobe(this can read parameter from configuration file /etc/modeprobe.conf).
While you type the paras in command line, the paras should also be declared with the module_para marco in codes:
1 static char *whom = "world";
2 static int howmany = 1;
3 module_param(howmany, int, S_IRUGO);
4 module_param(whom, charp, S_IRUGO);
The types of para are as following:
    bool/invbool(true->false, false->true)
    charp(a char pointer)
    integer(int, long, short, uint, ulong, ushort)
    array(values should be supplied as a comma-separated list)
The array parameter is declared in a different way:
module_param_array(name,type,nump,perm);  
Where name is the name of your array (and of the parameter), type is the type of thearray elements, nump is an integer variable, and perm is the usual permissions value. Ifthe array parameter is set at load time, nump is set to the number of values supplied.The module loader refuses to accept more values than will fit in the array.
TO define a type of para not defined above, see modulepara.h.
The final module_param fieldis a permission value, which is defiend in <linux/stat.h>. If perm is set to 0, there is no sysfs;otherwise, it appears under /sys/module with the givern set of permissions. Usually use S_IRUGO for those that only can be read. If you are read to detect the change of the paras and react, S_IRUGO| S_IWUSR would allow root to change the paras.  
 
posted @ 2018-11-07 10:55  glob  阅读(159)  评论(0编辑  收藏  举报