Linux设备文件浅析

Linux设备文件浅析
Linux设备文件浅析

linux下的文件分为常规文件和设备文件,常规文件一定在某一个设备上被存储,不论这个设备是真实的还是虚拟的,这里的设备是linux中vfs层中的设备,也就是前面所说的设备文件中的设备,vfs层的设备分为字符设备和块设备,字符设备可以类比为一个fifo的队列,无论读还是写都必须顺序进行,而块设备就可以随机进行读写,常规的文件一般都在块设备上被存储,包括设备文件本身也在一个块设备上被存储着,可以说vfs层解决了这种混乱,它提供给上面的操作者一个十分统一的接口,实际上vfs下面十分不雅,败絮其中吗?等你看了linux源代码就不会这么认为了,linux内核是分层次的,vfs仅仅是其中的一个罢了,即使下面很乱也不是很无序的乱,总体看来是很乱,那是因为你混合看所有设备那当然混乱,因为字符设备和块设备的管理方式就不同,如果理一下思路就会很自然的想到在vfs接口下面有三条线,一条是常规文件,一条是字符设别文件,另一条就是块设备文件。

linux用很好的数据结构组织了两类设备文件,对于字符设备比较简单,就是将所有的字符设备都置于一个map中,就是cdev_map,所有的字符设备在注册的时候都会加入这个map:

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops)

