linux字符设备驱动程序 笔记
- 格式:doc
- 大小:442.50 KB
- 文档页数:10
广州大学学生实验报告一、实验目的通过一个简单的设备驱动的实现过程。
学会Linux中设备驱动程序的编写二、使用仪器、器材1.设备:带网卡的PC若干、交换机一台。
2.工具:网线若干,已经安装好Red Hat Linux 9。
0系统的PC一台。
三、实验内容及原理设计和实现一个虚拟命名管道(FIFO)的字符设备。
写一个模块化的字符设备驱动程序四、实验过程(1)设备的实现1、数据结构/*vfifo.c*/#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#define __NO_VERSION__#include〈linux/config。
h>#include〈linux/module。
h>#include<linux/kernel.h〉#include〈linux/malloc。
h〉#include〈linux/fs。
h〉#include<linux/proc_fs。
h〉#include<linux/errno.h〉#include<linux/types。
h〉#include〈linux/fcntl。
h>#include〈linux/init。
h〉#include〈asm/system.h〉#include<asm/uaccess.h〉#ifndef VFIFO_MAJOR#define VFIFO_MAJOR 241#endif#ifndef VFIFO_NR_DEVS#define VFIFO_NR_DEVS 4#endif#ifndef VFIFO_BUFFER#define VFIFO_BUFFER 4000#endif#include<linux/devfs_fs_kernel。
h〉devfs_handle_t vfifo_devfs_dir;struct file_operations vfifo_fops;int vfifo_major=VFIFO_MAJOR;int vfifo_nr_devs=VFIFO_NR_DEVS;int vfifo_buffer=VFIFO_BUFFER;MODULE_PARM(vfifo_major,"i");MODULE_PARM(vfifo_nr_devs,"i");MODULE_PARM(vfifo_buffer,"i");MODULE_AUT HOR(”EBUDDY”);结构体/*vfifo。
4月9日字符设备驱动基本编程本文将使用内存来虚拟4个同类型字符设备scull,并以该字符设备为例来进行字符设备驱动基本编程的讲解。
本文可素材和源代码(做了少量修改)均来源于Linux Device Driver一书的第3版,因此本文可视为对该书相关章节的阅读理解。
一、让我们先来体验一下scull设备吧1、下载scull设备的驱动源码(单击下载),解压后make,可得到scull.ko。
将其加载进内核: insmod scull.ko2、创建设备节点文件dennis@dennis-desktop:/work/studydriver/examples/scull$ cat/proc/devices|grep scull252 scull252 scullpdennis@dennis-desktop:/work/studydriver/examples/scull$ sudo mknod scull0 c 252 0dennis@dennis-desktop:/work/studydriver/examples/scull$ sudo mknod scull1 c 252 1dennis@dennis-desktop:/work/studydriver/examples/scull$ sudo mknod scull2 c 252 2dennis@dennis-desktop:/work/studydriver/examples/scull$ sudo mknod scull3 c 252 3dennis@dennis-desktop:/work/studydriver/examples/scull$ sudo chmod 666 scull[0-3]3、体验scull设备。
向该字符设备写入内容后再将内容读出dennis@dennis-desktop:/work/studydriver/examples/scull$ cat scull0 dennis@dennis-desktop:/work/studydriver/examples/scull$ echo yangzhu > scull0dennis@dennis-desktop:/work/studydriver/examples/scull$ cat scull0 yangzhu二、实现字符设备驱动的工作1、确定主设备号和次设备号什么是主设备/次设备号o主设备号是内核识别一个设备属于哪一个驱动的标识。
linux操作系统课程学习笔记,我的Linux学习笔记·Linux操作系统基础今天的笔记主要是关于Linux操作系统根底的相关学问。
那就从我⾯前的电脑开端讲起。
计算机和操作系统计算机主要包括五个部分:运算器,控制器,存储器,输⼊设备和输出设备。
通常,运算器,控制器再加上其他⼀些部件如寄存器等构成了我们通常所说的CPU(central processing unit),存储器则主要是内存。
运算器,控制器和存储器可以实现数据的处理.但是数据从何⽽来,运算之后的结果去往哪⾥?这就需要输⼊设备和输出设备(I/O设备)。
我们通常⽤到的输⼊设备包括键盘⿏标等,输出设备为屏幕,打印机等。
值得⼀提的是,计算机中有个叫做硬盘的东西,它并不是存储器,⽽是⼀个I/O设备。
在将数据读取到内存时,它是⼀个输⼊设备;⽽将结果保存到磁盘时,它就变成了⼀个输出设备。
这么多设备整合在⼀起,就成了⼀台计算机。
它可以接收我们的指令(键盘⿏标),通过运算(CPU),把结果展⽰给我们(屏幕,硬盘等)。
但是这么多硬件是如何协调作⽤,共同完成⼀个任务⽽不会我⾏我素地乱来呢?我们需要⼀个东西,它可以控制硬件有序地⼯作,各⾃执⾏⾃⼰的任务,这个东西就是操作系统(Operating System)。
操作系统是⼀个特殊的软件,它的任务就是硬件管理—控制CPU的运算,控制内存的分配,控制计算机的⼏乎⼀切。
假如⼀台电脑没有操作系统,它可能只是⼀个艺术品,或者⼀堆废铁。
⼀个完整的操作系统包括内核和⼀些辅助软件。
内核的主要任务就是进⾏硬件管理,它是⼀个操作系统最基础最底层的东西。
内核若想很好地控制硬件并使其发挥相应的功能,需要和硬件相识相知相爱,他俩可以成为完美的⼀对,全都仰仗于驱动的帮忙。
驱动是硬件的灵魂,它向操作系统提供了访问和使⽤硬件的接⼝,以便在某项任务中最⾼效地调⽤硬件。
什么是LinuxLinux就是⼀个操作系统,它可以管理整个计算机硬件,并且可以接收我们的指令,来指挥硬件完成相应的任务,并把结果反馈给我们。
字符设备驱动1.主设备号和从设备号Linux使用设备号来标识字符设备。
设备号分为主设备号和从设备号。
·主设备号标识设备对应的驱动程序。
每个在内核中活动的字符设备驱动程序都有唯一的主设备号。
·从设备号只由设备驱动程序使用。
字符设备驱动程序使用从设备号区分管理的不同物理设备。
向系统增加一个驱动程序意味着要赋予它一个主设备号。
2.具体到LINUX系统里,设备驱动程序所提供的这组入口点由一个结构来向系统进行说明,此结构定义为:#include <linux/fs.h>struct file_operations {int (*lseek)(struct inode *inode,struct file *filp,off_t off,int pos);int (*read)(struct inode *inode,struct file *filp,char *buf, int count);int (*write)(struct inode *inode,struct file *filp,char *buf,int count);int (*readdir)(struct inode *inode,struct file *filp,struct dirent *dirent,int count);int (*select)(struct inode *inode,struct file *filp,int sel_type,select_table *wait);int (*ioctl) (struct inode *inode,struct file *filp,unsigned int cmd,unsigned int arg);int (*mmap) (void);int (*open) (struct inode *inode, struct file *filp);void (*release) (struct inode *inode, struct file *filp);int (*fsync) (struct inode *inode, struct file *filp);};3.驱动程序的初始化函数:Int Init_module (){Return register_chrdev(,,,)}驱动清除函数:V oid cleanup_module(){Unregister_chrdev(,);}用户输入命令insmod模块文件名称加载内核模块时,系统会检测此模块能否被加载,如果能被加载,内核件调用模块的初始化函数。
嵌入式Linux下ADC的驱动程序实现与应用作者:孙德辉梁鑫杨扬来源:《现代电子技术》2008年第22期摘要:详细介绍S3C2410芯片ADC模块以及Linux的驱动模型,并且通过S3C2410内置的ADC驱动程序设计说明字符型设备驱动开发方法;将驱动编译为模块的方式,单独加载入内核,便于调试。
以MINICOM为操作台,控制驱动模块的加载和应用程序的运行。
并通过实例介绍ADC驱动程序在电阻、电压等测试中的实际应用;从实验结果可以看出ADC驱动可以被成功加载和调用;该驱动可以测试电压、电流等标准工程量信号,或作为工业传感器接口的一部分对现场标准工程量信号进行采集处理。
关键词:S3C2410;ADC;Linux;字符设备驱动程序中图分类号:TP311文献标识码:B文章编号:1004373X(2008)2203303Implement and Application of ADC Driver about Embedded-LinuxSUN Dehui,LIANG Xin,YANG Yang(Key Laboratory of Beijing Municipality,The FAT Laboratory,North China University of Technology,Beijing,100041,China)Abstract:The module of ADC in S3C2410 CMOS chip and the model about Linux drivers are expounded,the method of developing character device drivers are illuminated by realizing an ADC driver.As convenient to debug,compiling the drivers into module and "insmod" it into kernel.Updating the drivers module and application by MINICOM,one kind of consoles.Application on testing resistance and voltage using ADC driver are introduced through an example.In the end,it is obviously that ADC drivers module could be "insmoded"and called successful from the result of ing the drivers testing resistance,voltage and many other standard signal.ADC drivers can collect the standard signal of plants as one part of interface of industrial sensor.Keywords:S3C2410;ADC;Linux;character device driver1 引言S3C2410开发板制造商提供了绝大部分的驱动程序,但有时出于实际开发的需要、应用程序的稳定性考虑,用户往往需要开发一个自己需要的接口驱动程序。
linux驱动开发知识点总结Linux驱动开发是指在Linux操作系统下开发和编写设备驱动程序的过程。
Linux作为一种开源操作系统,具有广泛的应用领域,因此对于驱动开发的需求也非常重要。
本文将从驱动程序的概念、驱动开发的基本步骤、常用的驱动类型以及驱动开发的注意事项等方面进行总结。
一、驱动程序的概念驱动程序是指控制计算机硬件和软件之间通信和交互的程序。
在Linux系统中,驱动程序负责与硬件设备进行交互,实现对硬件的控制和管理。
二、驱动开发的基本步骤1. 确定驱动的类型:驱动程序可以分为字符设备驱动、块设备驱动和网络设备驱动等。
根据具体的硬件设备类型和需求,选择合适的驱动类型。
2. 编写设备注册函数:设备注册函数用于向系统注册设备,使系统能够识别和管理该设备。
3. 实现设备的打开、关闭和读写操作:根据设备的具体功能和使用方式,编写设备的打开、关闭和读写操作函数。
4. 实现设备的中断处理:如果设备需要进行中断处理,可以编写中断处理函数来处理设备的中断请求。
5. 编写设备的控制函数:根据设备的需求,编写相应的控制函数来实现对设备的控制和配置。
6. 编译和安装驱动程序:将编写好的驱动程序进行编译,并将生成的驱动模块安装到系统中。
三、常用的驱动类型1. 字符设备驱动:用于控制字符设备,如串口、打印机等。
字符设备驱动以字符流的方式进行数据传输。
2. 块设备驱动:用于控制块设备,如硬盘、U盘等。
块设备驱动以块为单位进行数据传输。
3. 网络设备驱动:用于控制网络设备,如网卡。
网络设备驱动实现了数据包的收发和网络协议的处理。
4. 触摸屏驱动:用于控制触摸屏设备,实现触摸操作的识别和处理。
5. 显示驱动:用于控制显示设备,实现图像的显示和刷新。
四、驱动开发的注意事项1. 熟悉硬件设备的规格和寄存器的使用方法,了解硬件设备的工作原理。
2. 确保驱动程序的稳定性和可靠性,避免出现系统崩溃或死机等问题。
3. 对于需要频繁访问的设备,要考虑性能问题,尽量减少对硬件的访问次数。
(笔记)Linux下的ioctl()函数详解我这⾥说的ioctl函数是指驱动程序⾥的,因为我不知道还有没有别的场合⽤到了它,所以就规定了我们讨论的范围。
写这篇⽂章是因为我前⼀阵⼦被ioctl给搞混了,这⼏天才弄明⽩它,于是在这⾥清理⼀下头脑。
⼀、什么是ioctlioctl是设备驱动程序中对设备的I/O通道进⾏管理的函数。
所谓对I/O通道进⾏管理,就是对设备的⼀些特性进⾏控制,例如串⼝的传输波特率、马达的转速等等。
它的调⽤个数如下:int ioctl(int fd, ind cmd, …);其中fd是⽤户程序打开设备时使⽤open函数返回的⽂件标⽰符,cmd是⽤户程序对设备的控制命令,⾄于后⾯的省略号,那是⼀些补充参数,⼀般最多⼀个,这个参数的有⽆和cmd的意义相关。
ioctl函数是⽂件结构中的⼀个属性分量,就是说如果你的驱动程序提供了对ioctl的⽀持,⽤户就可以在⽤户程序中使⽤ioctl函数来控制设备的I/O通道。
下表列出了⽹络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:类别Request说明数据类型套接⼝SIOCATMARKSIOCSPGRPSIOCGPGRP是否位于带外标记设置套接⼝的进程ID 或进程组ID获取套接⼝的进程ID 或进程组IDintintint⽂件FIONBINFIOASYNCFIONREADFIOSETOWNFIOGETOWN设置/ 清除⾮阻塞I/O 标志设置/ 清除信号驱动异步I/O 标志获取接收缓存区中的字节数设置⽂件的进程ID 或进程组ID获取⽂件的进程ID 或进程组IDintintintintint接⼝SIOCGIFCONFSIOCSIFADDRSIOCGIFADDRSIOCSIFFLAGSSIOCGIFFLAGSSIOCSIFDSTADDRSIOCGIFDSTADDRSIOCGIFBRDADDRSIOCSIFBRDADDRSIOCGIFNETMASKSIOCSIFNETMASKSIOCGIFMETRICSIOCSIFMETRICSIOCGIFMTUSIOCxxx获取所有接⼝的清单设置接⼝地址获取接⼝地址设置接⼝标志获取接⼝标志设置点到点地址获取点到点地址获取⼴播地址设置⼴播地址获取⼦⽹掩码设置⼦⽹掩码获取接⼝的测度设置接⼝的测度获取接⼝MTU(还有很多取决于系统的实现)struct ifconfstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqstruct ifreqARP SIOCSARPSIOCGARPSIOCDARP创建/ 修改ARP 表项获取ARP 表项删除ARP 表项struct arpreqstruct arpreqstruct arpreq路由SIOCADDRTSIOCDELRT增加路径删除路径struct rtentrystruct rtentry流I_xxx⼆、 ioctl的必要性如果不⽤ioctl的话,也可以实现对设备I/O通道的控制,但那是蛮拧了。
实验二:字符设备驱动实验一、实验目的通过本实验的学习,了解Linux操作系统中的字符设备驱动程序结构,并能编写简单的字符设备的驱动程序以及对所编写的设备驱动程序进行测试,最终了解Linux操作系统如何管理字符设备。
二、准备知识字符设备驱动程序主要包括初始化字符设备、字符设备的I/O调用和中断服务程序。
在字符设备驱动程序的file_operations结构中,需要定义字符设备的基本入口点。
open()函数;release()函数read()函数write()函数ioctl()函数select()函数。
另外,注册字符设备驱动程序的函数为register_chrdev()。
register_chrdev() 原型如下:int register_chrdev(unsigned int major, //主设备号const char *name, //设备名称struct file_operations *ops); //指向设备操作函数指针其中major是设备驱动程序向系统申请的主设备号。
如果major为0,则系统为该驱动程序动态分配一个空闲的主设备号。
name是设备名称,ops是指向设备操作函数的指针。
注销字符设备驱动程序的函数是unregister_chrdev(),原型如下:int unregister_chrdev(unsigned int major,const char *name);字符设备注册后,必须在文件系统中为其创建一个设备文件。
该设备文件可以在/dev目录中创建,每个设备文件代表一个具体的设备。
使用mknod命令来创建设备文件。
创建设备文件时需要使用设备的主设备号和从设备号作为参数。
阅读教材相关章节知识,了解字符设备的驱动程序结构。
三、实验内容根据教材提供的实例。
编写一个简单的字符设备驱动程序。
要求该字符设备包括open()、write()、read()、ioctl()和release()五个基本操作,并编写一个测试程序来测试所编写的字符设备驱动程序。
第1篇一、实验背景与目的随着计算机技术的飞速发展,操作系统对硬件设备的支持越来越丰富。
设备驱动程序作为操作系统与硬件之间的桥梁,扮演着至关重要的角色。
本实验旨在通过学习Linux字符设备驱动的开发,加深对设备驱动程序的理解,提高实践能力。
二、实验环境与工具1. 操作系统:Linux Ubuntu 20.042. 编程语言:C3. 开发工具:gcc、make4. 驱动框架:Linux内核三、实验内容本实验主要完成以下内容:1. 字符设备驱动程序的基本框架2. 字符设备的打开、读取、写入和关闭操作3. 字符设备驱动的注册与注销4. 字符设备驱动的用户空间交互四、实验步骤1. 创建设备文件首先,我们需要在`/dev`目录下创建一个名为`mychar`的字符设备文件。
可以使用以下命令:```bashmknod /dev/mychar c 123 0```其中,`123`是主设备号,`0`是次设备号。
2. 编写字符设备驱动程序创建一个名为`mychar.c`的文件,并编写以下代码:```cinclude <linux/module.h>include <linux/fs.h>include <linux/uaccess.h>static int major = 123; // 设备号static int device_open(struct inode inode, struct file filp);static int device_release(struct inode inode, struct file filp);static ssize_t device_read(struct file filp, char __user buf, size_t count, loff_t pos);static ssize_t device_write(struct file filp, const char __user buf, size_t count, loff_t pos);static struct file_operations fops = {.open = device_open,.release = device_release,.read = device_read,.write = device_write,};static int __init mychar_init(void) {major = register_chrdev(0, "mychar", &fops);if (major < 0) {printk(KERN_ALERT "mychar: can't get major number\n");return major;}printk(KERN_INFO "mychar: registered correctly with major number %d\n", major);return 0;}static void __exit mychar_exit(void) {unregister_chrdev(major, "mychar");printk(KERN_INFO "mychar: Goodbye from the LKM!\n");}static int device_open(struct inode inode, struct file filp) {printk(KERN_INFO "mychar: Device has been opened\n");return 0;}static int device_release(struct inode inode, struct file filp) {printk(KERN_INFO "mychar: Device has been closed\n");return 0;}static ssize_t device_read(struct file filp, char __user buf, size_t count, loff_t pos) {printk(KERN_INFO "mychar: Device has been read\n");return count;}static ssize_t device_write(struct file filp, const char __user buf, size_t count, loff_t pos) {printk(KERN_INFO "mychar: Device has been written\n"); return count;}module_init(mychar_init);module_exit(mychar_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("A simple character device driver");```保存文件,并使用以下命令编译:```bashmake```3. 加载字符设备驱动程序将编译生成的`mychar.ko`文件加载到内核中:```bashinsmod mychar.ko```4. 测试字符设备驱动程序使用以下命令查看`/dev/mychar`设备文件:```bashls -l /dev/mychar```使用`cat`命令测试读取和写入操作:```bashcat /dev/mycharecho "Hello, world!" > /dev/mychar```观察系统日志,确认驱动程序的打开、读取、写入和关闭操作。
4.6 linux字符设备驱动程序[4-6-1]linux驱动程序介绍(参考课件)驱动程序:使硬件工作的软件。
模型一的缺点:软件程序的复用性不好模型二的缺点:如果驱动程序接口变化,则所有的应用程序就必须都改模型三:即linux驱动程序驱动模型:如图“使用驱动程序所示”。
解决了上述两种模型的缺点。
linux驱动程序的分类:◎字符设备驱动(重点)◎网络接口驱动(重点)◎块设备驱动1)字符设备:字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现open,close,read和write系统调用。
2)块设备:◎在大部分unix系统,块设备不能按字节处理数据,只能一次传送一个或多个长度是512字节(或一个更大的2次幂的数)的整块数据。
◎而Linux则允许块设备传送任意数目的字节。
因此块和字符设备的区别:仅仅是驱动的接口函数与内核的接口函数不同。
3)网络接口:任何网络事物都通过一个接口来进行,一个接口通常是一个硬件(eth0),但它也可以是一个纯粹的软件设备,比如回环接口(lo)。
一个网络接口负责发送和接收数据报文。
字符设备与块设备:随机访问?块设备随机访问,字符设备必须按顺序访问驱动程序安装方式:有两种◎模块方式(已知)(insmod, rmmod)◎直接编译进内核如何直接把驱动程序(内核模块)编译进内核?需要修改两个文件:Kconfig,Makefile(Kconfig用来产生配置菜单,到处有Kconfig):第一步:首先把驱动程序或内核模块源文件(hello.c)放到内核源代码相应的目录下(根据功能选择目录)(如drivers/char下)第二步:修改Kconfig,修改所放源文件目录下的Kconfig,在内核源代码的顶层目录执行:vi drivers/char/Kconfig(打开Kconfig),然后在其中加上如下两行代码(照着写):config HELLO_WORLDBool “helloworld”第三步:通过make menuconfig ARCH=arm进入配置菜单,选中刚添加(要编译进内核)的项。
配置结果体现在(.config)中,.config文件位于内核源代码顶层目录下,通过vi .config可以查看。
可以看到:CONFIG_HELLO_WORLD=y第四步:修改Makefile,修改所放源文件目录下的Makefile。
照着写obj-$(CONFIG_HELLO_WORLD) += hello.o (加上这一项,hello.c)第五步:编译内核。
修改好后,回到内核源代码顶层目录执行如下命令编译内核。
:male uImage ARCH=armCROSS_COMPILE=arm-linux-***************************** hello.c代码如下:********************************** #include <linux/module.h>#include <linux/init.h>static int __init hello_init(){printk("hello world!\n");return 0;}static void __exit hello_exit(){printk(KERN_EMERG "hello exit!\n");}module_init(hello_init);module_exit(hello_exit);*****************************************************************************编译完成启动内核的过程中,会打印出:Hello World!信息。
因为执行了模块初始化函数。
__init标志表示此函数将被放置到初始化代码段;内核在启动时,会依次调用初始化代码段中的函数指针。
__exit类似。
驱动程序使用:linux用户程序通过设备文件(也称:设备节点)来使用驱动程序操作字符设备和块设备(根据*fp找到在内核里面对应的sturct file结构,从而找到相应的read,write函数)网络设备没有设备文件,设备文件在dev目录下面。
[4-6-2]字符设备驱动程序设计(参考课件)1、主次设备号字符设备通过字符设备文件来存取。
字符设备文件由使用ls –l命令后输出的第一列的“c”标识。
在dev目录下使用ls –l命令可以看到设备文件项中有2个数字,由逗号分隔,这些数字就是设备文件的主次设备编号。
前主后次。
1.1设备号的作用思考:字符设备文件与字符设备驱动如何建立联系?——通过主设备号设备文件所对应的主设备号和驱动程序所对应的主设备号相同的话,那么这个驱动程序就对应这个设备文件。
(设备文件的主设备号通过创建设定,驱动程序通过申请获得)主设备号:用来标识与设备文件相连的驱动程序。
次设备号:被驱动程序用来辨别操作的是哪个设备。
总结:主设备号用来反映设备类型;次设备号用来区分同类型的设备。
主次设备号的描述:内核描述内核中通过类型dev_t来描述设备号,其实质是unsigned int 32位整数,其中高12位为主设备号,低20位为次设备号。
◎分离出主设备号MAJOR(dev_t dev);◎分离出次设备号MINOR(dev_t dev)◎定义主次设备号dev_t devno = MKDEV(mem_major, mem_minor)1.2分配主设备号Linux内核通过静态申请和动态分配两种方法来给设备分配主设备号。
1.2.1静态申请(简单但易导致冲突)方法如下:1、根据Documentation/deices.txt,确定一个没有使用的主设备号;2、使用register_chrdev_region函数注册设备号。
优点:简单,缺点:一旦驱动程序被广泛使用,这个随机选定的主设备号可能会导致设备号冲突,而使驱动程序无法注册。
原型:int register_chrdev_region(dev_t from,unsigned count,const char* name)功能:申请使用从from开始的count个设备号(主设备号不变,次设备号增加)参数:from:希望申请使用的设备号count:希望申请使用的设备号数目name:设备名(体现在/proc/devices)1.2.2动态分配(简单,但无法在安装驱动前创建设备文件,因为安装前还没有分配到主设备号)方法如下:使用alloc_chrdev_region 分配设备号原型:int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name) 功能:请求内核动态分配count个设备号,且次设备号从baseminor开始。
参数:dev:分配到的设备号位于dev指针所指向的内存中。
,不需要填值,用于获取值baseminor:起始次设备号count:需要分配的设备号数目name:设备名(体现在/proc/devices)优点:简单,易于驱动推广缺点:无法在安装驱动前创建设备文件(因为安装前还没有分配到主设备号)解决办法:安装驱动后,从/proc/devices中查询设备号,然后再创建设备文件。
1.3注销设备号(不用时应该释放这些设备号)原型:void unregister_chrdev_region(dev_t from,unsigned count)功能:释放从from开始的count个设备号2、创建设备文件——2种方法:2.1、使用mknod命令手工创建用法:mknod filename type major minor参数:filename:设备文件名type:设备文件类型“c”,“b”major:主设备号minor:次设备号例如:mknod serial0 c 100 0 //设备文件的主次设备号是确定的,一个设备文件只能对应一个设备。
要操作哪个设备,首先要创建对应主次设备号的设备文件,再操作此设备文件。
2.2、自动创建——后面课程介绍3、重要结构在Linux字符设备驱动程序设计中,有三种非常重要的内核数据结构:3.1、struct file:代表一个打开的文件。
系统中每个打开的文件在内核空间都有一个关联的struct file。
它由内核在打开文件时创建,在文件关闭后释放。
(每打开一次创建一个)重要成员:loff_t f_pos /*文件读写位置*/struct file_operations*f_op3.2、struct inode:用来记录文件的物理上的信息(如存放位置、设备号等)。
因此它和代表打开文件的file结构是不同的,一个文件可以对应多个file结构,但只有一个inode结构。
重要成员:dev_t i_rdev:设备号//inode代表设备文件(设备节点)?3.3、struct file_operations:一个函数指针的集合(更像一个转化表),定义能在设备上进行的操作。
结构中的成员指向驱动中的函数,这些函数实现一个特殊的操作,对于不支持的操作保留为NULL。
struct file_operations mem_fops = {.owner = THIS_MODULE,.llseek = mem_seek,.read = mem_read,.write = mem_write,.ioctl = mem_ioctl,.open = mem_open,.release = mem_release,};思考:应用程序如何访问驱动程序?解析:当应用程序执行read系统调用,对设备文件进行读的时候,驱动程序就会做出mem_read函数调用。
当应用程序执行write系统调用,对设备文件进行写的时候,驱动程序就会做出mem_write函数调用。
把应用程序中对文件的操作转化成驱动程序中相应的函数。
(内核根据应用程序系统调用中传递的*fp指针找到在内核里面对应的sturct file结构,从而找到驱动程序中相应的read,write函数)4、设备注册在linux2.6内核中,字符设备使用struct cdev结构来描述。
字符设备的注册分为如下三个步骤:4.1、分配cdev,分配空间:分配是对于指针而言,静态的不需要分配struct cdev的分配可使用cedv_alloc函数来完成。
原型:struct cdev *cdev_alloc(void)。
分配完成后返回分配到的struct cdev函数指针注意:如果cdev结构被定义为静态的,则不需要执行空间分配。