一、驱动器标签太长,或包含无效字符?
一、细节提要
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)
二、安装路径包含无效字符怎么解决?
原因:1.“Windows”文件夹中的“temp”文件被删或被修改。
2.解决方法:鼠标右击桌面,新建文件夹将其重命名为“temp”,将这个“temp”文件移动到“Windows”文件夹中即可。(“Windows”文件夹包含很多系统文件,不要轻易删除或修改)。
3.temp是临时文件夹,在C:\Documents and Settings\Administrator\LocalSettings\内。很多临时文件放在这里,收藏夹,浏览网页的临时文件,编辑文件等。这是根据操作的过程进行临时保存的。
三、ps注册,提示姓氏包含无效字符?
仅使用英文字母和数字,不要用符号和汉字
四、静态IP地址设置无效?
IP地址资源有限,不可能给每个开通宽带的用户都分配一个IP地址,IP地址是随机分配使用的。
你的静态IP突然上不了网的原因很简单,因为你指定的IP地址,在你不上网时把路由器关掉以后,这个IP地址被别的电脑使用了,所以你以后重新再开机后,就不能上网了。
如果你一定要使用静态IP地址,你可以购买。
网吧的IP地址是固定的,因为他花钱了。
五、什么是无效ip地址?
无效iP地址意思是设定地址是错误的
六、ip地址无效怎么算?
输入的IP地址错误。一个合法的IP地址,它的范围是在0~255。如果配置的ip地址不在这个范围内,就是一个无效的ip地址,不能使用。 IP地址需要结合子网掩码来使用。如果划分了子网,子网所拥有的地址范围是确定的,如果输入了一个不在这个范围的地址,也是一个无效的地址。
七、起始ip地址无效
当您尝试配置网络设备时,经常会遇到起始ip地址无效的问题。这可能会导致设备无法正常连接到网络,导致网络传输异常或连接失败。在网络设置中,正确配置起始ip地址对于设备的正常运行至关重要。
什么是起始ip地址无效?
起始ip地址无效是指在网络配置中所设置的起始ip地址无法被网络设备正确识别或使用。这可能是因为ip地址格式错误、与其他设备冲突或网络配置错误等原因导致的。
如何解决起始ip地址无效的问题?
1. 首先,确保您输入的ip地址格式正确无误。ip地址应由四组数字组成,每组数字范围在0~255之间,且用"."分隔开。
2. 检查网络中是否存在与您设置的ip地址相同的设备。确保ip地址唯一,避免与其他设备发生冲突。
3. 检查网络配置信息,确保子网掩码、网关等信息与ip地址设置相匹配,保证网络连接顺畅。
常见错误示例
以下是一些常见的导致起始ip地址无效的错误示例:
- ip地址格式错误,如超出0~255的范围、少于四组数字、没有用"."分隔等。
- ip地址与其他设备冲突,导致网络无法正常工作。
- 网络配置信息错误,如子网掩码设置错误、网关配置错误等。
解决方案案例分析
以下是一个解决起始ip地址无效问题的案例分析:
某公司网络管理员在配置新设备时遇到起始ip地址无效的问题。经过检查发现,他输入的ip地址格式有误,少了一组数字。在纠正错误后,设备成功连接到网络,问题得到解决。
总结
在网络配置过程中,遇到起始ip地址无效问题并不罕见。关键在于仔细检查ip地址设置,确保格式正确、唯一性和与网络配置匹配。只有正确配置ip地址,网络设备才能正常工作,确保网络连接畅通。
八、hosts 无效 ip地址
hosts 文件是一个没有扩展名的计算机文件,它可以被操作系统用来映射域名和 IP 地址。在大多数操作系统中,这个文件位于一个特定的目录中,其中包含了主机名到 IP 地址的映射。但是有时候,用户可能会遇到无效或者错误的ip地址的情况。
何为无效的 IP 地址?
无效的 IP 地址是指不符合 IP 地址规范的地址,或者是不存在的地址。在网络通讯中,IP 地址必须是唯一的且经过验证有效的,否则通讯可能会遇到问题。常见的无效 IP 地址包括格式不正确的地址、不存在的地址或者被禁止使用的地址。
hosts 文件中的 IP 地址问题
在一些情况下,用户可能会编辑 hosts 文件,将一些域名与 IP 地址进行映射,这样可以绕过 DNS 解析的过程,加快访问速度。然而,如果用户在 hosts 文件中使用了无效的 IP 地址,就会导致一些访问问题。
当操作系统查找某个域名所对应的 IP 地址时,会首先在 hosts 文件中查找,如果找到了对应的 IP 地址,就会直接使用这个地址进行访问。如果 hosts 文件中的 IP 地址是无效的,那么就会导致无法正常访问该域名,或者出现访问异常的情况。
处理 hosts 文件中的无效 IP 地址
为了避免因为 hosts 文件中存在无效的 IP 地址而导致访问问题,用户可以定期检查和更新 hosts 文件。确保其中的 IP 地址是正确的、有效的,不含有任何明显的错误。
另外,如果用户遇到访问问题,可以尝试暂时性地注释掉 hosts 文件中的某些条目,然后重新访问,看是否问题得到解决。这样可以排除是否是 hosts 文件中的无效 IP 地址导致的问题。
最佳实践
在编辑 hosts 文件时,建议用户谨慎操作,确保每个域名和 IP 地址的映射都是正确的。避免使用不确定的、来源不明的 IP 地址,以免造成访问问题。另外,建议定期检查 hosts 文件,及时更新其中的映射信息,保证网络访问的顺畅和安全。
总的来说,hosts 文件在网络通讯中起着重要的作用,但是同时也需要注意其中的信息是否正确有效,避免因为无效的 IP 地址而导致访问问题。合理管理 hosts 文件可以更好地保障网络通讯的稳定性和安全性。
九、静态ip地址无效
在网络主机配置中,静态IP地址无效是一种常见的问题,通常会导致设备无法正常连接到网络或互联网。静态IP地址是指管理员手动为设备分配的固定IP地址,与动态IP地址不同,它不会在每次连接到网络时自动分配。当静态IP地址出现问题时,可能会导致网络通信失败、设备无法被识别或访问权限受限等情况。
可能导致静态IP地址无效的原因
静态IP地址无法正常工作的原因各有不同,主要包括以下几个方面:
- 1. IP地址冲突:如果多台设备在同一网络上使用了相同的静态IP地址,就会导致IP地址冲突,进而使其中一台设备无法正常连接。
- 2. 子网掩码设置错误:子网掩码用于区分网络号和主机号,如果子网掩码设置不正确,设备可能无法正确识别网络中其他设备。
- 3. 网关配置错误:网关是设备连接到其他网络或互联网的关键,如果网关设置错误,设备将无法进行外部通信。
- 4. DNS配置问题:DNS服务器用于将域名解析为IP地址,如果DNS配置错误,设备无法正常访问互联网。
如何解决静态IP地址无效的问题
针对静态IP地址无效的问题,可以按照以下步骤逐一排查并解决:
- 1. 检查IP地址设置:确保设备的静态IP地址与网络中其他设备不发生冲突,且IP地址、子网掩码、网关地址等参数设置正确。
- 2. 检查网线连接:确保网线连接稳固,没有松动或断裂,以确保设备能够正常连接到网络。
- 3. 重启设备:有时简单的重启设备就可以解决网络连接问题,尝试重启设备并检查是否恢复正常。
- 4. 检查网络设置:检查路由器、交换机等网络设备的设置,确保网络设备正常工作并能够正常转发数据。
通过逐一检查上述步骤,可以大致确定静态IP地址无效的原因所在,并采取相应措施进行解决。在处理网络问题时,及时定位并解决问题是保障网络稳定性和安全性的重要步骤。
结语
静态IP地址无效是网络配置中常见的问题,但通过逐步排查和解决,大部分情况下都可以顺利解决。在日常维护中,建议定期检查网络设备的配置,并确保各项参数设置正确,以确保网络的正常运行。
十、海康ip地址无效
在网络监控系统中,海康ip地址无效问题是常见的挑战之一。海康威视作为全球领先的视频监控解决方案提供商,其产品广泛应用于各种场景,包括企业、政府、学校等。然而,有时用户可能会遇到IP地址无效的情况,导致监控设备无法正常工作。
为什么会出现海康IP地址无效的问题?
要解决这个问题,首先需要理解可能导致IP地址无效的原因。可能的原因包括:
- 网络连接问题:网络中断、网线故障等可能导致IP地址无效。
- IP地址设置错误:IP地址、子网掩码、网关等设置不正确会导致IP地址无效。
- DHCP配置问题:动态IP获取失败也可能导致IP地址无效。
如何解决海康IP地址无效的问题?
一旦发现IP地址无效的情况,用户可以尝试以下方法来解决问题:
- 检查网络连接:确保网络连接正常,网线连接稳固。
- 检查IP地址设置:确认设备IP地址、子网掩码、网关等设置正确。
- 重启设备:有时候简单的重启操作可以解决IP地址无效的问题。
- 重置网络配置:重置设备的网络配置,重新进行网络设置。
海康IP地址无效问题的解决技巧
除了上述常规方法外,还有一些技巧可以帮助用户更快速地解决IP地址无效问题:
- 固定IP地址:考虑设置固定IP地址而非动态获取,可以避免DHCP配置问题。
- 网络诊断工具:使用网络诊断工具检测网络连接和IP地址设置。
- 固件更新:及时更新监控设备的固件,修复可能存在的问题。
结语
在使用海康监控设备时,遇到IP地址无效的情况并不罕见。通过仔细排查可能的原因,并采取有效的解决方法,用户可以解决这一问题,确保监控系统的正常运行。
- 相关评论
- 我要评论
-