{

struct char_device_struct *cd;

struct cdev *cdev;

char *s;

int err = -ENOMEM;

cd = __register_chrdev_region(major, 0, 256, name);

...

cdev = cdev_alloc();

if (!cdev)

goto out2;

cdev->owner = fops->owner;

cdev->ops = fops;

strcpy(cdev->https://www.360docs.net/doc/c112987264.html,, name);

for (s = strchr(cdev->https://www.360docs.net/doc/c112987264.html,, '/'); s; s = strchr(s, '/'))

*s = '!';

err = cdev_add(cdev, MKDEV(cd->major, 0), 256);

...

cd->cdev = cdev;

return major ? 0 : cd->major;

...

}

注意这个map并不是一个字符设备的链表,而是一个hash表,这个map主要作用就是和2.6内核的新的设备模型联系,也就是和kobject联系,linux中真正将所有的字符设备连成链表的是上面函数里面的char_device_struct结构体,很早以前写过一篇《谈谈linux2.6 内核的驱动框架》中讲到驱动的两条线索,其中以kobject连接起来的第一条线索直取用户空间其实就是到了这里的这个map,在这个map将把任务交给了vfs的接口。hash组织的kobj_map效率非常高,其实这里的hash函数很简单,就是设备号和255相除取余,将hash值相等的kobject用next字段连接成一个链表,然后在需要查找某些值

的时候通过hash找到链表然后遍历链表通过一个回调函数进行精确比对最终找到需要的结构:

struct kobj_map {

struct probe {

struct probe *next;

dev_t dev;

unsigned long range;

struct module *owner;

kobj_probe_t *get; //这就是那个精确比对的回调函数,这个创意在于将比对策略一起放入了hash节点中,这样可以灵活实现不同的比对策略。

int (*lock)(dev_t, void *);

void *data;

} *probes[255]; //255个hash桶

struct rw_semaphore *sem;

};

每当打开一个字符设备时,从这个map中得到一个cdev结构体,而cdev中有一个file_operations字段,在默认的open函数中,用这个file_operations字段替换字符设备的默认的file_operations字段,然后从此用户就可以用这个file_operations 来操作字符设备了,这就是“狸猫换太子”了。

对于块设备远远比字符设备复杂,但是看起来要比字符设备有层次感,块设别也有一个前面的hash表,只不过它里面映射的不是简单的vfs层的块设备了,而是更为底层通用块设备,就是gendisk,为何要这样?就是因为块设备可以利用缓存,这在linux中是很重要的,

可以大大提高效率,因此必须在真正的块设备层上面提供一个统一的缓存管理的层次,最好和常规文件的缓存管理统一用一套机制,这样的结果就是block_device层次,其实block_device是一个vfs和gendisk之间的粘结层,可以为统一缓存管理机制提供更加统一的接口(gendisk很底层,不适合做这件事),为了和常规文件一致的管理缓存就必须一套和常规文件一致的file_operations结构体,linux的block设备恰恰提供了这个:def_blk_fops。另外就是以上的file_operations必须固定,不能让不同的disk任意设置,因为虽然底层设备不同,可是缓存管理机制是统一的,缓存不属于底层,而属于vfs。gendisk就是再往下的块设备层次了,它主要管理磁盘结构信息,比如分区信息等等,再往下就是IDE,SCSI这些特殊的层次了。

以上是字符设备和块设备文件的vfs架构,那么常规文件呢?前面说过,常规文件都在块设备中,因此常规文件的操作就成了最终的块设备的操作,最终在经过了缓存层次之后就到了块设备的架构了,最终也要经过gendisk到达底层硬件。

还有一类设备就是网络设备,比如网卡之类的,可是却没有在任何地方看到网络设备的设备文件,这到底是为什么?这就要从TCP/IP协议栈和BSD套接字说起了,在tcp/ip之前,操作网络设备是件很平常的事,可是tcp/ip之后就没人再直接操作网络设备进行通信了,取而代之的是用协议栈进行通信,tcp/ip规定应用通信信道是应用层的两个进程之间建立的信道,很多情况下,信道应该是独占的,而设备意味着共享,大家都可以用,因此建立设备文件并没有问题。可是在tcp/ip之后,网络设备就被抽象成了一个通信信道,BSD套接字实现了这一点,因此通信就是两个进程独占一个信道进行通信(不考虑广播和组播),网络设备就不能随意被共享了,更大的意义是没有必要被共享,没有人再直接操作网络设备进行通信,所有人都是通过套接字用协议栈进行通信的,而一个套接字就是一个信道的一个端点,被一个进程独占,并且在通信开始时动态建立,通信开始时间不早于进程创建时间,

因此就把网络设备的管理交给了进程,进程可以很方便的通过协议栈管理设备和应用设备,古老的ifconfig不就是通过套接字的ioctl配置设备的吗?这并不违背unix的一切皆文件的理念,套接字本身也是通过vfs操作的,只是有了协议栈和套接字用户接口,第一是没有必要再提供网卡设备文件了,第二就是网络通信信道的独占性和协议封装规则已经作为协议栈的标准存在了,底层的硬件网卡也遵循这些协议栈标准(IEEE802.x),因此操作系统必须提供标准的操作方式而不是将操作自由留给用户,用户如果不懂协议栈标准就无法操作设备并且用设备通信,而协议栈标准是统一的,因此必须由操作系统提供,然后把可以微调的配置用套接字接口的形式留给用户操作和配置。类似于管道,很多无名管道也没有设备文件,只要在进程中以独占方式操作的文件描述符都没有必要有设别文件,一切皆文件指的是vfs这个层次而不是必须要在文件系统有永久记录

《实用操作系统》实验报告五linux设备管理

《实用操作系统》实验报告 实验报告: 5 实验项目名称:设备管理 班级:学号:姓名: 地点:时间:2013 年11 月13 日 一、实验内容 1、添加硬盘,创建二个主分区、一个扩展分区,二个逻辑分区 注意:ide、scsi 提示:分区、格式化、挂载(fdisk,mkfs,mount) 2、查看常见的设备文件有哪些?(ls /dev ) 常见的设备文件:/dev/hd* IDE接口的硬盘(IDE接口的设备) /dev/sd* SCSI/USB设备/dev/cua* 串口设备/dev/lp* 并口设备/dev/tty* 终端设备/dev/consol 控制台设备/dev/eth* 以太网设备/dev/cdrom IDE光驱/dev/fd* 软驱/dev/audio 音频设备/dev/scd SCSI的光驱/dev/ppp PPP设备/dev/isdn* ISDN设备 3、挂载光盘,查看光盘内容创建挂载点要求:以本人姓名缩写为目录mkdir / 目录/设备挂载mount 空格源设备空格挂载点 4、显示管理System-config-display 5、声卡管理System-config-soundcard 6、打印机管理System-config-printer 7、网卡管理System-config-network 二、实验步骤及结果 1.添加硬盘,创建分区; 在启动虚拟机前,在工具栏中点击“虚拟机”,找到“设置”选项,在左面的硬件中找到硬盘,进行硬盘设备添加,这里有IDE和SCSI两种硬盘类型可供选择添加。完成硬盘添加后即可启动虚拟机进入linux系统。在这我添加了容量相同的硬盘设备类型各一;

Linux设备驱动程序举例

Linux设备驱动程序设计实例2007-03-03 23:09 Linux系统中,设备驱动程序是操作系统内核的重要组成部分,在与硬件设备之间 建立了标准的抽象接口。通过这个接口,用户可以像处理普通文件一样,对硬件设 备进行打开(open)、关闭(close)、读写(read/write)等操作。通过分析和设计设 备驱动程序,可以深入理解Linux系统和进行系统开发。本文通过一个简单的例子 来说明设备驱动程序的设计。 1、程序清单 //MyDev.c 2000年2月7日编写 #ifndef __KERNEL__ #define __KERNEL__//按内核模块编译 #endif #ifndef MODULE #define MODULE//设备驱动程序模块编译 #endif #define DEVICE_NAME "MyDev" #define OPENSPK 1 #define CLOSESPK 2 //必要的头文件 #include //同kernel.h,最基本的内核模块头文件 #include //同module.h,最基本的内核模块头文件 #include //这里包含了进行正确性检查的宏 #include //文件系统所必需的头文件 #include //这里包含了内核空间与用户空间进行数据交换时的函数宏 #include //I/O访问 int my_major=0; //主设备号 static int Device_Open=0; static char Message[]="This is from device driver"; char *Message_Ptr; int my_open(struct inode *inode, struct file *file) {//每当应用程序用open打开设备时,此函数被调用 printk ("\ndevice_open(%p,%p)\n", inode, file); if (Device_Open) return -EBUSY;//同时只能由一个应用程序打开 Device_Open++; MOD_INC_USE_COUNT;//设备打开期间禁止卸载 return 0; } static void my_release(struct inode *inode, struct file *file)

Linux命令大全(设备管理)

设备管理-setleds 名称:setleds 使用权限:一般使用者 使用方式: setleds [-v] [-L] [-D] [-F] [{+|-}num] [{+|-}caps] [{+|-}scroll]说明: 用来设定键盘上方三个LED 的状态。在Linux 中,每一个虚拟主控台都有独立的设定。 参数: -F 预设的选项,设定虚拟主控台的状态。 -D 除了改变虚拟主控台的状态外,还改变预设的状态。 -L 不改变虚拟主控台的状态,但直接改变LED 显示的状态。这会使得LDE 显示和目前虚拟主控台的状态不符合。我们可以在稍后用-L 且不含其它选项的setleds 命令回复正常状态。 -num +num 将数字键打开或关闭。 -caps +caps 把大小写键打开或关闭。 -scroll +scroll 把选项键打开或关闭。 范例: 将数字键打开,其馀二个灯关闭。 # setleds +num -caps -scroll 设备管理-loadkeys 名称: loadkeys 使用权限: 所有使用者

使用方式: loadkeys [ -d --default ] [ -h --help ] [ -q --quiet ] [ -v --verbose [ -v --verbose ]...] [ -m --mktable ] [ -c --clearcompose ] [ -s --clearstrings ] [ filename... ] 使用说明: 这个命令可以根据一个键盘定义表改变linux 键盘驱动程序转译键盘输入过程。详细的说明请参考dumpkeys。 选项: -v --verbose 印出详细的资料,你可以重复以增加详细度。 -q --quiet 不要显示任何讯息。 -c --clearcompose 清除所有composite 定义。 -s --clearstrings 将定串定义表清除。 相关命令: dumpkeys 设备管理-rdev 名称:rdev 使用权限:所有使用者 使用方式:使用这个指令的基本方式是:rdev [-rsvh ] [-o offset ] [ image [value [ offset ] ] ] 但是随著使用者想要设定的参数的不同,底下的方式也是一样: rdev [ -o offset ] [ image [ root_device [ offset ] ] ] swapdev [ -o offset ] [ image [ swap_device [ offset ] ] ] ramsize [ -o offset ] [ image [ size [ offset ] ] ] videomode [ -o offset ] [ image [ mode [ offset ] ] ] rootflags [ -o offset ] [ image [ flags [ offset ] ] ]

Linux设备模型(文档翻译)_(整理文档)

Linux 内核文档翻译- driver-model/bus.txt Bus Types 总线类型 Definition 定义 ~~~~~~~~~~ See the kerneldoc for the struct bus_type. intbus_register(struct bus_type * bus); Declaration 声明 ~~~~~~~~~~~ Each bus type in the kernel (PCI, USB, etc) should declare one static object of this type. They must initialize the name field, and may optionally initialize the match callback. 内核中每个总线类型(PCI、USB 等等)都应该声明一个此类型的静态对象。它们必须初始化该对象的name 字段,然后可选的初始化match 回调函数。 structbus_typepci_bus_type = { .name = "pci", .match = pci_bus_match, }; The structure should be exported to drivers in a header file: 这个结构体应该在头文件中向驱动程序导出: extern struct bus_typepci_bus_type; Registration 注册 ~~~~~~~~~~~~ When a bus driver is initialized, it calls bus_register. This initializes the rest of the fields in the bus object and inserts it into a global list of bus types. Once the bus object is registered, the fields in it are usable by the bus driver. 当初始化一个总线驱动时,将会调用bus_register。这时这个总线对象剩下的字段将被初始化,然后这个对象会被插入到总线类型的一个全局列表里去。一旦完成一个总线对象的注册,那么对于总线驱动来说它里面的字段就已经可用了。

Linux设备驱动模型之platform总线深入浅出

Linux设备驱动模型之platform总线深入浅出 在Linux2.6以后的设备驱动模型中,需关心总线,设备和驱动这三种实体,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。 对于依附在USB、PCI、I2C、SPI等物理总线来这些都不是问题。但是在嵌入式系统里面,在Soc系统中集成的独立外设控制器,挂接在Soc内存空间的外设等却不依附在此类总线。基于这一背景,Linux发明了一种总线,称为platform。相对于USB、PCI、I2C、SPI等物理总线来说,platform总线是一种虚拟、抽象出来的总线,实际中并不存在这样的总线。 platform总线相关代码:driver\base\platform.c 文件相关结构体定义:include\linux\platform_device.h 文件中 platform总线管理下最重要的两个结构体是platform_device和platform_driver 分别表示设备和驱动在Linux中的定义如下一:platform_driver //include\linux\platform_device.h struct platform_driver { int (*probe)(struct platform_device *); //探测函数,在注册平台设备时被调用int (*remove)(struct platform_device *); //删除函数,在注销平台设备时被调用void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); //挂起函数,在关机被调用int (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *);//恢复函数,在开机时被调用struct device_driver driver;//设备驱动结构}; 1 2 3 4 5 6 7 8

实验九Linux设备管理实验

实验九Linux设备管理实验 一、实验目的: 掌握linux系统重定向、管道操作和设备管理的法。 二、预备知识 1.标准的输入输出和重定向 执行一个shell命令行时通常会自动打开三个标准文件,即标准输入文件(stdin,通常对应终端的键盘);标准输出文件(stdout)和标准错误输出文件(stderr),这两个文件都对应终端的屏幕。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。 用户在输入输出数据时存在以下问题: ●从终端输入数据时,用户输入的数据只能用一次,如果下次再想用这些 数据时就得重新输入。而且在终端上输入时,项输入有误修改起来不是 很便。 ●输出到屏幕上的信息只能看不能动,无法对此输出作更多处理,如将作 为另一命令的输入进行进一步的处理等。 为了解决上述问题,Linux系统为输入输出的传送引入了另外两种机制,即输入输出重定向。输入重定向是指把命令(或可执行程序)的标准输入重定向到指定的文件中。也就是说,输入可以不来自键盘,而来自一个指定的文件。因此,输入重定向主要用于改变一个命令的输入源,告别是改变那些需要大量输入的输入源。输出重定向是批把命令(或可执行程序)的标准输出或标准错误输出重定

向到指定文件中。这样,命令的输出就不显示在屏幕上,而是写入到指定文件中。2.管道 将一个程序或命令的输出作为另一个程序或命令的输入可有两种法,一种是通过一个临时文件将两个命令或程序联系在一起;另一种是Linux所提供的管道功能,这种法比前一种法更好。管道可以把一系列命令连接起来,这就意味着第一个命令的输出会将为第二个命令的输入通过管道传给第二个命令,而第二个命令的输出又作为第三个命令的输入,以此类推。显示在屏幕上的是管道行中最后一个命令的输出(如果命令行中示使用输出重定向)。用户还可以通过使用管道符“|”来建立一个管道行。 3.文件备份和压缩 参见第二章相关的ppt。 三、实验容和实验步骤(实验情况请截图和说明) 1.基本实验 (1)标准输入输出文件使用 通过wc命令统计指定文件包含的行数、单词数和字符数。 实验步骤一:在命令提示符输入ls,显示当前目录下的文件。 [m112013@tan ~]$ ls ch4 ch5 lab1 lab2 lab3 lab4 lab5 lab6 lab7 lab8 lab9 subdir [m112013@tan ~]$ cd lab9 [m112013@tan lab9]$ ls test.c

linux设备模型介绍

第一节基本概念 在设备模型里面,所有的东西都是kobject,这也是linux建立设备设计模型的目的(对比2.4之前),实现了统一的实体;我们理解上,却可以分为两个层次,一个是kobject,一个是管理kobject的kobject(可以把它叫做kset虽然有点绕,但是没有办法了,毕竟就像那个“世界上先有鸡还是先有蛋的哲学问题一下”); kobject结构

1)前面两个顾名思义,就是name了,为什么会有两个呢?k_name就是指向name的,如何知道呢,呵呵,看一下代码 2)kref就是一个内核的原子计数结构,因为涉及内核的操作基本都需要是原子性的,为了大家的方便,kobject就把它包括进来了,所以大家就不必要各自定义自己的计数了(一般情况下:),poll也是类似,把等待队列包括进来; 3)entry 这个名字比较让人误解,其实看它的类型知道是list成员,它就是加入到kset的list 的那个零部件; 4)ktpye 要理解这个成员就稍微麻烦些了,先看一下定义 Default_attrs就是一种比较简单的设置属性文件的方法,它其实跟我们自己调用sysfs_create_file没有什么区别,呵呵,看一下代码就知道了,所以大家基本上可以把它忽略掉:),调用关系为kobject_add->create_dir->populate_dir 把一个忽略掉,剩下的两个就比较重要了;每个对象一般都有多个属性,用面向对象的角度来看,我们可以把对属性的操作抽象为show和store这一对方法,那么多个属性就会有多对show和store的方法;那么,为了实现对这些方法的统一调用,就利用ktype中的sysfs_ops 实现了多态;这样一来,对于sysfs中的普通文件读写操作都是由kobject->ktype->sysfs_ops

