Linux字符设备驱动实例


globalmem

linux 设备驱动开发详解时,字符设备驱动一章,写的测试代码和应用程序,加上自己的操作,对初学者我觉得非常有帮助。

写这篇文章的原因是因为我看了我之前发表的文章,还没有写过字符设备相关的,至于里面提到的结构体的作用,有很多详细的文章说明,我就不做更深的叙述。

代码在github上,点击下面阅读原文可以直达

https://github.com/weiqifa0/globalmem/blob/main/README.md

把这部分放在github上也有好处,后续可以增加删除一些东西,以后自己需要使用的时候也方便许多。

我们讨论字符设备驱动,就有必要知道他的结构体和头文件,像一些后来的封装什么的,大部分还是脱离不了操作这个结构体里面的东西。

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_CDEV_H
#define _LINUX_CDEV_H#include <linux/kobject.h>
#include <linux/kdev_t.h>
#include <linux/list.h>
#include <linux/device.h>struct file_operations;
struct inode;
struct module;struct cdev {struct kobject kobj; /*内嵌kobject结构体,方便以后应用,也会在sys下生成相关设备文件*/struct module *owner;/*所属于的模块,正常就是本模块THIS_MODULE*/const struct file_operations *ops;/*文件的操作结构体,设备也是一个文件*/struct list_head list;/*字符设备的链表头*/dev_t dev;/*设备号*/unsigned int count;
} __randomize_layout;
/*初始化cdev,并建立和file_operation的联系*/
void cdev_init(struct cdev *, const struct file_operations *);
/*申请cdev内存*/
struct cdev *cdev_alloc(void);void cdev_put(struct cdev *p);int cdev_add(struct cdev *, dev_t, unsigned);void cdev_set_parent(struct cdev *p, struct kobject *kobj);
int cdev_device_add(struct cdev *cdev, struct device *dev);
void cdev_device_del(struct cdev *cdev, struct device *dev);void cdev_del(struct cdev *);void cd_forget(struct inode *);#endif


加载内核模块insmod globalmem.ko 错误需要的修改。

insmod: can't insert 'globalmem.ko': Device or resource busy

出错的原因:

模块使用的是静态分配设备号的方式,而这个设备号已经被系统中的其他设备所占用。查看未被占用的设备号,需要到pro/devices下面去查看。

查看设备号的方法:

# cat /proc/devices

编译内核版本

#uname -a
Linux bsp-ubuntu1804 4.15.0-117-generic #118-Ubuntu SMP Fri Sep 4 20:02:41 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

加载模块之后使用lsmod查看模块

weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo insmod globalmem.koweiqifa@bsp-ubuntu1804:~/c/globalmem$ lsmod |grep global
globalmem              16384  0
weiqifa@bsp-ubuntu1804:~/c/globalmem$weiqifa@bsp-ubuntu1804:~/c/globalmem$ cat /proc/devices |grep global
230 globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$

创建设备文件节点

使用mknod创建设备节点的时候,后面跟上的参数需要跟我们在/proc/devices下面看到的对应,也就是我们在驱动里面申请的主设备号。

weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo mknod /dev/globalmem c 230 0
weiqifa@bsp-ubuntu1804:~/c/globalmem$ ls /dev/globalmem -al
crw-r--r-- 1 root root 230, 0 Dec 22 16:19 /dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$

使用命令读写设备文件

Linux 下的 echo 和cat 命令是十分有用,这两个命令可以让在不写代码的情况下就可以完成调试读写设备。

weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo chmod 777 /dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo echo "linux" > /dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$ cat /dev/globalmem
linux
cat: /dev/globalmem: No such device or address
weiqifa@bsp-ubuntu1804:~/c/globalmem$ cat /dev/globalmem
linux
cat: /dev/globalmem: No such device or address
weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo echo "linuxgdb" > /dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$ cat /dev/globalmem
linuxgdb
cat: /dev/globalmem: No such device or address
weiqifa@bsp-ubuntu1804:~/c/globalmem$

通过代码来读写设备文件

代码在下面阅读原文的链接里面。

weiqifa@bsp-ubuntu1804:~/c/globalmem$ gcc app-main.c && ./a.out
str:LINUX,GDB
weiqifa@bsp-ubuntu1804:~/c/globalmem$

使用传入参数设置主设备号

内核模块参数我觉得是一个比较冷门的知识点,冷门的原因是因为我们在做项目的时候很少使用这个参数,但是实际上这个参数非常有用。

