当前位置: 首页 > news >正文

《linux系统内核设计与实现》-实现最简单的字符设备驱动

开发linux内核驱动需要以下4个步骤:

1 编写hello驱动代码

驱动代码如下 helloDev.c,这是一个最小、最简单的驱动,去掉了其他的不相干代码,尽量让大家能了解驱动本身。

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/slab.h>#define BUFFER_MAX  (10)             // buff大小
#define OK          (0)
#define ERROR       (-1)struct cdev *gDev;                   // 字符设备结构体指针
struct file_operations *gFile;       // 文件操作结构体指针
dev_t devNum;                        // 设备号
unsigned int subDevNum = 1;          // 注册设备的数量int reg_major  = 232;                // 主设备号
int reg_minor =  0;                  // 次设备号
char *buffer;                        // 缓冲区/*** printk 是内核中用于输出调试信息、错误信息和其他日志信息的函数。* 它将消息输出到内核日志缓冲区,这些日志可以通过 dmesg 命令查看* KERN_INFO 是一个宏:信息性消息
*/// hello_open函数:打开文件
int hello_open(struct inode *p, struct file *f)
{printk(KERN_INFO "hello_open\r\n");return 0;
}// hello_write函数
ssize_t hello_write(struct file *f, const char __user *u, size_t s, loff_t *l)
{printk(KERN_INFO "hello_write\r\n");return 0;
}// hello_read函数
ssize_t hello_read(struct file *f, char __user *u, size_t s, loff_t *l)
{printk(KERN_INFO "hello_read\r\n");return 0;
}int hello_init(void)
{devNum = MKDEV(reg_major, reg_minor);                   // 根据主次设备号,生成devNum,唯一标识设备// 把设备号注册到内核中。从devNum开始注册subDevNum个设备。if (OK == register_chrdev_region(devNum, subDevNum, "helloworld")) {printk(KERN_INFO "register_chrdev_region ok \n");} else {printk(KERN_INFO "register_chrdev_region error n");return ERROR;}printk(KERN_INFO " hello driver init \n");// 内核模块成功分配并初始化了一个字符设备结构gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);// 文件操作gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);// 赋值。回调函数gFile->open = hello_open;gFile->read = hello_read;gFile->write = hello_write;gFile->owner = THIS_MODULE;// 建立联系:通过这两行代码,驱动程序完成了字符设备的初始化和注册,使得字符设备可以被用户进程打开、读取和写入。cdev_init(gDev, gFile);             // 初始化字符设备结构体gDev,并将其与文件操作结构体gFile关联起来。cdev_add(gDev, devNum, 1);          // 将初始化好的字符设备gDev 添加到内核字符设备层,使其成为一个有效的字符设备,可以被用户空间访问和操作return 0;
}// 驱动退出函数
void __exit hello_exit(void)
{printk(KERN_INFO " hello driver exit \n");cdev_del(gDev);                                         // 删除字符设备kfree(gFile);                                           // 释放内存kfree(gDev);                                            // 释放内存unregister_chrdev_region(devNum, subDevNum);            // 注销设备号return;
}module_init(hello_init);        // 声明驱动的入口函数。执行insmod的时候调用
module_exit(hello_exit);        // 声明驱动的退出函数。执行rmmod的时候调用
MODULE_LICENSE("GPL");          // 指定模块的许可证

有了驱动文件之后,还需要一个Makefile才能把驱动编译出来

2 编写makefile

ifneq ($(KERNELRELEASE),)
obj-m := helloDev.o
else
PWD := $(shell pwd)									# 获取当前目录路径,并赋值给变量 PWD
# KDIR:= /lib/modules/4.4.0-31-generic/build
# KDIR:= /home/winter/linux-4.9.229
KDIR := /lib/modules/`uname -r`/build				# 指定内核构建目录
all:make -C $(KDIR) M=$(PWD)
clean:rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~
endif
# $(KERNELRELEASE) 是内核构建系统设置的变量,当通过内核构建系统调用此 Makefile 时,这个变量会被定义。
# -C $(KDIR):切换到内核构建目录
# M=$(PWD):指定模块源码目录为当前目录
# make -C $(KDIR) M=$(PWD):调用内核构建系统
# 这段 Makefile 通过条件分支来区分内核构建环境和用户构建环境,在用户环境中调用内核构建系统进行模块编译,并提供了清理编译生成文件的功能。

linux应用层程序在编译的时候,需要链接c运行时库和glibc库。那驱动需不需要呢?

3 编译和加载hello驱动

驱动也需要,但是驱动不能链接和使用应用层的任何lib库,驱动需要引用内核的头文件和函数。所以,编译的时候需要指定内核源码的地址。为了开发方便,也可以安装内核开发包,之后引用这个内核开发包的目录也可以。本例为:/lib/modules/4.4.0-31-generic/build