linux设备驱动中常用函数

Linux2.6设备驱动常用的接口函数(一) ----字符设备 刚开始,学习linux驱动,觉得linux驱动很难,有字符设备,块设备,网络设备,针对每一种设备其接口函数,驱动的架构都不一样。这么多函数,要每一个的熟悉,那可多难啦!可后来发现linux驱动有很多规律可循,驱动的基本框架都差不多,再就是一些通用的模块。 基本的架构里包括:加载,卸载,常用的读写,打开,关闭,这是那种那基本的咯。利用这些基本的功能,当然无法实现一个系统。比方说:当多个执行单元对资源进行访问时,会引发竞态;当执行单元获取不到资源时,它是阻塞还是非阻塞?当突然间来了中断,该怎么办?还有内存管理,异步通知。而linux 针对这些问题提供了一系列的接口函数和模板框架。这样,在实际驱动设计中,根据具体的要求,选择不同的模块来实现其功能需求。 觉得能熟练理解,运用这些函数,是写号linux设备驱动的第一步。因为是设备驱动,是与最底层的设备打交道,就必须要熟悉底层设备的一些特性,例如字符设备,块设备等。系统提供的接口函数,功能模块就像是工具,能够根据不同的底层设备的的一些特性,选择不同的工具,方能在linux驱动中游刃有余。 最后就是调试,这可是最头疼的事。在调试过程中,总会遇到这样,那样的问题。怎样能更快,更好的发现并解决这些问题,就是一个人的道行咯!我个人觉得: 发现问题比解决问题更难! 时好时坏的东西,最纠结! 看得见的错误比看不见的错误好解决! 一:Fops结构体中函数: ①ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 用来从设备中获取数据. 在这个位置的一个空指针导致 read 系统调用以-EINVAL("Invalid argument") 失败. 一个非负返回值代表了成功读取的字节数( 返回值是一个 "signed size" 类型, 常常是目标平台本地的整数类型). ②ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 发送数据给设备. 如果 NULL, -EINVAL 返回给调用 write 系统调用的程序. 如果非负, 返回值代表成功写的字节数 ③loff_t (*llseek) (struct file *, loff_t, int); llseek 方法用作改变文件中的当前读/写位置, 并且新位置作为(正的)返回值. loff_t 参数是一个"long offset", 并且就算在 32位平台上也至少 64 位宽. 错误由一个负返回值指示. 如果这个函数指针是 NULL, seek 调用会以潜在地无法预知的方式修改 file 结构中的位置计数器( 在"file 结构" 一节中描述). ④int (*open) (struct inode *, struct file *);

