驱动模块加载三要素例子

发布时间 2023-04-15 10:14:43作者: 不是不想赢而是看淡了
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#define     HELLO_MAJOR    250
#define     HELLO_MINOR    0
#define     DEV_NUM        1
#define     DEV_NAME    "hello_world"
dev_t devno;
struct cdev hello_cdev;
struct file_operations hello_fops={
     .owner = THIS_MODULE,
};
int __init hello_init(void)
{
    int ret;
    //申请设备号
    devno = MKDEV(HELLO_MAJOR,HELLO_MINOR);
    //注册设备号
    ret = register_chrdev_region(devno,DEV_NUM,DEV_NAME);
    if (ret < 0)
    {
        printk(" register_chrdev_region fail!!!\n");
        ret = alloc_chrdev_region(&devno,HELLO_MINOR,DEV_NUM,DEV_NAME);
        if (ret < 0)
        {
            printk(" alloc_chrdev_region fail!!!\n");
            return -EFAULT;
        }
    }
    //printk(" register_chrdev_region success!!!\n");
    printk(" major = %d,minor = %d\n",MAJOR(devno),MINOR(devno));
    //申请字符设备
    //初始化字符设备
    cdev_init(&hello_cdev,&hello_fops);
    hello_cdev.owner = THIS_MODULE;
    //注册字符设备
    ret = cdev_add(&hello_cdev,devno,DEV_NUM);
    if (ret < 0)
    {
        printk(" cdev_add fail !!!\n");
        return -EFAULT;
    }
    printk(" cdev_add success!!!\n");
    printk(" hello_init!!!\n");
    return 0;
}
module_init(hello_init);
void __exit hello_exit(void)
{
     printk(" hello_exit!!!\n");
     cdev_del(&hello_cdev);
     printk(" cdev_del!!!\n");
     unregister_chrdev_region(devno,DEV_NUM);
     printk(" unregister_chrdev_region!!!\n");
}
module_exit(hello_exit);
MODULE_LICENSE("GPL");

 

 

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/
#KERNELDIR ?= /home/linux/linux-3.14/ 
PWD := $(shell pwd)
module:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
.PHONY: module clean 
else
    obj-m += hello.o
endif

 

Makefile文件解析:

ifeq ($(KERNELRELEASE),)
内核源码底层Makefile文件中定义的变量,判断变量是否为空值,如果为空,跳到else后面执行语句,并且对变量赋值
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/ 定义一个内核路径
PWD ?= $(shell pwd) 定义一个当前路径的变量

module:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

$(MAKE) 在这里等价make
-C $(KERNELDIR) 链接到内核路径
M=$(PWD) modules 指定要编译的模块的路径,并编译

clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
调用内核中Makefile文件命令清空中间文件和最终目标文件
.PHONY: module clean
指定目标文件为伪目标文件,当我执行目标文件时,后面的命令必须要执行。

else
obj-m += xxx.o
endif