make

编译出来的驱动文件,名称为:helloDev.ko

接下来把这个驱动加载到内核

# 清零内核日志
dmesg -c
# 执行
insmod helloDev.ko
# 再看内核日志
dmesg

# 查看驱动
lsmod

# 卸载驱动
rmmod helloDev.ko
# 再查看驱动,无

4 编写应用程序测试hello驱动test.c

/*************************************************************************> File Name: test.c> Author: Winter> Created Time: 2024年05月17日 星期五 21时03分06秒************************************************************************/#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>#define DATA_NUM   (64)
int main(int argc, char *argv[])
{int fd, i;int r_len, w_len;fd_set fdset;char buf[DATA_NUM]="hello world";memset(buf,0,DATA_NUM);fd = open("/dev/hello", O_RDWR);printf("%d\r\n",fd);if(-1 == fd) {perror("open file error\r\n");return -1;} else {printf("open successe\r\n");}w_len = write(fd,buf, DATA_NUM);r_len = read(fd, buf, DATA_NUM);printf("%d %d\r\n", w_len, r_len);printf("%s\r\n",buf);return 0;
}

编译执行。因为没有/dev/hello这个设备文件,所以打开失败

需要创建设备文件

mknod
man mknod
# 名字 类型 【主设备号  次设备号】
mknod [OPTION]... NAME TYPE [MAJOR MINOR]
mknod /dev/hello c 232 0# 查看
ls -l /dev/hello# 再执行测试程序
./test

有调用日志

这个返回值是驱动部分对应的返回值

5 一些命令

dmesg -c			# 清零内核日志
insmod helloDev.ko  # 插入(加载)Linux内核模块的命令
dmesg				# dmesg 命令用于查看和管理 Linux 内核的环形缓冲区中的消息
lsmod				# 查看驱动
rmmod helloDev.ko   # 卸载驱动# 创建设备文件:名字 类型 【主设备号  次设备号】
mknod [OPTION]... NAME TYPE [MAJOR MINOR]
mknod /dev/hello c 232 0

相关文章:

《linux系统内核设计与实现》-实现最简单的字符设备驱动

开发linux内核驱动需要以下4个步骤&#xff1a; 1 编写hello驱动代码 驱动代码如下 helloDev.c&#xff0c;这是一个最小、最简单的驱动&#xff0c;去掉了其他的不相干代码&#xff0c;尽量让大家能了解驱动本身。 #include <linux/module.h> #include <linux/mod…...

【MotionCap】pycharm 远程在wsl2 ubuntu20.04中root的miniconda3环境

pycharm wsl2 链接到pycharmsbin 都能看到内容,/root 下内容赋予了zhangbin 所有,pycharm还是看不到/root 下内容。sudo 安装了miniconda3 引发了这些问题 由于是在 root 用户安装的miniconda3 所以安装路径在/root/miniconda3 里 这导致了环境也是root用户的,会触发告警 WA…...

[BJDCTF 2nd]简单注入

sqlsqlsqlsqlsql又来喽 过滤了单双引号&#xff0c;等于符号&#xff0c;还有select等&#xff0c;但是这里没有二次注入 。扫描发现hint.txt 看出题人的意思是&#xff0c;得到密码即可获得flag。 select * from users where username$_POST["username"] and passw…...

java项目的一些功能(完善登录功能、注册接口参数校验、完善分页查询、完善日期格式、更新文章分类和添加文章分类的分组校验、自定义校验、文件上传 )

目录 完善登录功能 注册接口参数校验 完善分页查询 完善日期格式 更新文章分类和添加文章分类的分组校验 ​编辑 自定义校验 文件上传 完善登录功能 对前端传过来的明文密码进行md5加密处理 password DigestUtils.md5DigestAsHex(password.getBytes()); 这样既可 注…...

Mac安装AndroidStudio连接手机 客户端测试

参考文档&#xff1a;https://www.cnblogs.com/andy0816/p/17097760.html 环境依赖 需要java 1.8 java安装 略 下载Android Studio 地址 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 本机对应的包进行下载 安装过程 https://www.cnblogs.c…...

Git 完整的提交规范教程

约定式提交规范 本文中的关键词 “必须&#xff08;MUST&#xff09;”、“禁止&#xff08;MUST NOT&#xff09;”、“必要&#xff08;REQUIRED&#xff09;”、“应当&#xff08;SHALL&#xff09;”、“不应当&#xff08;SHALL NOT&#xff09;”、“应该&#xff08;S…...

【TB作品】51单片机 Proteus仿真 00001仿真实物PID电机调速系统

