Linux 驱动开发简单实例

2023-05-16

Xiuye_XY于 2021-08-03 19:17:07 发布343 收藏 3

分类专栏: 笔记 C/C++ Linux

版权

​编辑笔记同时被 3 个专栏收录正在上传…重新上传取消

128 篇文章0 订阅

订阅专栏

​编辑C/C++

278 篇文章2 订阅

订阅专栏

​编辑Linux

61 篇文章0 订阅

订阅专栏

驱动源码

  1. #include <linux/init.h>
  2. #include <linux/module.h>

  3. #include <linux/kernel.h>

  4. #include <linux/fs.h>

  5. #include <linux/delay.h>

  6. #define major_version 200

  7. #define driver1_name "driver1"

  8. static char read_buf[100] = "Hello driver1";

  9. static char write_buf[100];

  10. static int driver1_open(struct inode *inode,struct file *file){

  11. printk("driver1 open\r\n");

  12. return 0;

  13. }

  14. static int driver1_close(struct inode *inode,struct file *file){

  15. printk("driver1 close\r\n");

  16. return 0;

  17. }

  18. static ssize_t driver1_read(struct file *file, char __user * buf, size_t count, loff_t *ppos){

  19. printk("driver1 read\r\n");

  20. copy_to_user(buf,read_buf,count);

  21. return 0;

  22. }

  23. static ssize_t driver1_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos){

  24. int ret = 0;

  25. printk("driver1 write\r\n");

  26. ret = copy_from_user(write_buf,buf,count);

  27. if(!ret){

  28. printk("receive data: %s \r\n",write_buf);

  29. }

  30. return 0;

  31. }

  32. static struct file_operations ops={

  33. .owner = THIS_MODULE,

  34. .open = driver1_open,

  35. .release = driver1_close,

  36. .read = driver1_read,

  37. .write = driver1_write

  38. };

  39. static int __init driver1_init(void)

  40. {

  41. int ret ;

  42. printk("%s,%d\r\n", __func__, __LINE__);

  43. ret= register_chrdev(major_version,driver1_name, &ops);

  44. return ret;

  45. }

  46. static void __exit driver1_exit(void)

  47. {

  48. printk("%s,%d\r\n", __func__, __LINE__);

  49. unregister_chrdev(major_version, driver1_name);

  50. }

  51. module_init(driver1_init);

  52. module_exit(driver1_exit);

  53. MODULE_LICENSE("GPL");

Makefile文件:(像obj-m ,-C, M= 等好像是规定的,不要随便改写)


  
  1. #内核的源码路径, ?= 条件赋值, uname -r 得到内核的版本号

  2. KERNELDIR = /lib/modules/$(shell uname -r)/build

  3. # 生成模块

  4. obj-m := driver1.o

  5. # := 立即赋值, 得到当前的绝对路径

  6. PWD := $(shell pwd)

  7. # -C 切换工作路径, make -c

  8. modules:

  9. $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

  10. clean:

  11. rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules* *.mod

  12. .PHONY: modules clean

应用程序调用驱动文件:


  
  1. #include<iostream>

  2. #include<unistd.h>

  3. #include <sys/types.h>

  4. #include <sys/stat.h>

  5. #include <fcntl.h>

  6. using namespace std;

  7. int main(int argc,char*argv[]){

  8. int ret = 0;

  9. int fd = 0;

  10. char *filename;

  11. char read_buf[100],write_buf[100]="hello,driver1";

  12. if(argc < 2){

  13. cout << "cmd one param!" << endl;

  14. return -5;

  15. }

  16. filename = argv[1];

  17. fd = open(filename,O_RDWR);

  18. if(fd < 0){

  19. cout << "Cannot open file,"<<filename<< endl;

  20. return -1;

  21. }

  22. ret = read(fd,read_buf,100);

  23. if(ret < 0){

  24. cout << "read file "<<filename << " failed."<<endl;

  25. return -2;

  26. }

  27. cout<< "read buf:" << read_buf << endl;

  28. ret = write(fd,write_buf,100);

  29. if(ret <0){

  30. cout << "write file "<< filename << " failed." <<endl;

  31. return -3;

  32. }

  33. ret = close(fd);

  34. if(ret <0){

  35. cout << "close file "<< filename << " failed." <<endl;

  36. return -3;

  37. }

  38. cout << "app end" << endl;

  39. return 0;

  40. }

