Ubuntu18.04添加内核模块(字符设备)

Ubuntu18.04添加内核模块(字符设备)

虚拟机Ubuntu18.04(内核版本linux-5.4.0-135-generic)

参考

嵌入式Linux驱动开发(一)------字符设备驱动框架入门

1 编译内核模块

  • 创建字符设备代码文件char_dev.c:
c 复制代码
#include <linux/init.h>     //定义了module_init
#include <linux/module.h>   //最基本的头文件,其中定义了MODULE_LICENSE这一类宏
#include <linux/fs.h>       // file_operations结构体定义在该头文件中
#include <linux/device.h>    //class、class_device结构体的定义位置

static const char* devive_name = "first_driver";  //  定义设备名
static struct class *first_class;    //定义class结构体
static struct device *first_dev;    //定义device结构体

//定义了open函数
static int first_drv_open (struct inode *inode, struct file *file)
{
        printk("open\n");
        return 0;
}

//定义了write函数
static ssize_t first_drv_write (struct file *file, const char __user *buf, size_t size, loff_t * ppos)
{
        printk("write\n");
        return 0;
}

//在file_operations中注册open和write函数
static struct file_operations first_drv_fo =
{
        .owner  =  THIS_MODULE,

        //将对应的函数关联在file_operations的结构体中
        .open   =  first_drv_open,      
        .write  =  first_drv_write,
};

static int dev_id = 0;     //初始化的设备号0
//init驱动的入口函数
static int __init first_drv_init(void)
{      
        //注册设备,实际是将file_operations结构体放到内核的制定数组中,以便管理
        //在register_chrdev中制定dev_id作为主设备号,若dev_id为0则自动分配一个主设备号
        dev_id = register_chrdev(dev_id, devive_name , &first_drv_fo);

	    first_class = class_create(THIS_MODULE, "first_drv");    //初始化class结构体,指定设备文件名

    	first_dev = device_create(first_class, NULL, MKDEV(dev_id, 0), NULL, "first_drv");// 根据class来初始化device,会创建出对应的设备文件 /dev/first_drv
     
        printk("init\n");
        return 0;
}

//驱动的出口函数
static void __exit first_drv_exit(void)
{
        printk("exit\n");
        unregister_chrdev(dev_id, devive_name);  //卸载设备,实际是将file_operations结构体从内核维护的相关数组中以主设备号作为索引删除
	    device_unregister(first_dev); // 后创建的先卸载
    	class_destroy(first_class);
}

//内核将通过这个宏,来直到这个驱动的入口和出口函数
module_init(first_drv_init);  
module_exit(first_drv_exit);

MODULE_AUTHOR("Ethan Lee <4128127@qq.com>");
MODULE_LICENSE("GPL");  //指定协议
  • 同目录下创建Makefile文件:
sh 复制代码
obj-m += char_dev.o
KERN_DIR=/usr/src/linux-headers-5.4.0-135-generic

all:
	make -C ${KERN_DIR} M=${shell pwd} modules

clean:
	rm -f *.ko *.o *.mod.o *.mod.c *.sysvers
  • 编译:
sh 复制代码
make

2 加载内核模块

sh 复制代码
sudo insmod char_dev.ko
  • 查看是否添加成功:
sh 复制代码
cat /proc/devices

结果如下:

sh 复制代码
Character devices:
 ...
 189 usb_device
 204 ttyMAX
 226 drm
 240 first_driver  #这里是我们添加的模块
 241 aux
 242 hidraw
...

Block devices:
  7 loop
  8 sd
  9 md
 11 sr
 65 sd
 66 sd
...
  • 创建一个测试程序char_dev_test.c:
c 复制代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    int fd;      //声明设备描述符
    int val = 1;  //随便定义变量传入到
    fd = open("/dev/first_drv",  O_RDWR);  //根据设备描述符打开设备
    if(fd < 0)          //打开失败
            printf("can't open\n");  
    write(fd, &val, 4);  //根据文件描述符调用write

    return 0;
}
  • 编译并运行测试程序:
sh 复制代码
gcc char_dev_test.c -o char_dev_test

sudo ./char_dev_test
  • 查看结果:
sh 复制代码
$ dmesg  | tail -10
[ 1746.094412] CPU3 has been hot-added
[ 1746.094945] CPU4 has been hot-added
[ 1746.097525] CPU5 has been hot-added
[ 1746.098038] CPU6 has been hot-added
[ 1746.098708] CPU7 has been hot-added
[ 2861.264107] char_dev: loading out-of-tree module taints kernel.
[ 2861.264142] char_dev: module verification failed: signature and/or required key missing - tainting kernel
[ 2861.264398] init
[ 3070.234439] open
[ 3070.234441] write

3.卸载内核模块

sh 复制代码
sudo rmmod char_dev
  • 查看结果:
sh 复制代码
$ dmesg  | tail -1
[ 4282.264114] exit
相关推荐
2035去旅行3 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希1233 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡4 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.8 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道8 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.11 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落12 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨12 小时前
WSL2的安装与使用
linux·wsl
微小的鱼13 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng13 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器