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
相关推荐
tan180°20 分钟前
Boost搜索引擎 网络库与前端(4)
linux·网络·c++·搜索引擎
Mr. Cao code1 小时前
Docker:颠覆传统虚拟化的轻量级革命
linux·运维·ubuntu·docker·容器
抓饼先生1 小时前
Linux control group笔记
linux·笔记·bash
搞一搞汽车电子2 小时前
S32K3平台eMIOS 应用说明
开发语言·驱动开发·笔记·单片机·嵌入式硬件·汽车
挺6的还2 小时前
25.线程概念和控制(二)
linux
您的通讯录好友2 小时前
conda环境导出
linux·windows·conda
代码AC不AC3 小时前
【Linux】vim工具篇
linux·vim·工具详解
码农hbk3 小时前
Linux signal 图文详解(三)信号处理
linux·信号处理
bug攻城狮3 小时前
Skopeo 工具介绍与 CentOS 7 安装指南
linux·运维·centos
宇宙第一小趴菜4 小时前
08 修改自己的Centos的软件源
linux·运维·centos