编译驱动


  
  1. make -C /lib/modules/5.8.0-63-generic/build M=/home/xiuye/Documents/cpp/driver1 modules

  2. make[1]: Entering directory '/usr/src/linux-headers-5.8.0-63-generic'

  3. CC [M] /home/xiuye/Documents/cpp/driver1/driver1.o

  4. MODPOST /home/xiuye/Documents/cpp/driver1/Module.symvers

  5. CC [M] /home/xiuye/Documents/cpp/driver1/driver1.mod.o

  6. LD [M] /home/xiuye/Documents/cpp/driver1/driver1.ko

  7. make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-63-generic'

加载驱动

insmod driver1.ko 或者 modprobe driver1.ko

创建设备文件(如果/dev下没有驱动名的文件)

mknod /dev/driver1 c 200 0

  
  1. root@ubuntu:cpp/driver1# ls /dev/driver1

  2. /dev/driver1

  3. root@ubuntu:cpp/driver1# cat /proc/devices | grep driver1

  4. 200 driver1

应用程序调用驱动(只能在root下调用,否则失败,不知道原因):


  
  1. root@ubuntu:cpp/driver1# ./a.out /dev/driver1

  2. read buf:Hello driver1

  3. app end

查看驱动打印消息:


  
  1. root@ubuntu:cpp/driver1# dmesg

  2. [ 5062.671752] driver1_exit,76

  3. [ 5078.688136] driver1_init,63

  4. [ 5303.464000] driver1 open

  5. [ 5303.464002] driver1 read

  6. [ 5303.464030] driver1 write

  7. [ 5303.464030] receive data: hello,driver1

  8. [ 5303.464031] driver1 close

删除驱动:


  
  1. root@ubuntu:cpp/driver1# rmmod driver1

  2. root@ubuntu:cpp/driver1# dmesg

  3. [ 5438.032293] driver1_exit,76

删除设备文件,直接用 rm 命令。

echo $? 显示当前程序返回值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 驱动开发简单实例 的相关文章

