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

Linux驱动学习day2

APP和驱动交互方式

app与驱动之间,通过下面两个函数交互数据

  1. copy_to_user
  2. copy_from_user
/* 函数原型 */
static inline unsigned long copy_from_user(void* to , const char* from , unsigned long n);static inline unsigned long copy_to_user(void* to , const char* from , unsigned long n);

驱动和硬件之间交互

  1. 可以使用各个子系统函数(iic and so on)
  2. 寄存器(但是Linux中不能直接使用addr ,要使用内存映射ioremap)
int *p = ioremap(addr , size);

改进hello_drv.c驱动代码

为了实现在开发板上能够自动生成nod,不需要使用mknod显示创建nod,在入口函数的时候创建类class_create , 并且注册设备device_create();下图是insmod hello_drv.ko之后的结果,可以cat dev,就能看到其驱动的主设备号和次设备号。

入口函数 

/* register_chrdev */
static int __init hello_init(void)
{major = register_chrdev(0 , "hello_drv", &hello_drv);/* do not need mknod */hello_class = class_create(THIS_MODULE, "hello_class");if (IS_ERR(hello_class)) {printk("failed to allocate class\n");unregister_chrdev(major, "hello_class");return PTR_ERR(hello_class);}/* struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...) */device_create(hello_class , NULL , MKDEV(major, 0) , NULL , "hello"); /* create node /dev/hello */return 0;
}

出口函数 

/* entry function */
static void __exit  hello_exit(void)
{/* distroy void device_destroy(struct class *class, dev_t devt)*/device_destroy(hello_class , MKDEV(major, 0));class_destroy(hello_class);unregister_chrdev(major, "hello_drv");return;
}
#include <linux/module.h>     // 最基本模块宏
#include <linux/kernel.h>     // printk
#include <linux/init.h>       // __init/__exit
#include <linux/fs.h>         // register_chrdev 等
#include <linux/uaccess.h>    // copy_to_user, copy_from_user
#include <linux/types.h>      // dev_t, bool 等类型
#include <linux/device.h>static int major = 0;
static char hello_buf[100];static struct class *hello_class;/* funciton */static ssize_t hello_drv_read (struct file *file, char __user *buf , size_t size, loff_t * offset)
{unsigned long len = (size < 100 ? size : 100);//printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);if(copy_to_user(buf, hello_buf, len) != 0){printk("copy_to_user error\n");return -1;}printk("read from drivers:%s %s %s\n" , __FILE__ , __FUNCTION__ , hello_buf);return len;
}static ssize_t hello_drv_write (struct file *file, const char __user *buf , size_t size, loff_t * offset)
{unsigned long len = (size < 100 ? size : 100);// printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);if(copy_from_user(hello_buf, buf, len) != 0){printk("copy_from_user error\n");return -1;}printk("write from user:%s %s %s\n" , __FILE__ , __FUNCTION__ , hello_buf);return len;  
}static int hello_drv_open (struct inode *node, struct file *file)
{// printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);return 0;
}static int hello_drv_close (struct inode *node, struct file *file)
{// printk("%s %s %d\n" , __FILE__ , __FUNCTION__ , __LINE__);return 0;
}/*  create struct file_operations */
static struct file_operations hello_drv = 
{.owner          = THIS_MODULE,.open           = hello_drv_open,.read           = hello_drv_read,.write          = hello_drv_write,.release        = hello_drv_close,
};/* register_chrdev */
static int __init hello_init(void)
{major = register_chrdev(0 , "hello_drv", &hello_drv);/* do not need mknod */hello_class = class_create(THIS_MODULE, "hello_class");if (IS_ERR(hello_class)) {printk("failed to allocate class\n");unregister_chrdev(major, "hello_class");return PTR_ERR(hello_class);}/* struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...) */device_create(hello_class , NULL , MKDEV(major, 0) , NULL , "hello"); /* create node /dev/hello */return 0;
}/* entry function */
static void __exit  hello_exit(void)
{/* distroy void device_destroy(struct class *class, dev_t devt)*/device_destroy(hello_class , MKDEV(major, 0));class_destroy(hello_class);unregister_chrdev(major, "hello_drv");return;
}module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

使用命令echo "4 4 1 7" > /proc/sys/kernel/printk,可以取消掉内核驱动的打印。

使用命令echo "7 4 1 7" > /proc/sys/kernel/printk,可以开启内核驱动的打印。

从上图结果看,可以成功写入驱动并且读出来。成功! 

http://www.lqws.cn/news/189199.html

相关文章:

  • vm+ubuntu24.04扩展磁盘
  • Ubuntu创建修改 Swap 文件分区的步骤——解决嵌入式开发板编译ROS2程序卡死问题
  • 使用 Docker Compose 部署 Jenkins(LTS 版)持续集成环境
  • JAVA-什么是JDK?
  • TP6 实现一个字段对数组中的多个值进行LIKE模糊查询(OR逻辑)
  • HTTP协议
  • 影楼精修-AI衣服祛褶皱算法解析
  • LLM Agent 如何颠覆股价预测的传统范式
  • PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式
  • 高效复用 Cursor 请求,提升开发效率 —— 使用 interactive-feedback-mcp 工具详解
  • 三维GIS开发cesium智慧地铁教程(4)城市白模加载与样式控制
  • Python 训练营打卡 Day 45
  • 【001】frida API分类 总览
  • css元素的after制作斜向的删除线
  • 飞云智能波段主图+多空短线决策副图指标,组合操盘技术图文解说
  • SpringCloud学习笔记-2
  • 【Elasticsearch】映射:Nested 类型
  • day46python打卡
  • 【Linux】虚拟机代理,自动化脚本修改~/.bashrc
  • vue3子组件获取并修改父组件的值
  • 【计算机网络】非阻塞IO——poll实现多路转接
  • 【佳易王个体诊所电子处方软件】助力智慧诊疗! #医疗数字化 #电子处方效率提升
  • 【 知你所想 】基于ernie-x1-turbo推理模型实现趣味猜心游戏
  • QT自定义资源管理器
  • 使用UDP连接ssh
  • maven私服
  • vanna+deepseek+chainlit 实现自然语言转SQL的精度调优
  • Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
  • MySQL 性能调优入门 - 慢查询分析与索引优化基础
  • 行业案例 | ASOS 借助 Azure AI Foundry(国际版)为年轻时尚爱好者打造惊喜体验