实验报告&#xff1a;Proteus 仿真 PID 电机调速系统 一、实验背景 PID&#xff08;比例-积分-微分&#xff09;控制器广泛应用于工业控制系统中&#xff0c;用于调节各种物理变量。本实验的目的是通过 Proteus 仿真软件设计并实现一个 PID 电机调速系统&#xff0c;以控制直…...

【LInux】从动态库的加载深入理解页表机制

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

IDEA与通义灵码的智能编程之旅

1 概述 本文主要介绍在IDEA中如何安装和使用通义灵码来助力软件编程,从而提高编程效率,创造更大的个人同企业价值。 2 安装通义灵码 2.1 打开IDEA插件市场 点击IDEA的设置按钮,下拉选择Plugins,如下: 2.2 搜索通义灵码 在搜索框中输入“通义灵码”,如下: 2.3 安…...

多表查询sql

概述&#xff1a;项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系&#xff0c;分为三种&#xff1a; 一对多多对多一对一 一、多表关系 一对多 案例&#xff1a;部门与…...

移动端UI风格营造舒适氛围

移动端UI风格营造舒适氛围...

摸鱼大数据——Spark SQL——DataFrame详解一

1.DataFrame基本介绍 DataFrame表示的是一个二维的表。二维表&#xff0c;必然存在行、列等表结构描述信息​表结构描述信息(元数据Schema): StructType对象字段: StructField对象&#xff0c;可以描述字段名称、字段数据类型、是否可以为空行: Row对象列: Column对象&#xff…...

【Java探索之旅】初识多态_概念_实现条件

文章目录 &#x1f4d1;前言一、多态1.1 概念1.2 多态的实现条件 &#x1f324;️全篇总结 &#x1f4d1;前言 多态作为面向对象编程中的重要概念&#xff0c;为我们提供了一种灵活而强大的编程方式。通过多态&#xff0c;同一种操作可以应用于不同的对象&#xff0c;并根据对象…...

[Day 26] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

數據科學與AI的整合應用 數據科學&#xff08;Data Science&#xff09;和人工智能&#xff08;AI&#xff09;在現代技術世界中扮演著至關重要的角色。兩者的整合應用能夠為企業和研究人員提供強大的工具&#xff0c;以更好地理解、預測和解決各種複雜的問題。本文將深入探討…...

算法 —— 滑动窗口

目录 长度最小的子数组 无重复字符的最长子串 最大连续1的个数 将x减到0的最小操作数 找到字符串中所有字母异位词 最小覆盖子串 长度最小的子数组 sum比target小就进窗口&#xff0c;sum比target大就出窗口&#xff0c;由于数组是正数&#xff0c;所以相加会使sum变大&…...

【设计模式】工厂模式(定义 | 特点 | Demo入门讲解)

文章目录 定义简单工厂模式案例 | 代码Phone顶层接口设计Meizu品牌类Xiaomi品牌类PhoneFactory工厂类Customer 消费者类 工厂方法模式案例 | 代码PhoneFactory工厂类 Java高级特性---工厂模式与反射的高阶玩法方案&#xff1a;反射工厂模式 总结 其实工厂模式就是用一个代理类帮…...

Linux之计划和日志

计划任务 计划任务概念解析 在Linux操作系统中,除了用户即时执行的命令操作以外,还可以配置在指定的时间、指定的日期执行预先计划好的系统管理任务(如定期备份、定期采集监测数据)。通过安装at和crontabs这两个系统服务实现一次性、周期性计划任务的功能,并分别通过at、…...

C++ 多态篇

文章目录 1. 多态的概念和实现1.1 概念1.2 实现1.2.1 协变1.2.2 析构函数1.2.3 子类虚函数不加virtual 2. C11 final和override3.1 final3.2 override 3. 函数重载、重写与隐藏4. 多态的原理5. 抽象类6.单继承和多继承的虚表6.1 单继承6.2 多继承 7. 菱形继承的虚表(了解)7.1 菱…...

【LVGL-SquareLine Studio】

LVGL-SquareLine Studio ■ SquareLine Studio-官网下载地址■ SquareLine Studio-参考博客■ SquareLine Studio-安装■ SquareLine Studio-汉化■ SquareLine Studio-■ SquareLine Studio-■ SquareLine Studio-■ SquareLine Studio-■ SquareLine Studio- ■ SquareLine S…...

mysqli 与mysql 区别和联系, 举例说明

mysqli是一种PHP的扩展&#xff0c;用于与MySQL数据库进行交互。它提供了一套面向对象的接口&#xff0c;可以更方便地操作数据库。MySQL是一种关系型数据库管理系统&#xff0c;用于存储和管理数据。 区别&#xff1a; mysqli是MySQL的扩展&#xff0c;而不是单独的数据库管…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...