linux设备管理命令

linux设备管理命令 1.1 stty [语法]: stty [-a] [-g] [选项] [说明]: 本命令设置终端,无参数时报告终端设置,本命令功能十分强大,应谨慎使用,下面仅介绍部分常用功能 ?-a 显示当前终端所有设置 ?-g 以能作为 stty 命令参数的方式显示终端设置以下是终端常用设置,在设置前加-表示清除设置: o1.控制方式,ispeed 0 110 300 600 1200 1800 2400 4800 9600 19200 38400,本命令设置终端输入波特率,若为0则使用缺省波 特率。例如 stty ispeed 9600 ospeed 0 110 300 600 1200 1800 2400 4800 9600 19200 38400本命令设置终端输出波特率,参看 ispeed。 o2.输入方式 ?ingbrk(-ignbrk) 忽略(不忽略)中断(BREAK) ?brkint(-brkint) 设置(清除)信号INTR为中断信号 ?inlcr(-inlcr) 将换行转换(不转换)成回车 ?icrnl( -icrnl) 将回车转换(不转换)成换行 ?igncr(-ignrc) 忽略(不忽略)回车 ?iuclc( -iuclc) 将大写字母转换(不转换)成小写字母o3.输出方式 ?olcut(-olcut) 将小写字母转换(不转换)为大写字母 ?onlcr(-onlcr) 输出时将换行符转换(不转换)为回车换行 ?ocrnl(-ocrnl) 输出时将回车符转换(不转换)为换行符o4.本地方式 ?echo (-echo) 设置(清除)回显 ?stwrap(-stwrap) 截断(不截断)大于79个字符的行 ?echoctl(-echoctr) 将控制键回显为^ 1.2 tty [语法]: tty [说明]: 显示出终端的设备名 [例子]: tty 1.3 lp [语法]: lp 文件... [说明]: 将文件送打印机打印 [例子]: lp myfile将文件myfile 送打印机输出 1.4 lpstat [语法]: lpstat [选项] [打印任务号] [说明]: 显示打印机状态,选项的意义如下:

