深入浅出linux驱动,Linux Kernel 字符驱动的深入浅出讲解
注:在写Linux 内核驱动,并将这一过程发生的技术,和菜鸟们可能会碰的问题进行一次解释,希望对后来都有用,阅读此文需要一定Linux基础,或者不要浪费时间,好品德看完全文要顶一下,看完此文你应该肻定会开发自己的字符驱动,请注意注解部分。
我反着来讲整个过程,讲解是为让人更快明白,有些术语不是标准的哦,对于正在找这个朋友此文就是你的宝,如果你乐意你可以给我付费。
第一步:内核加入到你设备中,整个调用驱动过程代码以下
MyTest::MyTest(QWidget *parent, const char *name, WFlags f):led(parent, name, f)
{
/*1.int m_fd 是句柄 WIN32的名词 类的私有变量。private: int m_fd;
2.:: 这是名字空间符
3.open Linux打开设备的系统function
4. "/dev/pwcs", 这句话的解释 /dev 表示linux系统驱动 可以指示 内核工程中 如图
/pwcs 自定义的设备名称
5. O_RDWR 系统标准备读写宏
*/
m_fd = ::open("/dev/pwcs", O_RDWR); //..打开设备.
if (m_fd < 0) {
//..没有打开设备
}
/*1.connect 系统函数
2.0,1,这些指驱动自定义要控制设备的系列号 ,
3.SIGNAL(什么事件)
4.this 这是什么呀,自己查去
5.SLOT(事件动作)
*/
connect(0, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) ); //..
connect(1, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) );
//.......可以有很多
checkBoxClicked();
}
MyTest::~MyTest()
{
::close(m_fd); //..关闭设备
}
void MyTest::checkBoxClicked()
{
/* ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的参数个数如下:int ioctl(int fd, int cmd, …);其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数控制设备的I/O通道。
*/
::ioctl(m_fd, int(m_pwc1->isChecked()), 0);
::ioctl(m_fd, int(m_pwc2->isChecked()), 1);
::ioctl(m_fd, int(m_pwc3->isChecked()), 2);
::ioctl(m_fd, int(m_pwc4->isChecked()), 3);
}
}
第二步:增加内核驱动控制代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #include
#include
#include
#define DEVICE_NAME "pwcs" //..注意这里 m_fd = ::open("/dev/pwcs", O_RDWR); 打开设备.
/*
connect(0, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) ); //..
connect(1, SIGNAL(clicked()), this, SLOT(checkBoxClicked()) );
S3C64XX_GPK(XX) 来自这里 \u-kernel\arch\arm\mach-s3c64xx\include\mach\gpio.h
*/
static int power_gpios[] = {
S3C64XX_GPK(0), //..设备中要控制CPU的GPIO :0 connect自定义要控制设备的系列号
S3C64XX_GPF(14), //.. :1 connect自定义要控制设备的系列号
S3C64XX_GPA(2), //.. :2 connect自定义要控制设备的系列号
S3C64XX_GPF(13), //.. :3 connect自定义要控制设备的系列号
S3C64XX_GPK(1), //.. :4 connect自定义要控制设备的系列号
};
#define PW_GPIO_NUM ARRAY_SIZE(power_gpios) //..数组大小
static long power_gpio_ctrls_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
switch(cmd) {
case 0:
case 1:
if (arg > PW_GPIO_NUM) {
return -EINVAL;
}
gpio_set_value(power_gpios[arg], cmd); //..\u-kernel\arch\arm\mach-s3c64xx\include\mach\gpio.h
//printk(DEVICE_NAME": %d %d\n", arg, cmd);
break;
default:
return -EINVAL;
}
return 0;
}
static struct file_operations power_gpio_ctrl_dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = power_gpio_ctrls_ioctl,
};
static struct miscdevice power_gpio_ctrl_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME, //..注意这里
.fops = &power_gpio_ctrl_dev_fops,
};
static int __init power_gpio_ctrl_dev_init(void) {
int ret;
int i;
for (i = 0; i < PW_GPIO_NUM; i++) {
ret = gpio_request(power_gpios, "PWC"); //..用户控制符 “PWC”注册时用
if (ret) {
printk("%s: request GPIO %d for ctrl failed, ret = %d\n", DEVICE_NAME,
power_gpios, ret);
return ret;
}
s3c_gpio_cfgpin(power_gpios, S3C_GPIO_OUTPUT);
gpio_set_value(power_gpios, 0);
}
ret = misc_register(&power_gpio_ctrl_dev); //..注册
printk(DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit power_gpio_ctrl_dev_exit(void) {
int i;
for (i = 0; i < PW_GPIO_NUM; i++) {
gpio_free(power_gpios);
}
misc_deregister(&power_gpio_ctrl_dev); //..干掉它
}
module_init(power_gpio_ctrl_dev_init); //..模块初始化 给open用的
module_exit(power_gpio_ctrl_dev_exit); //..模块初退出 给close用的
MODULE_LICENSE("GPL"); //..模块许可授权 注意这个是必须的或者注册不了,其它方式我不说了,
//..给钱告 诉你。
MODULE_AUTHOR("IFOCOOL@QQ.COM"); //..作者信息
第三步:使用make menuconfig 可以看到.
source "drivers/char/Kconfig" 在内核配置菜单Kconfig文件中增加以下内容注意以下两个图
在drivers/char/Kconfig的文件 menu "Character devices" 菜单下增加以下内容
config POWER_CTRL #配置关键字
tristate "GPIO Power On/Off Ctrl" #这段菜单名称
depends on CPU_S3C6410 #depends on CPU_S3C6410 表示还要这个菜单项前“CPU_S3C6410”看我写的LINUX
#专题里面有讲到。
default y #默为y
在drivers/char/Makefile的文件 增加以下内容
obj-$(CONFIG_POWER_CTRL) += power_gpio_ctrl.o #C文件编绎后目标文件 power_gpio_ctrl.c的目标文件
#CONFIG_POWER_CTRL=CONFIG+POWER_CTRL(注:这来自
Kconfig)
第四步:必须完成第三步后执行这一步
linux 命令台中执行: make menuconfig
进行字符驱动选择菜单如图
最后一步make内核
深入浅出linux驱动,Linux Kernel 字符驱动的深入浅出讲解相关推荐
- linux驱动程序开发指南-字符驱动介绍
概述: 在linux系统中设备驱动程序通常是作为应用层和设备层的中间层软件,驱动程序的主要功能是实现应用层访问硬件设备的具体操作接口,通过调用驱动程序,上层应用程序可以采用统一的接口访问各种硬件设备. ...
- linux驱动初探之字符驱动
关键字:字符驱动.动态生成设备节点.helloworld linux驱动编程,个人觉得第一件事就是配置好平台文件,这里以字符设备,也就是传说中的helloworld为例~ 此驱动程序基于linux3. ...
- 设备驱动基础学习--字符驱动实现
1.标识设备文件 当我们ls -l /dev/sd{a,b} /dev/ttyS{0,1}时, 可以看到,设备文件和普通文件区别不大,主要差异在于: 1)设备类型为b.c,分别表示块设备和字符设备. ...
- Linux字符驱动开发学习总结
linux驱动编写(虚拟字符设备编写) 昨天我们说了一些简单模块编写方法,但是终归没有涉及到设备的编写内容,今天我们就可以了解一下相关方面的内容,并且用一个实例来说明在linux上面设备是如何编写的. ...
- Linux字符驱动中动态分配设备号与动态生成设备节点
在编写Linux内核驱动程序的时候,如果不动态生成设备号的话,需要自己手动分配设备号,有可能你分配的设备号会与已有设备号相同而产生冲突.因此推荐自动分配设备号.使用下面的函数: int alloc_c ...
- linux字符驱动之点亮LED
上一节中,我们讲解了如何自动创建设备节点,这一节我们在上一节的基础上,实现点亮LED. 上一节文章链接:https://blog.csdn.net/qq_37659294/article/detail ...
- linux字符驱动之概念介绍
一.字符驱动框架 问:应用程序open.read.write如何找到驱动程序的open.read.write函数? 答:应用程序的open.read.write是在C库里面实现的,它里面通过swi v ...
- Linux内核驱动如何编写?我们先从字符驱动入门开始
几年前正式转到linux开发岗位的时候,由于项目急需编写linux驱动来控制项目采集设备(板卡),我便被安排做这一部分工作.那时候挺慌的-,在之前的一年多时间里基本都是window应用开发,对于lin ...
- linux Pci字符驱动基本加载流程
今天有朋友问我linux系统Pci字符驱动加载流程,简单整理了一下,顺便做个记录. 首先说下需要包含的头文件: 一个完整的字符驱动一般包含下面这些头文件: #include <linux/typ ...
最新文章
- Spring3.x中各个jar包的作用总结
- linux 占用缓存前10_Linux 中的零拷贝技术
- 无法创建文件系统以及无法创建PV时怎么办?
- 【机器学习】那些决定模型上限的操作
- 修改服务器ssh登录超时时间
- Android 软键盘盖住输入框的问题
- nginx支持php5,配置nginx支持php
- Hash函数加密算法(一)
- HDU-ACM-2041
- Linux ubuntu基本知识
- 第九十八节,JavaScript语法、关键保留字及变量
- oracle中asm是什么,什么是ASM?
- 史上最全的vue.js源码解析(一)
- div+css网页html成品学生作业包含10个html页面——动漫主题海贼王
- 总结一下面试中经常被问到的面试题,希望对各位初中级同胞有用。
- iOS11及iPhone X适配
- 什么时候找客户聊天才是最佳时间呢?
- 520,都来被虐吧。。。
- php notice 影响,PHP notice/warning 对性能的影响
- html调整上下的间距,html上下间距怎么调
热门文章
- 中国区块链开发者的热血时代来临!
- Python还能走多远?
- 谷歌宕机,只有运维背锅吗?
- 从 Web1.0 到 3.0 你不知道的互联网的演进史!
- 在家想远程公司电脑?Python + 微信一键连接!
- “刘强东案”细节流出;小米或全球首发5G手机;罗永浩密会纳德拉;| 极客头条...
- 互联网之“死”:为什么开发者会排斥新技术?
- 水逆的美团滴滴与头条
- 2017 科技大事件回顾:智能音箱大战、数据泄露于内贼
- mysql配置环境变量,进阶加薪全靠它!