1. Character-driven framework
Q: How do the applications open, read, and write find the driver's open, read, and write functions?
Answer: The application's open, read, and write are implemented in the C library. It uses the swi val instruction to trigger an exception. This exception will enter the kernel space. In the kernel's exception handling function, there is an input based on us Val to decide whether to call the system_open or system_read, system_write functions, these functions have different properties according to our open different files, different files have different attributes (such as device type (character device or block device or network device), main device number) These attributes find the lower-level driver.
Q: What is the major device number and what is the minor device number
Answer: The Linux major device number is used to distinguish between different hardware device types, such as the difference between LED and serial port;
Linux minor device number is used to distinguish between different hardware devices, such as the difference between serial port 1 and serial port 2;
Q: What method is used to find the open function of the driver
Answer: Through a registration function + device node
The registration functions are as follows (old registration functions, new ones will be discussed later):
register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
Parameter 1: Major device number (important)
Parameter 2: Name (not important)
Parameter 3: file_operations structure (important)
Device node:
It can be created manually or automatically. For the time being, it will only be created manually.
mknod /dev/xxx c 252 0
Create a device node named / dev / xxx, c represents the character device node, 252 is the major device number, and 0 is the minor device number.
Q: The application program is generally executed by the main function, so what is the driver program to execute first?
Answer: Through a macro, specify the entry function of the driver, and the entry function will be executed when the driver is loaded.
For example: module_init (first_drv_init); // Used to modify the entry function
Naturally, the exit function of the driver will be executed when the driver is unloaded.
For example: module_exit (first_drv_exit); // Used to modify the export function
The driver source program is as follows:
#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 <linux/module.h>
int major;
static int first_drv_open(struct inode * inode, struct file * filp)
{
printk("first_drv_open\n");
return 0;
}
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
{
printk("first_drv_write\n");
return 0;
}
/* File operations struct for character device */
static const struct file_operations first_drv_fops = {
.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,
};
/* 驱动入口函数 */
static int first_drv_init(void)
{
/* 主设备号设置为0表示由系统自动分配主设备号 */
major = register_chrdev(0, "first_drv", &first_drv_fops);
return 0;
}
/* 驱动出口函数 */
static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv");
}
module_init(first_drv_init); //用于修饰入口函数
module_exit(first_drv_exit); //用于修饰出口函数
MODULE_AUTHOR("LWJ");
MODULE_DESCRIPTION("Just for Demon");
MODULE_LICENSE("GPL"); //遵循GPL协议
Makefile source code is as follows:
ifneq ($(KERNELRELEASE),)
obj-m := first_drv.o
else
KDIR := /home/opt/EmbedSky/linux-2.6.30.4
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
The test procedure is as follows:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
int fd;
int val = 1;
fd = open("/dev/xxx",O_RDWR); //打开名为 /dev/xxx 的设备节点
if(fd < 0)
{
printf("open error\n");
}
write(fd,&val,4);
return 0;
}
The test steps on the development board are as follows:
[WJ2440]# insmod first_drv.ko
[WJ2440]# ./first_test
open error //没有创建设备节点
[WJ2440]# cat proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound
29 fb
81 video4linux
89 i2c
90 mtd
116 alsa
128 ptm
136 pts
180 usb
188 ttyUSB
189 usb_device
204 tq2440_serial
252 first_drv //我们创建的字符设备,主设备号252
253 usb_endpoint
254 rtc
Block devices:
259 blkext
7 loop
8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
[WJ2440]# mknod /dev/xxx c 252 0 //手动创建一个字符设备节点
[WJ2440]# ls -l /dev/xxx
crw-r--r-- 1 root root 252, 0 Jan 1 20:49 /dev/xxx
[WJ2440]# ./first_test //有设备节点后成功我们的应用程序运行了
first_drv_open
first_drv_write
[WJ2440]#
This article refers to: