一、驱动器标签太长,或包含无效字符?
一、细节提要
1、与用户与内核数据交换有关的函数(1)copy_from_user()函数
该将数据从用户空间复制到内核空间。
如果成功复制则返回0,如果不成功复制则返回尚未成功复制的剩下的字节数。
(2)copy_to_user()函数
将数据从内核空间复制到用户空间。
(3)复制机制与使用mmap的对比
复制时,内核空间和用户空间的地址不一样,效率低。
好文推荐:
一文让你读懂Linux五大模块内核源码,内核整体架构设计(超详细)
全网独一无二Linux内核Makefle系统文件详解(一)(纯文字代码)
一篇文带你搞懂,虚拟内存、内存分页、分段、段页式内存管理(超详细)
2、代码逻辑图
二、代码示例
1、代码编写
在ubuntu的/home/xjh/iot/embedded_basic/rootfs/tmp中编写代码:app.c与module_test.c。
2、代码编译
(1)编译驱动源代码
利用同目录下的Makefile文件编译module_test.c,得到module_test.ko驱动文件。
(2)编译应用层程序
怎样编译app.c?使用ubuntu的gcc还是交叉编译工具链?或者和驱动源代码一样的操作(这个如何完成编译的)?
因为此应用层程序要在开发板运行,因此需要使用交叉编译工具链中的gcc来编译,而不是 ubuntu 中的gcc。
在已经正确安装了交叉编译工具链的ubuntu系统中,使用如下命令编译app.c得到app.exe。
arm-linux-gcc app.c -o app.exe
因为之前实验中已经将ubuntu的/home/xjh/iot/embedded_basic/rootfs/tmp挂载到开发板/mnt目录,所以开发板完全启动后,可以在/mnt目录中看到刚才编译的文件。
3、代码测试
可以直接在开发板的/mnt目录下进行测试。
(1)装载测试
[root@xjh mnt]# lsmod
Not tainted
[root@xjh mnt]# insmod module_test.ko //安装模块
[ 5278.035378] chrdev_init helloworld init
[ 5278.038524] register_chrdev success... mymajor = 250.//自动分配的主设备号为250
[root@xjh mnt]# lsmod //列出已经安装的模块
Not tainted
module_test 1823 0 - Live 0xbf006000//这个具体表示什么意思?
[root@xjh mnt]#
装载后查看/proc/devices,是否有驱动源码中所写的驱动名字、自动分配的主设备号。
[root@xjh mnt]# cat /proc/devices
Character devices:
1 mem
2 pty
//省略……
250 testchar //这里出现了我们在驱动程序中给驱动取的名字、自动分配的主设备号
//省略……
Block devices:
1 ramdisk
259 blkext
//省略……
179 mmc
254 device-mapper
(2)创建设备文件
[root@xjh mnt]# cd /dev
[root@xjh dev]# ls
CEC ptyr6 sequencer2 ttyq5
HPD ptyr7 snd ttyq6
adc ptyr8 tty ttyq7
//省略……这里没有test这设备文件。
//接下来看执行“mknod /dev/test c 250 126”之后的效果如何
[root@xjh dev]#
[root@xjh ]# mknod /dev/test c 250 1
[root@xjh ]# ls /dev
CEC ptyr6 sequencer2 ttyq4
HPD ptyr7 snd ttyq5
adc ptyr8 test //出现了设备文件test tyq6
alarm ptyr9 tty ttyq7
//省略……
[root@xjh ]# ls -l /dev/test
crw-r--r-- 1 root root 250, 126 Jan 1 14:02 /dev/test
[root@xjh ]# //主设备号 //次设备号 和mknod时的设置一样
(3)操作设备文件
运行应用层程序app.exe,观察运行效果。
[root@xjh mnt]# ./app.exe
[ 1587.469172] test_chrdev_open
[ 1587.470769] test_chrdev_write
[ 1587.473521] copy_from_user success..
[ 1587.477106] test_chrdev_read
[ 1587.479949] copy_to_user success..
[ 1587.483352] test_chrdev_release
open /dev/test success.. //这是应用层的判断是否open成功的代码,为何那么迟才输出?
璇诲嚭鏉ョ殑鍐呭鏄細helloworld2222. //为何乱码,scrt的缘故?
[root@xjh mnt]#
【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!
点击报名免费内核学习直播课程:
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639ke.qq.com/course/4032547?flowToken=1042639说明
1)Linux系统字符编码默认是UTF-8格式的,如果SecureCRT没有设置成UTF-8格式,中文显示会出现乱码。设置SCRT格式的方法见博客:SecureCRT显示乱码的解决办法
2)为何应用层判断是否open成功的代码很迟才输出?(待解决)
(4)卸载模块测试
[root@xjh mnt]# rmmod module_test.ko
[ 1385.257231] chrdev_exit helloworld exit
[root@xjh mnt]# lsmod
Not tainted
[root@xjh mnt]#
4、总结说明
(1)应用层的代码编译,要使用交叉编译工具链。
(2)驱动源代码的编译,要使用与开发板系统内核版本一致的内核源码进行编译。其实应该还是借用ubuntu的 gcc工具来进行编译的,因为内核源码中没有gcc编译器。Makefile 文件指明要进入这个与开发板系统内核版本一致的内核源码中,然后make modules。这说明是根据内核源码中的Makefile文件的指示,执行Makefile文件中的一个目标modules。
//在Makefile的1300行
modules: $(module-dirs)
@$(kecho) ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
(3)mymajor = register_chrdev(0, MYNAME, &test_fops);
参数 0 表示让系统自动分配主设备号。
参数MYNAME表示设备(或者说驱动)的名字。
参数&test_fops是指向struct file_operations变量的指针,这个变量代表着驱动的实质内容。
返回值mymajor代表系统为设备分配的主设备号。
/proc/devices文件记录着系统中已经注册的块设备和字符设备。可以通过cat或者vim(但只能读不能修改)来查看此文件内容。注册成功后,可以通过/proc/devices文件查看到该设备的名字MYNAME及其设备号mymajor。
此函数成功后,主设备号为mymajor的设备与它的驱动内容&test_fops就关联起来了,也就是说一个设备对应了一个驱动内容。那在应用层如何表示这个设备呢?见(4)。
(4)/dev/test是设备文件,是命令行中使用mknod命令创建的。安装好驱动模块后,得到系统分配的主设备号mymajor(这里是250)。然后利用这个主设备号来创建设备文件,即执行“mknod /dev/test c 250 126”。这样一来,主次设备号为250、126的设备就和设备文件/dev/test关联了,应用层通过API操作/dev/test文件,也就是操作主次设备号为250、126的设备,而应用层操作里的API就对应着这个设备对应的驱动&test_fops。
设备文件不能使用vim打开,可以使用ls -l 命令查看。
综合(3)(4),主次设备号、设备名字、驱动内容、设备文件,这几个概念要清楚。
主次设备号:主设备号是register_chrdev()的返回值mymajor,次设备号在mknod时设定。
设备名字:MYNAME (主设备号、设备名字在/proc/devices文件中)
驱动内容:&test_fops (程序猿在驱动源代码中编写)
设备文件:/dev/test,利用mknod命令手动创建
(5)设备文件是手动创建的,能不能让它自动创建呢?字符设备驱动高级篇4——自动创建设备文件的函数代码分析_天糊土的博客-CSDN博客
(6)应用层的open、read等API,与驱动源码的test_chrdev_open、test_chrdev_read等具体操作函数,通过struct file_operations的填充而关联起来。不过这里的驱动源码中的test_chrdev_open、test_chrdev_read等具体操作函数,并没有做什么事情,按理应该操作一些硬件的。这里只是为了演示应用层读写操作与驱动层的读写如何关联起来的,因而没有硬件操作细节(比如硬件寄存器操作这些行为)。
关于具体的硬件操作见:字符设备驱动基础5——驱动如何操控硬件(动静态映射操作LED)
1、应用层代码:app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//这是应用层
#define FILE "/dev/test"
//“/dev/test”是利用mknod手工创建的设备文件,创建之后,
//这个设备文件就和该设备编号的设备对应上了,操作此设备文件就是操作该设备。
//问题是mknod需要输入主设备号,和驱动源码中自动获取的主设备号不相冲突吗?
//不冲突,因为这里就是根据驱动程序安装后得到的主设备号后
//才利用这个主设备号来创建设备文件的。我理解顺序相反了。
//应该驱动程序安装在前,应用程序运行在后。
char buf[100];
int main(void)
{
int fd = -1;
fd = open(FILE, O_RDWR);//这里的open,对应的是驱动文件中的.open指定的函数
if (fd < 0)
{
printf("open %s error.\n", FILE);
return -1;
}
printf("open %s success..\n", FILE);
// 读写文件
write(fd, "helloworld2222", 14);
read(fd, buf, 100);
printf("读出来的内容是:%s.\n", buf);
// 关闭文件
close(fd);
return 0;
}
2、驱动文件:module_test.c
#include <linux/module.h> // module_init module_exit
#include <linux/init.h> // __init __exit
#include <linux/fs.h>
#include <asm/uaccess.h>
#define MYNAME "testchar"
int mymajor; //内核自动分配的主设备号
char kbuf[100]; //内核空间(即驱动空间,毕竟内核和驱动属于同一层)的buf
static int test_chrdev_open(struct inode *inode, struct file *file)
{
// 这个函数中真正应该放置的是打开这个设备的硬件操作代码部分
// 但是现在暂时我们写不了这么多,所以用一个printk打印个信息来做代表。
printk(KERN_INFO "test_chrdev_open\n");
return 0;
}
static int test_chrdev_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "test_chrdev_release\n");
return 0;
}
//读函数,即从内核空间(驱动空间)读取数据到用户空间
ssize_t test_chrdev_read(struct file *file, char __user *ubuf, \
size_t count, loff_t *ppos)
{
int ret = -1;
printk(KERN_INFO "test_chrdev_read\n");
//将内容从内核空间(驱动空间)读取到用户空间
//返回值为0说明读取成功,读取不成功时返回值是剩余没有读取的字节数
ret = copy_to_user(ubuf, kbuf, count);
if (ret)
{
printk(KERN_ERR "copy_to_user fail\n");
return -EINVAL;
}
printk(KERN_INFO "copy_to_user success..\n");
导读-最新发表 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛 (0voice.com)
原文地址:一文讲解字符设备驱动基础——读写接口的操作实践 - 圈点 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛 (0voice.com)
二、aoc驱动安装教程?
一:先卸载原有驱动,卸载方法:我的电脑——属性——硬件——设备管理器——显示卡——双击谈出显卡属性——驱动程序——卸载二:然后安装新的显示器驱动.方法一:买电脑的时候送的有光盘,插入光驱自动安装就行.方法二:去网上按显示器型号下载一个驱动安装.方法三:直接用驱动人生之类的驱动软件自动检测安装。
三、驱动总裁封装教程?
以下是驱动总裁封装教程的步骤:
步骤1:安装驱动总裁
首先,您需要在您的计算机上安装驱动总裁软件。您可以从驱动总裁的官方网站下载最新版本的驱动总裁软件,并按照安装向导进行安装。
步骤2:打开驱动总裁并选择封装
打开驱动总裁软件,并选择左侧导航栏中的“驱动封装”选项。然后,单击“选择文件”按钮,并选择要封装的驱动文件。
步骤3:配置封装选项
在驱动封装窗口中,您可以设置封装选项。您可以选择要创建的封装类型和压缩格式。您还可以设置封装文件的名称和保存路径。
步骤4:开始封装
配置完封装选项后,单击“开始封装”按钮开始封装。驱动总裁将创建一个封装文件,并将驱动文件和相关组件打包到封装文件中。
步骤5:完成封装
封装过程完成后,您可以在提示框中看到封装文件的保存路径。单击“确定”按钮完成封装。
以上就是驱动总裁封装教程的步骤。使用驱动总裁封装工具,您可以轻松地封装和打包驱动文件,并将其方便地共享给其他用户。
四、声卡驱动安装教程?
以360驱动大师为例。打开“360驱动大师”软件,它会自动扫描未安装的驱动,我们可以看见有两个声卡驱动等待安装。点击“一键安装”进行驱动安装。
驱动安装完成后重启一下电脑,重启之后打开:打开我的电脑→属性→设备管理器。设备管理器里的声卡上的黄色感叹号不见了,就说明声卡驱动已经安装好了。
五、office驱动安装教程?
安装Office打印机驱动程序需要以下步骤:
1.首先,确认您的Office打印机与计算机相连接,并且已经启动。
2.打开设备管理器。您可以在“控制面板”中找到它,或者直接在“我的电脑”上右键单击,选择“属性”,并点击左侧的“高级系统设置”。
3.选择“设备管理器”,并找到打印机选项。
4.右键单击您的Office打印机并选择“更新驱动程序”。
5.选择“自动搜索更新的驱动程序”。
6.如果有最新的驱动程序,系统将自动下载并安装它。
7.如果没有最新的驱动程序,您可以在制造商的网站上找到它。请确保下载与您的打印机型号完全匹配的驱动程序,并且选择与您的操作系统兼容的驱动程序。
8.下载后,运行安装程序,并按照提示进行安装。在安装过程中,您需要输入打印机的名称和型号,以确保安装程序正确识别打印机。
9.完成安装后,您可以重新启动计算机并测试打印机是否正常工作。
六、gpib驱动安装教程?
首先,安装NI的GPIB的驱动,设置设备的GPIB的地址,代码入加入gpib.lib、ni488.h文件,
ibdev(int board_index, int pad, int sad, int timeout, int eoi, int eos) 打开设备
ibwrt(int ud, void *buf, long count);写数据
ibrd(int ud, void *buf, long count);读数据
七、uln驱动使用教程
uln2003有16个引脚其中有七个输入七个输出,8号引脚接地,9号引脚接12V或5V,比如我用的四相五线步进电机,步进电机公共端接5V,其余四个线接驱动芯片的四个输出端,然后单片机或外围电路接上ULN2003的四个输入引脚,这样挨个给脉冲就能转一定角度,建议你看一下步进电机工作原理,你就知道该怎样写程序了,
八、罗技驱动使用教程?
该罗技驱动使用教程如下:
连接之前要先将g304的接收器取出来,它就在鼠标的电池盖里面,将鼠标上半部分的后半边盖子掀开,里面就可以找到接收器。将这个接收器插在电脑相关的接口上,然后将g304的开关打开,之后等待大约10秒钟的时间,鼠标就会和电脑连接成功。
九、USBASP驱动安装教程?
1、把USBAsp板插在电脑的USB口上,这时会弹出找到硬件向导,点取消即可。
2、下载USBAsp驱动安装包到本地,然后双击安装包
首先出现欢迎界面,不需要关注一路next即可
接着就可以看到安装进度,这时只需要等待安装完毕即可。
等安装程序结束以后,在设备管理器中查看,就会发现USBAsp已经被识别到,可以正常工作了
十、电脑怎么还原驱动?驱动还原教程,还原驱动?
1、打开电脑桌面上的鲁大师应用程序,点击上方的“驱动检测”,如下图所示。
2、再点击“驱动管理”选项,如下图所示。
3、然后再点击“驱动还原”,在驱动列表中选择需要还原的显卡驱动,点击“还原”,显卡驱动会自动还原到之前的版本。
扩展资料:驱动,计算机软件术语,是指驱动计算机里软件的程序。驱动程序全称设备驱动程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。此信息能够使计算机与相应的设备进行通信。驱动程序是硬件厂商根据操作系统编写的配置文件,可以说没有驱动程序,计算机中的硬件就无法工作。