app: open , read , write
驱动: led_open,led_read,led_write
Drive frame:
1. Write out: led_open, led_read
Second, how to tell the kernel?
a. Define a file_operations
b. Tell the kernel about this structure:
register_chrdev(major,name,file_operations)
c. Who will call it (register_chrdev)
Driver's entry function first_drv_init
d. Modification: module_init (first_drv_init) (how to know which entry function is)
module_init: (entry function) defines a structure, the structure has a function pointer, which points to the entry function xxx_init. When loading a driver, the kernel will find the function pointer in the structure, pointing to the entry function.
When loading a driver, the kernel will find the function pointer in this structure, pointing to the entry function. The entry function tells the kernel file_operations.
Introduce an array chrdevs in the kernel (file_operations and major of character devices are included in this array):
static struct char_device_struct { struct char_device_struct *next; unsigned int major; unsigned int veminor; int minorct; char name[64]; struct file_operations *fops; struct cdev *cdev; /* will die */ } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
app:open("/dev/xxx")
Properties of open files: c _ _ _, _ _ _, _ _ _, major, minor
Device type, major device number
Kernel array chrdevs:
1 | 2 | …… | …… | …… | …… | major | …… | …… | …… |
★★VFS system will find the registered file_operations structure according to the properties of the opened file (device type: character device, major device number).
★★The implementation of register_chrdev: In a kernel array chrdevs, use the major as the index to find an item, fill in the file_operations in this item, and hang it.
Summarize:
How to find the specific implementation of the driver (led_open) according to the opened device (open)?
A chrdevs array is defined in the kernel. In this array, according to the major device number, the file_operations of that item is found. This file_operations structure is implemented in the driver.
Driver: 1. Defined led_open, led_write, led_read
2. The file_operations structure is defined, .open=led_open, .write=led_write
3. In the entry function, use register_chrdev (major, name, file_operations) to put this structure into the kernel array chrdevs, corresponding to the major device number.
Entry function (registration): hang the file_operations structure to the device number corresponding to the chrdevs array
Exit function (unload): Drag the file_operations structure from the corresponding device number.
The first driver first_drv.c:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> static int first_drv_open(struct inode *inode, struct file *file) { printk("first_drv_open\n"); return 0; } static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { printk("first_drv_write\n"); return 0; } static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* This is a macro, pushed to the __this_module variable automatically created when the module is compiled */ .open = first_drv_open, .write = first_drv_write, }; int first_drv_init(void) { register_chrdev(111, "first_drv", &first_drv_fops); //register the driver and tell the kernel return 0; } void first_drv_exit(void) { unregister_chrdev(111, "first_drv"); //Uninstall the driver } module_init(first_drv_init); module_exit(first_drv_exit);
Makefile:
KERN_DIR = /work/system/linux-2.6.22.6 all: make -C $(KERN_DIR) M=`pwd` modules clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m += first_drv.o
KERN_DIR represents the directory of the kernel, compile a driver, which depends on the kernel.
-C: Go to the KERN_DIR directory and use the Makefile in this directory to compile.
M=: what is the current directory. modules: target.