我们可以把内核模块当做main函数,main函数是可以接收传参的,内核模块也可以在加载的时候接收传入的参数。

如下是把主设备号传给内核模块,但是需要注意,这个主设备号不能被占用了。


weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo insmod globalmem.ko globalmem_major=231
weiqifa@bsp-ubuntu1804:~/c/globalmem$ cat /proc/devices |grep globalmem
231 globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$

增加自动创建设备节点的驱动文件

每次手动创建设备文件节点总是很麻烦,而且在实际编写设备驱动的时候,不会出现自己手动创建设备节点这种低端的操作。

当然了,聪明的内核提供了接口让我们在注册驱动的时候也把设备文件节点注册上去。

具体代码可以查看globalmem2.c里面的代码。

weiqifa@bsp-ubuntu1804:~/c/globalmem$ chmod 777 globalmem.ko
weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo insmod globalmem.ko
[sudo] password for weiqifa:
weiqifa@bsp-ubuntu1804:~/c/globalmem$ ls /dev/globalmem
/dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$ ls /dev/globalmem -al
crw------- 1 root root 238, 0 Dec 22 17:18 /dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$/*修改权限后才可以正常进行独写操作*/
weiqifa@bsp-ubuntu1804:~/c/globalmem$ sudo chmod 777 /dev/globalmem
weiqifa@bsp-ubuntu1804:~/c/globalmem$ gcc app-main.c && ./a.out
write data ok!
str:LINUX,GDB
weiqifa@bsp-ubuntu1804:~/c/globalmem$

使用lseek操作文件位置

具体对应的文件是app-main2.c

weiqifa@bsp-ubuntu1804:~/c/globalmem$ gcc app-main2.c && ./a.out
file ret:0
write data ok! fd:3
str:123456789ABCDEF10111213141516171819201617181920
lseek:1
str:23456789ABCDEF10111213141516171819201617181920
weiqifa@bsp-ubuntu1804:~/c/globalmem$

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466745.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8-[函数]-嵌套函数,匿名函数,高阶函数

1.嵌套函数 &#xff08;1&#xff09;多层函数套用 name "Alex"def change_name():name "Alex2"def change_name2():name "Alex3"print("第3层打印", name)change_name2() # 调用内层函数print("第2层打印", name)chan…

Linux C高级编程——时间编程

Linux高级编程——时间编程 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 1 时间类型 &#xff08;1&#xff09; 世界标准世界&#xff08;格林威治时间&#xff09; &#xff08;2&#xff09; 日历时间&#xff08;1970年1月1日0时&#xff09;—…

Excel——多个Sheet页合并成一个

import xlrd import pandas as pd from pandas import DataFrame from openpyxl import load_workbookexcel_name 文件路径/文件名.xlsx #表格地址表格名 wb xlrd.open_workbook(excel_name) # 获取workbook中所有的表格 sheets wb.sheet_names() # print(sheets)# 循环遍…

c语言画谢宾斯基三角形

谢宾斯基三角形是一个有意思的图形&#xff0c;&#xff08;英语&#xff1a;Sierpinski triangle&#xff09;是一种分形&#xff0c;由波兰数学家谢尔宾斯基在1915年提出,它是一种典型的自相似集。先画一个三角形&#xff0c;然后呢&#xff0c;取三角形的中点&#xff0c;组…

F-Secure Client Security 注册机

F-Secure Client Security 6.*/7.* 通用注册机&#xff1a;下载地址&#xff1a;http://files.cnblogs.com/boringlamb/Keymaker.rar听说8的beta版已经出来&#xff0c;期待正式版&Keygen :)转载于:https://www.cnblogs.com/boringlamb/archive/2008/04/07/1140540.html

进程间的通信——无名管道

进程间的通信——无名管道 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、进程间的通信 &#xff08;1&#xff09;同主机进程间数据交互机制&#xff1a;无名管道&#xff08;PIPE&#xff09;&#xff0c;有名管道&#xff08;FIFO&#xff09;…

sklearn官网-多分类问题

sklearn实战-乳腺癌细胞数据挖掘&#xff08;博主亲自录制视频&#xff09; https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare 1.12.6. Multioutput classification Mult…

剖析C语言是如何画出这样的三角形的

哈哈&#xff0c;就是喜欢这些有意思的C语言上篇文章是这样写的c语言画谢宾斯基三角形那篇文章写的有点不直接&#xff0c;然后再查了下资料&#xff0c;看到了下面这些&#xff0c;我觉得解释更加好&#xff0c;这里主要是运用了光栅法&#xff0c;至于光栅法&#xff0c;可以…