随机推荐

  • stm32串口一直进USART1_IRQHandler

    今天在使用USART模块 xff0c 遇到了一些问题并解决了 xff0c 于是发贴共享 问题描述 xff1a 在使用USART做串口通讯时 xff0c 我只把接收中断打开 xff0c 并设置抢占优先级为最低一个级别 xff0c 而接收中断上
  • tensorflow载入报错Process finished with exit code -1073741819 (0xC0000005)

    这几天准备在现有的软件里加上caffe来测试一种新算法 发现windows下python3 6安装caffe是真的难 xff0c 只能装好python2 7的版本就放弃了 回来继续完善软件 xff0c 又发现软件里的tensorflow不能
  • python项目打包(自定义dll) anaconda3+pyinstaller

    目前手上有一个python 43 pyqt的项目需要打包 xff0c 所以查了一下打包的方法 下面介绍一下具体步骤 xff1a python打包有很多方法 xff0c py2exe xff0c pyinstaller等等 xff08 其实我
  • Docker(六)同一镜像有多个Tag情况下,执行 docker rmi 镜像ID 指令无法删除

    删除方法一 docker rmi f 镜像ID 删除方法二 docker rmi repository tag 参考 xff1a 1 https www imooc com article 35040
  • 《ROS机器人开发实践(胡春旭)》第十章MoveIt!机械臂控制 学习笔记

    r 在学习 ROS机器人开发实践 胡春旭 第10章的MoveIt xff01 时 xff0c 因为在自己创建的工作空间中没有下载作者的源代码 xff0c 所有有以下几个问题 xff1a 1 使用moveit setup assistant时
  • Android 根据网络分析运营商信息

    我们想获取手机的运营商信息 通常都会去调用系统的TelephonyManager类的取数据 但是很多时候可能取不到卡的信息 xff08 例如双卡手机和一些特殊卡 xff09 xff0c 这样就区别不了运营商了 但是有时候我们的需求要进行不通
  • 简单又好看的按钮,扁平化按钮。

    今天分享一下流行的扁平化按钮 完全不需要用到图片哦 效果图如下 xff1a 里面有2个按钮都是一样的模式 只要修改的色值就可以 下面跟我来更新你的UI吧 首先编写 button xml 代码如下 lt xml version 61 34 1
  • Android 获取运营商信息(完整版)-解决高通,MTK等双卡问题

    由于国内的运营商问题 xff0c 双卡手机获取IMSI号问题要根据厂商API 来实现 下面我们就来做一套完整的分析运营商获取IMSI号逻辑 1 xff0c 首先我们要判断手机的平台 1 1 xff0c 判断手机是否MTK平台 public
  • AstarPathfindingProject 中RVO碰撞体扩展

    原本库中只有矩形RVO碰撞体 xff0c 如果要添加自己的需要继承RVOObstacle抽象类 xff0c 重写里面的方法 例如下面的圆柱形碰撞 using UnityEngine if UNITY EDITOR using UnityEd
  • Android中抓取手机视频流数据。

    目前实时抓取手机视频数据有2种方法 xff0c 一种是通过camera的回调获取源数据 xff0c 这里获取的源数据是没有编码的数据 有的人发送yuv数据然后在那绘制图片 xff0c 也说视频聊天 xff0c 真是可笑 这种方式是可是实现视
  • Android 使用AudioRecord录音相关和音频文件的封装

    在Android中录音可以用MediaRecord录音 xff0c 操作比较简单 但是不够专业 xff0c 就是不能对音频进行处理 如果要进行音频的实时的处理或者音频的一些封装 就可以用AudioRecord来进行录音了 这里给出一段代码
  • Android 中使用MediaRecorder进行录像详解(视频录制)

    在这里给出自己的一个测试DEMO xff0c 里面注释很详细 简单的视频录制功能 package com video import java io IOException import android app Activity import
  • Android手机中获取手机号码和运营商信息

    代码如下 xff1a package com pei activity import android app Activity import android os Bundle import android view View import
  • C语言下划线开头的函数

    首先 xff0c C 43 43 里关于下划线的问题是源于C语言 xff0c 因为C 43 43 允许用extern C 来修饰代码以C语言语法方式编译 然后说C语言里的下划线 xff1a C语言确实允许以下划线开头的函数存在 xff0c
  • 校验和计算方法

    1 说明 xff1a 1 校验和覆盖的内容 xff1a IP校验和 xff1a IP首部 ICMP校验和 xff1a ICMP首部 43 ICMP数据 xff1b UDP TCP校验和 xff1a 首部 43 数据 43 12个字节伪首部
  • 布谷鸟算法浅谈与简单应用

    简介 布谷鸟算法是由剑桥大学Xin She Yang教授和S Deb于2009年提出的一种新兴的启发算法 xff0c 是一种通过模拟自然界当中布谷鸟 xff08 也就是杜鹃 xff0c 故该算法也称为杜鹃算法 xff09 在繁育后代的行为而
  • torchvision中inception v3的实现

    一 torchvision中inception v3的网络结构 论文中给的结构如下图所示 但是torchvision中的inception v3结构中并不是这么实现的 下面解释一下torchvision中的inception v3结构 xf
  • 实践 基于Arduino 的 平衡车

    完成样子 因为只是学习验证 xff0c 没用电烙铁 xff0c 只用了面包板来连接各个组件 xff0c 中间用扎带固定 xff08 不稳定 xff09 完成后能基本保持平衡 xff0c 但太大力去推容易倒 平衡原理 通过负反馈实现平衡 xf
  • CMake入门-04-自定义编译选项

    工作环境 系统 xff1a macOS Mojave 10 14 6CMake Version 3 15 0 rc4 Hello World 自定义编译选项 CMake 允许为项目增加编译选项 xff0c 从而可以根据用户的环境和需求选择最
  • Linux 驱动开发简单实例

    Xiuye XY于 2021 08 03 19 17 07 发布343 收藏 3 分类专栏 xff1a 笔记 C C 43 43 Linux 版权 编辑笔记同时被 3 个专栏收录正在上传 重新上传取消 128 篇文章0 订阅 订阅专栏 编辑