Linux设备模型 热插拔、mdev 与 firmware

Linux设备驱动程序学习(15) -Linux设备模型(热插拔、mdev 与firmware) 热插拔 有2 个不同角度来看待热插拔: 从内核角度看,热插拔是在硬件、内核和内核驱动之间的交互。 从用户角度看,热插拔是内核和用户空间之间,通过调用用户空间程序(如hotplug、udev 和mdev)的交互。当需要通知用户内核发生了某种热插拔事件时,内核才调用这个用户空间程序。 现在的计算机系统,要求Linux 内核能够在硬件从系统中增删时,可靠稳定地运行。这就对设备驱动作 者增加了压力,因为在他们必须处理一个毫无征兆地突然出现或消失的设备。 热插拔工具 当用户向系统添加或删除设备时,内核会产生一个热插拔事件,并在/proc/sys/kernel/hotplug文件里查找处理设备连接的用户空间程序。这个用户空间程序主要有 hotplug:这个程序是一个典型的bash 脚本,只传递执行权给一系列位于/etc/hot-plug.d/ 目录树的程序。hotplug 脚本搜索所有的有 .hotplug 后缀的可能对这个事件进行处理的程序并调用它们, 并传递给它们许多不同的已经被内核设置的环境变量。(基本已被淘汰,具体内容请参阅《LDD3》) udev :用于linux2.6.13或更高版本的内核上,为用户空间提供使用固定设备名的动态/dev目录的解 决方案。它通过在sysfs 的/class/ 和/block/ 目录树中查找一个称为dev 的文件,以确定所创建的 设备节点文件的主次设备号。所以要使用udev,驱动必须为设备在sysfs中创建类接口及其dev属性文件,方法和sculld模块中创建dev属性相同。udev的资料网上十分丰富,我就不在这废话了,给出以 下链接有兴趣的自己研究:

Linux设备驱动程序简介

