前言 这一部分主要是用来介绍 Linux 设备驱动程序的一些基本概念,包括:Linux 设备驱动程序的作用、内核功能的划分、设备和模块的分类以及版本编号。...一、Linux 设备驱动程序的作用 设备驱动程序就像一个个的“黑盒子”,使某个特定硬件响应一个定义良好的内部编程接口,这些操作完全隐藏了设备的工作细节。...用户的操作通过一组标准化的调用执行,而这些调用独立于特定的驱动程序。将这些调用映射到作用于实际硬件的设备特有操作上,则是设备驱动程序的任务。...这些代码称为设备驱动,内核中必须嵌入系统中出现的每个外设的驱动,从硬盘驱动到键盘和磁带驱动器。 网络 网络必须由操作系统来管理,因为大部分网络操作不是特定于某一个进程:进入系统的报文是异步事件。...三、设备和模块的分类 以 Linux 的方式看待设备可区分为 3 种基本设备类型,每个模块常常实现 3 种类型中的 1 种,因此可分类成字符模块,块模块,或者一个网络模块。
6、打印设备编号 有时当从一个驱动程序打印消息时,我们会希望打印与硬件关联的设备编号。...对设备驱动程序来讲,它没有多少价值,这里包含该函数只是出于完整性考虑。...例如,如果键盘因某种奇怪的原因被锁住了就会发生这种情况。这时,运行专为探明此种情况而设计的程序,通过查看它的输出情况,可以发现这种假的挂起。...从上面的例子看出,第一个 scull 设备目前保存有 20881 字节的数据。如果愿意,我们还可以跟踪数据链,或者查看模块中的其他任何感兴趣的数据。...在这里,我们要查看的是从 scull_devices 指针位置开始的一个字大小(4个字节)的数据;该命令的结果告诉我们,设备数组的起始地址位于 0xd0880de8,而第一个设备结构本身位于 0xcf36ac00
例如我们要操作某个设备,首先,我们要知道设备在/dev下的设备文件名。这个设备文件提供主设备号以及次设备号。然后内核通过设备文件提供的主设备找到设备驱动程序(操作设备由驱动程序实现)。...最后通过主设备号和次设备构成的设备号找到正确的设备。有了操作的对象(设备)和操作的方法(驱动程序)那就可以完成了我们的要求。 一个驱动程序可以操作多个设备,所以不同的设备可以具有相同的主设备号。...在驱动中还可以检查 O_NONBLOCK 标志查看是否有非阻塞请求。其它的标志较少使用。特别地注意的是,读写权限的检查是使用 f_mode 而不是 f_flags 。...cdev_add 一返回,你的设备就是"活的"并且内核可以调用它的操作,因此,在驱动程序还没有完全准备好处理设备上的操作时,就不能调用 cdev_add。...如果想尝试比较简单的字符驱动实现,可以查看我的另一篇驱动开发之 hello 驱动程序实现的文章: 荔枝派Zero(全志V3S)驱动开发之hello驱动程序
gcc helloworld.c -o execFile(此步骤会生成一个execFlie的文件,可用ls查看) 9.运行 ....格式不对 Linux设备驱动程序安装fatal error: linux/module.h: No such file or directory 需要makefile文件 要在Ubuntu中安装整个Linux...内核源代码 sudo apt-get install linux-source
linux显示网卡型号 #kudzu –probe –class=network 范例: [root@localhost ~]# kudzu –probe –class=network – class...1849 subDeviceId: 8136 pciType: 1 pcidom: 0 pcibus: 1 pcidev: 0 pcifn: 0 网卡型号为Realtek RTL8101E 查看硬件所有信息...:dmidecode | more 查看内存信息:dmidecode |grep -A16 “Memory Device”或者dmidecode -t memory 查看CPU型号:cat /proc/
Linux的驱动程序注冊过程,大致分为两个步骤: 模块初始化 驱动程序注冊 以下以内核提供的演示样例代码pci-skeleton.c,具体说明一个pci设备驱动程序的注冊过程。...其它设备的驱动代码注冊过程基本同样,大家可自行查看。使用的内核代码版本号是2.6.38。 1....事实上模块的初始化过程就是这么简单,这也是linux驱动程序的ISO标准流程:module_init–>xx_init_module–>xx_register_driver。...在介绍注冊函数之前,必需要具体说明下linux的总线设备驱动模型,否则以下的内容非常难描写叙述清楚。...2.1 linux总线设备驱动模型 关于总线设备驱动模型,非常多书上都有具体的解说,可是都非常抽象,非常难理解(至少我是这样觉得的)。以下我尽量用最简单的方法来说明相关内容。
一、设置测试系统 我是在虚拟机上进行的开发,查看当前 Linux 系统的内核版本: uname -r 二、Hello World 模块 1、代码详解 hello.c #include <linux/init.h...2、内核的并发 常见引起并发原因: linux 系统中通常正在运行多个并发进程,并且可能有多个进程同时使用我们的驱动程序。...大多数设备能够中断处理器,而中断处理程序异步运行,而且可能在驱动程序正试图处理其他任务时被调用。 linux 可以运行在多处理器上,因此可能同时有多个处理器在使用该进程。...一个精心设计的驱动程序仍然可以,如同内核空间驱动,允许对设备的并行存取。 如果你必须编写一个封闭源码的驱动,用户空间的选项使你容易避免不明朗的许可的情况和改变的内核接口带来的问题。...最重要的设备不能在用户空间处理,包括但不限于网络接口和块设备。 十、快速参考 insmod modprobe rmmod 用户空间工具,加载模块到运行中的内核以及去除它们。
很明显,根据设备的接口,我们可以知道分为usb设备,串口设备,pci设备,spi设备,i2c设备等等,那么在linux内核中又有样的划分呢?...下面所述就是linux中对所有设备的一个分类,并描述了相互之间的简单区别。...linux中设备和模块的分类: 字符设备:字符设备是能够像字节流(类似文件)一样被访问的设备,有字符设备驱动程序来实现这种特性。...linux可以让应用程序向字符设备一样读写块设备,允许一次传递任意多字节的数据。...Linux下的磁盘设备都是块设备,尽管在Linux下有块设备节点,但应用程序一般是通过文件系统及其高速缓存来访问块设备的,而不是直接通过设备节点来读写块设备上的数据。
内核代码是可抢占的;因此,我们的驱动程序代码可能在任何时候丢失对处理器的独占,而拥有处理器的进程可能正在调用我们的驱动程序代码。设备中断是异步事件,也会导致代码的并发执行。...在驱动程序中使用 rwsem 的机会相对较少,但偶尔也比较有用。 使用 rwsem 的代码必须包括 。...通过查看它的输出报告,我们可以很快确定锁竞争是否是问题所在。 七、除了锁之外的办法 1、免锁算法 大量的读取者/写入者情况——如果只有一个写入者——就可以用这种方法来设计我们的算法。...循环缓冲区的使用在设备驱动程序中相当普遍。特别是网络适配器,经常使用循环缓冲区和处理器交换数据(数据包)。 2、原子变量 有时,共享的资源可能恰好是一个简单的整数值。...假定我们的驱动程序维护着一个共享变量 n_op,该变量的值表明有多少个设备操作正在并发地执行。通常,即使下面的简单操作也需要锁定: n_op++; 完整的锁机制对一个简单的整数来讲却显得有些浪费。
目录 示例程序目标 编写驱动程序 编写应用程序 卸载驱动模块 在前几篇文章中,我们一块讨论了:在 Linux 系统中,编写字符设备驱动程序的基本框架,主要是从代码流程和 API 函数这两方面触发。...编写驱动程序 以下所有操作的工作目录,都是与上一篇文章相同的,即:~/tmp/linux-4.15/drivers/。...从代码中可以看出:驱动程序使用 alloc_chrdev_region 函数,来动态注册设备号,并且利用了 Linux 应用层中的 udev 服务,自动在 /dev 目录下创建了设备节点。...还是通过 dmesg 指令来查看驱动模块的打印信息: $ dmesg 可以看到:操作系统为这个设备分配的主设备号是 244,并且也打印了GPIO硬件的初始化函数的调用信息。...来查看一下 /proc/devices 目录下显示的设备号: $ cat /proc/devices 设备已经注册了,主设备号是: 244 。
虽然 lshw 命令( 列出硬件(list hardware),读作 “ls hardware”)远不是每个人最先学会的 50 个 Linux 命令之一,但它可以提供很多系统硬件的有用信息。...注意系统将这个设备命名为了 /dev/sdc。...要获得“磁盘”类设备的简略列表,可以运行下面这条命令。注意其中有两个设备被列出了两次,所以我们看到的仍然是五个磁盘设备。...DVD+-RW GSA-H73N /0/100/1f.5/0.0.0 /dev/sdb disk 500GB SAMSUNG HE502HJ 如果你决定要查看系统上的...,并统计每个类别中的设备数量。
资料下载 coding无法使用浏览器打开,必须用git工具下载: git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git...视频观看 百问网驱动大全 编程_LCD驱动程序框架_使用设备树 参考资料,GIT仓库里: 基于这个程序修改: IMX6ULL\source\03_LCD\03_lcd_drv_qemu_ok STM32MP157...\source\A7\03_LCD\03_lcd_drv_qemu_ok 参考:内核自带的示例驱动程序 Linux驱动源码:drivers/video/fbdev/simplefb.c 设备树:...说明 Linux驱动程序 = 驱动程序框架 + 硬件编程。 在前面已经基于QEMU编写了LCD驱动程序,对LCD驱动程序的框架已经分析清楚。...核心就是: 分配fb_info 设置fb_info 注册fb_info 硬件相关的设置 本节课程我们基于设备树来编写驱动程序。 2. 入口函数注册platform_driver 3.
dmesg # 查看设备号 cat /proc/devices # 创建设备文件 # 格式(c表示字符设备驱动、b表示块设备驱动): mknod /dev/xxx c或者b major minor...查看设备文件信息 ls -l /dev/xxx 最简单的模块 module_test.c #include #include static...可以通过查看/proc/devices文件来确定已经注册了 的字符设备驱动和块设备驱动以及相应的编号 cat /proc/devices unregister_chrdev 从内核卸载字符设备驱动 /*.../* linux/kdev_t.h */ // 传入两个参数生成设备号(dev_t),分别为主设备号和次设备号 MKDEV(ma, mi) // 传入设备号(dev_t),返回主设备号 MAJOR(...dev) // 传入设备号(dev_t),返回次设备号 MINOR(dev) register_chrdev_region 事先知道要使用的主次设备号,需要cat /proc/devices查看未使用的设备号
众所周知,Linux 2.6内核引入了总线驱动模型这一概念,如此,很多基于总线的设备驱动就分成了总线驱动和设备驱动两部分。...当你加载PCI驱动的时候,驱动程序会把系统中已经存在的设备的厂商号和设备号与驱动程序中的对比,如果一致,则会注册PCI总线驱动并进行下一步操作。...下面是我写的一个PCI总线的驱动程序,注意是PCI设备识别时的驱动程序,这里并没有实现具体的功能驱动。...PCI设备的驱动分成两个部分,一部分是总线的,就是PCI设备识别、调用驱动程序probe函数的部分,另一部分就是具体的功能驱动,比如网卡。... #include #include //设备相关 #define MY_VENDOR_ID 0x168c
USB设备驱动程序开发框架 USB设备驱动程序开发框架的源代码文件 文件名 说明 Driver.h 驱动程序头文件 DrvInit.c 入口例程和卸载例程 DrvPnp.c 即插即用例程 DrvDispatch.c...分发例程 DrvPower.c 电源管理例程 Resource.h 资源管理头文件 Resource.rc 版本资源信息 USB设备驱动程序开发框架的构造文件 文件名 说明 DrvBuild.bat
电脑可以外接很多设备,如键盘、鼠标、硬盘、显示器、网卡等,每个设备的用法和功能不同,操作系统为了对这些输入输出设备进行统一管理,必须要屏蔽设备之间的差异,因此需要设备控制器。 设备控制器的特点?...为什么需要设备驱动程序?...设备控制器虽然屏蔽了设备的细节,但每种设备控制器的寄存器、缓冲区等的使用模式不同,因此引入了设备驱动程序屏蔽设备控制器的差异。 设备控制器属于硬件范畴,但设备驱动程序属于操作系统的一部分。...驱动程序处理中断 设备控制器在完成任务以后,会发出中断信号,此时CPU收到中断指令以后,往往会对中断进行响应,而响应的处理函数往往在驱动程序中,因此驱动程序初始化的时候,要先注册一个该设备的中断处理函数...存储系统IO分层 Linux的存储系统的IO由上到下可以分为三个层次,分别是: 文件系统层 通用块层 设备层 文件系统层:包括虚拟文件系统和其他文件系统的具体实现,向上为应用程序统一提供了标准的文件访问接口
/*既然上面分析了,块设备的工作原理。 那如何写一个块设备呢?*/ /*怎么写一个块设备驱动程序? * 1. 分配一个gendisk结构,用alloc_disk函数 * 2....设置gendisk结构 * 3.1 设置主设备号,次设备号 * 3.2 设置block_device_operations结构 * 3.3 设置queueu结构 * 4....注册gendisk: 用add_disk函数 */ /***既然知道如何写一个块设备驱动程序,我们就动手用内存模拟一个块设备驱动***/ #define BLOCK_SIZE (1024...512; unsigned long len = req->current_nr_sectors * 512; // 长度 if (rq_data_dir(req) == READ)//读设备...{ memcpy(req->buffer, ramblock_buf+offset, len); } else //写设备 { memcpy(ramblock_buf+offset
目录 API 函数 编写驱动程序 编写应用程序 卸载驱动模块 小结 今天我们继续讨论: Linux 中字符设备的驱动程序。 在上一篇文章中Linux驱动实践:你知道【字符设备驱动程序】的两种写法吗?...我们说过:字符设备的驱动程序,有两套不同的API函数,并且在文中详细演示了利用旧的API函数来编写驱动程序。 这篇文章,我们继续这个话题,实际演示一下:字符设备驱动程序的另一套API函数的使用方法。...静态注册:由我们的驱动程序来指定主设备号,即参数1:from; 动态注册:由操作系统来分配,驱动程序提供一个变量来接收该设备号,即参数1: dev 指针; 另外,在Linux 2.6后期的内核版本中,引入了...来查看一下 /proc/devices 目录下显示的设备号: $ cat /proc/devices 设备已经注册了,主设备号是: 244 。...代码结构还是非常清晰的,这得益于Linux良好的驱动程序架构设计!这也是每一名架构师需要学习、努力模仿的地方。
大家好,我是道哥,今天我为大伙儿解说的技术知识点是:【字符设备的驱动程序】。 在上一篇文章中,讨论的是Linux系统中,驱动模块的两种编译方式。...旧的 API 函数 在Linux内核代码2.4版本和早期的2.6版本中,注册、卸载字符设备驱动程序的经典方式是: 注册设备: int register_chrdev(unsigned int major...再来查看一下 /proc/devices 目录下,也没有 driver1 设备的设备号。...来查看一下 /proc/devices 目录下显示的设备号: 可以看到 driver1 已经挂载好了,并且它的主设备号是244。...,继续用dmesg命令查看一下: 卸载驱动模块 卸载指令: $ sudo rmmod driver1 继续用dmesg指令来查看驱动程序中的打印信息: 说明驱动程序中的 driver1_exit(
领取专属 10元无门槛券
手把手带您无忧上云