NILMTK在Windows下的安装教程

近期&#xff0c;要进行负荷辨识&#xff0c;找到NILMTK安装包&#xff0c;特意将过程记录下来。 &#xff08;1&#xff09;Windows安装 本机已安装了Anaconda&#xff0c;环境是Python3&#xff0c;NILMTK包的项目地址为&#xff1a;https://github.com/nilmtk/nilm_metada…

who|sort实现

who|sort实现 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 创建无名管道&#xff0c;执行who命令的进程将输出重定向到管道的写端&#xff1b;执行sort命令的进程将输入重定向到管道的读端。即who的输出连接到sort的输入。 #include <stdio.h>…

修改cmdline 把内存改成512MB

#添加cmdline的方式— — 在BoardConfig.mk中修改device/mediateksample/aiv8167sm3_bsp/BoardConfig.mk BOARD_KERNEL_CMDLINE bootopt64S3,32N2,32N2 mem512MB— — 在dts 里面修改kernel-4.4\arch\arm\boot\dts\*.dts / {model "Atmel AT91SAM9M10G45-EK";compa…

selenium webdriver模拟鼠标键盘操作

在测试使用Selenium webdriver测试WEB系统的时候&#xff0c;用到了模拟鼠标、键盘的一些输入操作。 1、鼠标的左键点击、双击、拖拽、右键点击等&#xff1b; 2、键盘的回车、回退、空格、ctrl、alt、shift等&#xff1b; 在webdriver中&#xff0c;有专门的一个类&#xff0c…

NILMTK——经典数据集REDD介绍和使用

配置了NILMTK包的环境之后&#xff0c;想找数据测试一下&#xff0c;在NILMTK官网的API Docs里边发现dataset_converters模块中有内置的数据集处理函数&#xff0c;如图&#xff1a; 将数据转换成HDF文件&#xff0c;这些数据都是比较优秀的&#xff0c;其中&#xff0c;常用的…

[转]ASP中ActiveX控件的内嵌及调用

懂ASP&#xff08;Active Server Pages&#xff09;的人很多&#xff0c;但能用ASP自如地调用ActiveX控件的人却不多&#xff1b;如果不调用ActiveX控件&#xff0c;则可以说微软当初设计ASP的初衷根本没有达到。众所周知&#xff0c;ActiveX技术是微软在Internet上除了IE外的另…

Linux C实现简单的shell

Linux C下实现简单的Shell 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 【需求描述】 用各种C函数实现一个简单的交互式Shell&#xff1a; 1、给出提示符&#xff0c;让用户输入一行命令&#xff0c;识别程序名和参数并调用适当的exec函数执行程序…

上拉电阻的作用

1、介绍使用微控制器&#xff08;MCUs&#xff09; 或任何数字逻辑设备时&#xff0c;上拉电阻器非常常见。本教程将解释何时何地使用上拉电阻器&#xff0c;然后我们将做一个简单的计算&#xff0c;以显示为什么上拉很重要。2、上拉电阻是什么&#xff1f;假设您有一个将一个引…

NILMTK——深扒组合优化(CO)和FHMM细节

前面的博客讲了具体实现&#xff0c;现在深究算法代码实现细节&#xff01;&#xff01;&#xff01; 1.CO (1)关于train 从以下代码可知&#xff0c;CO首先是对各个电器的功率数据做了train&#xff0c;为了了解其原生实现对代码进行了深究&#xff1a; classifiers {CO:…

Python关键字

and  as  assert  break  class  continue   def  del  elif  else  except  exec  finally   for  from  global  if  import  in  is  lambda not  or  pass  print  raise  return  try while  with  yield  Non…

对51CTO的初步看法

决定给自己见一个技术博客之后&#xff0c;在网上搜了一下&#xff0c;发现了51CTO网站&#xff0c;进入之后发现网速够快&#xff0c;有尝试了博客的功能&#xff0c;也基本满足了我的要求&#xff0c;那就是它了&#xff0c;于是我就在51CTO安家了。写了两片共近千字的文章之…

深圳工资指导价出炉!最高月薪6万!你拖同行后腿了吗?

2020 年只剩下不到一个月了&#xff0c;年初立的 flag 有没有实现呢&#xff1f;我想多数人面临的尴尬是升职、加薪、赢取白富美、走上人生巅峰可能一步都没实现~对比周围混得风生水起的小伙伴感觉自己也不差啥啊&#xff0c;怎么就莫名其妙被甩了八条街&#xff1f;想一探究竟…