第一章Linux设备驱动程序简介 Linux Kernel 系统架构图 一、驱动程序的特点 ?是应用和硬件设备之间的一个软件层。 ?这个软件层一般在内核中实现 ?设备驱动程序的作用在于提供机制,而不是提供策略,编写访问硬件的内核代码时不要给用户强加任何策略 o机制:驱动程序能实现什么功能。 o策略:用户如何使用这些功能。 二、设备驱动分类和内核模块 ?设备驱动类型。Linux 系统将设备驱动分成三种类型 o字符设备 o块设备 o网络设备 ?内核模块:内核模块是内核提供的一种可以动态加载功能单元来扩展内核功能的机制,类似于软件中的插件机制。这种功能单元叫内核模块。 ?通常为每个驱动创建一个不同的模块,而不在一个模块中实现多个设备驱动,从而实现良好的伸缩性和扩展性。 三、字符设备 ?字符设备是个能够象字节流<比如文件)一样访问的设备,由字符设备驱动程序来实现这种特性。通过/dev下的字符设备文件来访问。字符设备驱动程序通常至少需要实现 open、close、read 和 write 等系统调用 所对应的对该硬件进行操作的功能函数。 ?应用程序调用system call<系统调用),例如:read、write,将会导致操作系统执行上层功能组件的代码,这些代码会处理内核的一些内部 事务,为操作硬件做好准备,然后就会调用驱动程序中实现的对硬件进 行物理操作的函数,从而完成对硬件的驱动,然后返回操作系统上层功 能组件的代码,做好内核内部的善后事务,最后返回应用程序。 ?由于应用程序必须使用/dev目录下的设备文件<参见open调用的第1个参数),所以该设备文件必须事先创建。谁创建设备文件呢? ?大多数字符设备是个只能顺序访问的数据通道,不能前后移动访问指针,这点和文件不同。比如串口驱动,只能顺序的读写设备。然而,也 存在和数据区或者文件特性类似的字符设备,访问它们时可前后移动访

Linux统一设备管理平台platform之设备注册流程V2版-李枝果

Linux lizhiguo0532@https://www.360docs.net/doc/c112987264.html, --------------------------------------------------------------------------------------------------------------------- https://www.360docs.net/doc/c112987264.html,/sz_farsight ---------------------------------------------------------------------------------------------------------------------- linux-2.6.14 1. linux2.6 platform_device platform_driver Linux Platform_device Platform_driver platform driver device driver ( driver_register ) platform platform device 2.s3c2410 3. a. :include\linux\ioport.h struct resource { const char *name; /* */ unsigned long start, end; /* cpu * start cpu * end */ unsigned long flags; /* */ /* */ /* */ struct resource *parent, *sibling, *child; /* */ }; /* * ,

如何实现Linux设备驱动模型

文库资料?2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd. 如何实现Linux 设备驱动模型 设备驱动模型,对系统的所有设备和驱动进行了抽象,形成了复杂的设备树型结构,采用面向对象的方法,抽象出了device 设备、driver 驱动、bus 总线和class 类等概念,所有已经注册的设备和驱动都挂在总线上,总线来完成设备和驱动之间的匹配。总线、设备、驱动以及类之间的关系错综复杂,在Linux 内核中通过kobject 、kset 和subsys 来进行管理,驱动编写可以忽略这些管理机制的具体实现。 设备驱动模型的内部结构还在不停的发生改变,如device 、driver 、bus 等数据结构在不同版本都有差异,但是基于设备驱动模型编程的结构基本还是统一的。 Linux 设备驱动模型是Linux 驱动编程的高级内容,这一节只对device 、driver 等这些基本概念作介绍,便于阅读和理解内核中的代码。实际上,具体驱动也不会孤立的使用这些概念,这些概念都融合在更高层的驱动子系统中。对于大多数读者可以忽略这一节内容。 1.1.1 设备 在Linux 设备驱动模型中,底层用device 结构来描述所管理的设备。device 结构在文件中定义,如程序清单错误!文档中没有指定样式的文字。.1所示。 程序清单错误!文档中没有指定样式的文字。.1 device 数据结构定义 struct device { struct device *parent; /* 父设备 */ struct device_private *p; /* 设备的私有数据 */ struct kobject kobj; /* 设备的kobject 对象 */ const char *init_name; /*设备的初始名字 */ struct device_type *type; /* 设备类型 */ struct mutex mutex; /*同步驱动的互斥信号量 */ struct bus_type *bus; /*设备所在的总线类型 */ struct device_driver *driver; /*管理该设备的驱动程序 */ void *platform_data; /*平台相关的数据 */ struct dev_pm_info power; /* 电源管理 */ #ifdef CONFIG_NUMA int numa_node; /*设备接近的非一致性存储结构 */ #endif u64 *dma_mask; /* DMA 掩码 */ u64 coherent_dma_mask; /*设备一致性的DMA 掩码 */ struct device_dma_parameters *dma_parms; /* DMA 参数 */ struct list_head dma_pools; /* DMA 缓冲池 */ struct dma_coherent_mem *dma_mem; /* DMA 一致性内存 */ /*体系结构相关的附加项*/ struct dev_archdata archdata; /* 体系结构相关的数据 */ #ifdef CONFIG_OF

linux设备驱动

Linux设备驱动 操作系统的目的之一就是将系统硬件设备细节从用户视线中隐藏起来。例如虚拟文件系统对各种类型已安装的文件系统提供了统一的视图而屏蔽了具体底层细节。本章将描叙Linux核心对系统中物理设备的管理。 CPU并不是系统中唯一的智能设备,每个物理设备都拥有自己的控制器。键盘、鼠标和串行口由一个高级I/O芯片统一管理,IDE控制器控制IDE硬盘而SCSI控制器控制SCSI硬盘等等。每个硬件控制器都有各自的控制和状态寄存器(CSR)并且各不相同。例如Adaptec 2940 SCSI控制器的CSR与NCR 810 SCSI控制器完全不一样。这些CSR被用来启动和停止,初始化设备及对设备进行诊断。在Linux中管理硬件设备控制器的代码并没有放置在每个应用程序中而是由内核统一管理。这些处理和管理硬件控制器的软件就是设备驱动。Linux 核心设备驱动是一组运行在特权级上的内存驻留底层硬件处理共享库。正是它们负责管理各个设备。 设备驱动的一个基本特征是设备处理的抽象概念。所有硬件设备都被看成普通文件;可以通过和操纵普通文件相同的标准系统调用来打开、关闭、读取和写入设备。系统中每个设备都用一种特殊的设备相关文件来表示(device special file),例如系统中第一个IDE硬盘被表示成/dev/hda。块(磁盘)设备和字符设备的设备相关文件可以通过mknod命令来创建,并使用主从设备号来描叙此设备。网络设备也用设备相关文件来表示,但Linux寻找和初始化网络设备时才建立这种文件。由同一个设备驱动控制的所有设备具有相同的主设备号。从设备号则被用来区分具有相同主设备号且由相同设备驱动控制的不同设备。例如主IDE硬盘的每个分区的从设备号都不相同。如/dev/hda2表示主IDE 硬盘的主设备号为3而从设备号为2。Linux通过使用主从设备号将包含在系统调用中的(如将一个文件系统mount到一个块设备)设备相关文件映射到设备的设备驱动以及大量系统表格中,如字符设备表,chrdevs。 Linux支持三类硬件设备:字符、块及网络设备。字符设备指那些无需缓冲直接读写的设备,如系统的串口设备/dev/cua0和/dev/cua1。块设备则仅能以块为单位读写,典型的块大小为512或1024字节。块设备的存取是通过

设备管理--Linux设备驱动程序安装

集美大学计算机工程学院实验报告 课程名称:操作系统班级:xxx实验成绩: 指导教师:姓名:xxx ( 学号:xxxx上机实践日期:xxx 实验项目名称: 设备管理——Linux设备驱动程序安装 实验项目编号:组号:上机实践时间: 2 学时~ 一、目的(本次实验所涉及并要求掌握的知识点) 1.认识Linux的设备的种类和设备工作方式; 2.理解设备驱动程序的工作原理; 3.掌握设备驱动程序的编写规范,能编写并安装简单的设备驱动程序。 二、实验内容与设计思想(设计思路、主要数据结构、主要代码结构、主要代码段分析、电路图) 实验内容: ¥ 在Linux系统中,编写一个简单的字符型设备驱动程序模块,设备具有独占特性,可执行读和写操作,相关系统调用为open, close, read, write,open和close分别相当于请求和释放设备,read和write内容保存在设备模块内的缓冲区中。设备模块可动态注册和卸载,并建立与之对应的特殊文件/dev/mydev。 实验设计: 1.按照要求编写设备驱动模块,同时编写一个测试程序 2.分别对其编译,注意编译时的项 3.设备模块加载 4.创建特殊文件 5.分析执行结果 6.设备模块卸载 < 三、实验使用环境(本次实验所使用的平台和相关软件) Linux 四、实验步骤和调试过程(实验步骤、测试数据设计、测试结果分析) LINUX_VERSION_CODE is * the code (as per KERNEL_VERSION) of this version. */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) < #include /* for put_user */ #endif #define SUCCESS 0 #define DEVICE_NAME "kueng_char_dev"

Linux设备模型:基本概念

Linux设备模型:基本概念 1. 前言 在“Linux内核的整体架构”中,蜗蜗有提到,由于Linux支持世界上几乎所有的、不同功能的硬件设备(这是Linux的优点),导致Linux内核中有一半的代码是设备驱动,而且随着硬件的快速升级换代,设备驱动的代码量也在快速增长。个人意见,这种现象打破了“简洁就是美”的理念,是丑陋的。它导致Linux内核看上去非常臃肿、杂乱、不易维护。但蜗蜗也知道,这不是Linux的错,Linux是一个宏内核,它必须面对设备的多样性,并实现对应的驱动。 为了降低设备多样性带来的Linux驱动开发的复杂度,以及设备热拔插处理、电源管理等,Linux内核提出了设备模型(也称作Driver Model)的概念。设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口。驱动的开发,就简化为对内核所规定的数据结构的填充和实现。 本文将会从设备模型的基本概念开始,通过分析内核相应的代码,一步一步解析Linux设备模型的实现及使用方法。 2. Linux设备模型的基本概念 2.1 Bus, Class, Device和Device Driver的概念 下图是嵌入式系统常见的硬件拓扑的一个示例: 硬件拓扑描述Linux设备模型中四个重要概念中三个:Bus,Class和Device(第四个为Device Driver,后面会说)。 Bus(总线):Linux认为(可以参考include/linux/device.h中struct bus_type的注释),总线是CPU和一个或多个设备之间信息交互的通道。而为了方便设备模型的抽象,所有的设备都应连接到总线上(无论是CPU内部总线、虚拟的总线还是“platform Bus”)。 Class(分类):在Linux设备模型中,Class的概念非常类似面向对象程序设计中的Class (类),它主要是集合具有相似功能或属性的设备,这样就可以抽象出一套可以在多个设

Linux设备驱动程序说明介绍

Linux设备驱动程序简介 Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel 中的函数,有些常用的操作要自己来编写,而且调试也不方便。本人这几周来为实验室自行研制的一块多媒体卡编制了驱动程序,获得了一些经验,愿与Linux fans共享,有不当之处,请予指正。 以下的一些文字主要来源于khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关device driver的一些资料. 这些资料有的已经过时,有的还有一些错误,我依据自己的试验结果进行了修正. 一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口.设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作.设备驱动程序是内核的一部分,它完成以下的功能: 1.对设备初始化和释放. 2.把数据从内核传送到硬件和从硬件读取数据. 3.读取应用程序传送给设备文件的数据和回送应用程序请求的数据. 4.检测和处理设备出现的错误. 在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是块设备.字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作.块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待. 已经提到,用户进程是通过设备文件来与实际的硬件打交道.每个设备文件都都有其文件属性(c/b),表示是字符设备还蔤强樯璞?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们.设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序. 最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度.也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作.如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck. 读/写时,它首先察看缓冲区的内容,如果缓冲区的数据 如何编写Linux操作系统下的设备驱动程序 二、实例剖析 我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理.把下面的C代码输入机器,你就会获得一个真正的设备驱动程序.不过我的kernel是2.0.34,在低版本的kernel上可能会出现问题,我还没测试过. [code]#define __NO_VERSION__

第一章(linux设备驱动程序).doc

第1章Linux内核简介 世界各地都有人在钻研Linux内核,大多是在写设备驱动程序。尽管每个驱动程序都不一样,而且你还要知道自己设备的特殊性,但是这些设备驱动程序的许多原则和基本技术技巧都是一样的。通过本书,可以学会写自己的设备驱动程序,并且可以钻研内核的相关部分。本书涉及到的是设备无关编程技巧,不会将例子跟特殊设备绑定在一起。 本章没有实际编写代码。但我要介绍一些关于Linux内核的背景概念,这样到我们稍后开始介绍实际编程时,就很顺利了。 当你学习编写驱动程序的时候,你也会发现很多关于Linux内核的知识,这对理解你机器怎么工作很有帮助,并且还可以知道为什么你的机器没有希望的那么快,或者为什么不按照你象要它做的那样做。我们会逐渐介绍一些新概念,先从简单的驱动程序开始,每介绍一些新概念都会看到相关例子代码,这些代码都不需要特殊硬件。 驱动程序作者的作用 作为一个程序员,你可以选择自己的驱动程序,在编程所需时间和结果的灵活性之间做个可以接受的权衡。尽管说驱动程序的灵活性看起来有那么点怪,我喜欢这个词是因为它强调了设备驱动程序提供的是机制,而不是策略。 机制和策略之间的差别是Unix设计背后最好的点子之一。实际编程中遇到的大多数问题都可以被划分成两个部分:“需要作什么”(机制)和“这个程序怎么用”(策略)。如果这两个主题是由程序不同部分来承担的,或者是由不同的程序组合一起承担的,那么这个软件包就很容易开发,也很适合特殊需求。 举个例子,Unix的图形显示管理在X服务器和窗口管理器之间划了一道线,X服务器了解硬件并给用户程序提供唯一的接口,而窗口管理器实现特殊的策略并不需要知道硬件的任何信息。人们可以在不同硬件上使用同样的窗口管理器,并且不同用户在同一台工作站上可以使用不同的设置。另一个例子是TCP/IP的网络分层结构:操作系统提供抽象的套接字操作,是设备无关的,不同服务器主管这个服务。另外,ftpd服务器提供文件传输机制,而用户可以使用任何客户端程序;命令行的客户端和图形化界面的客户端都存在,并且谁都可以为传输文件写一个新的用户界面。 只要涉及到驱动程序,就会运用这样的功能划分。软盘驱动程序是设备无关的——这不仅表现在磁盘是一个连续读写的字节数组上。如何使用设备是应用程序要做的事:tar要连续地写数据,而mkfs则为要安装的设备做准备工作,mcopy依赖于设备上存在的特殊数据结构。在写驱动程序时,程序员应该特别留心这样的基本问题:我们要写内核代码访问硬件,但由于不同用户有不同需要,我们不能强迫用户采用什么样的特定策略。设备驱动程序应该仅仅处理硬件,将如何使用硬件的问题留给应用程序。如果在提供获得硬件能力的同时没有增加限制,我们就说驱动程序是灵活的。不过,有时必须要作一些策略决策。 可以从不同侧面来看你的驱动程序:它是位于应用层和实际设备之间的软件。驱动程序的程序员可以选择这个设备应该怎样实现:不同的驱动程序可以提供不同的能力,甚至相同的设备也可以提供不同能力。实际驱动程序设计应该是在众多需求之间的一个平衡。例如,不同程序可以同时使用同一个设备,而驱动程序的开发者可以完全自由地决定如何处理同步机制。你可以实现到设备上的内存映射,而完成独立于硬件的具体能力,或者你可以提供给用

相关文档
最新文档