嵌入式系统-—基于32位微处理器与实时操作系统 Chap10

上传人:壹****1 文档编号:570255792 上传时间:2024-08-03 格式:PPT 页数:179 大小:1.26MB
返回 下载 相关 举报
嵌入式系统-—基于32位微处理器与实时操作系统 Chap10_第1页
第1页 / 共179页
嵌入式系统-—基于32位微处理器与实时操作系统 Chap10_第2页
第2页 / 共179页
嵌入式系统-—基于32位微处理器与实时操作系统 Chap10_第3页
第3页 / 共179页
嵌入式系统-—基于32位微处理器与实时操作系统 Chap10_第4页
第4页 / 共179页
嵌入式系统-—基于32位微处理器与实时操作系统 Chap10_第5页
第5页 / 共179页
点击查看更多>>
资源描述

《嵌入式系统-—基于32位微处理器与实时操作系统 Chap10》由会员分享,可在线阅读,更多相关《嵌入式系统-—基于32位微处理器与实时操作系统 Chap10(179页珍藏版)》请在金锄头文库上搜索。

1、嵌入式系统-基于32位微处理器与实时操作系统Chap10Stillwatersrundeep.流静水深流静水深,人静心深人静心深Wherethereislife,thereishope。有生命必有希望。有生命必有希望主要内容主要内容n版级支持包 BSPn嵌入式系统初始化以及BSP的设计nLinux系统驱动程序开发n嵌入式联网BSP的概念nBSP全称“板级支持包”(Board Support Packages),说的简单一点,就是一段启动代码,和计算机主板的BIOS差不多,但提供的功能区别就相差很大n在Windows CE中,BSP是驱动程序、OEM适应层(OEM Adaptation Laye

2、rs,OAL)、硬件抽象层(HAL)以及启动设备和使外设正常工作所需BIOS文件的集合。 BSP和BIOS区别nBIOS主要是负责在电脑开启时检测、初始化系统设备(设置栈指针,中断分配,内存初始化.)、装入操作系统并调度操作系统向硬件发出的指令。 nBSP是和操作系统绑在一起运行,尽管BSP的开始部分和BIOS所做的工作类似,但是 BSP还包含和系统有关的基本驱动 nBIOS程序是用户不能更改,编译编程的,只能对参数进行修改设置,但是程序员还可以编程修改BSP,在BSP中任意添加一些和系统无关的驱动或程序,甚至可以把上层开发的统统放到BSP中 不同系统中的BSPn一个嵌入式操作系统针对不同的C

3、PU,会有不同的BSPn即使同一种CPU,由于外设的一点差别BSP相应的部分也不一样 BSP的特点与功能的特点与功能n硬件相关性n因为嵌入式实时系统的硬件环境具有应用相关性,所以,作为高层软件与硬件之间的接口,BSP必须为操作系统提供操作和控制具体硬件的方法。n操作系统相关性n不同的操作系统具有各自的软件层次结构,因此,不同的操作系统具有特定的硬件接口形式BSP的设计与实现的设计与实现n为实现上述两部分功能,设计一个完整为实现上述两部分功能,设计一个完整的的BSPBSP需要完成两部分工作:需要完成两部分工作:n设计初始化过程,完成嵌入式系统的初始化;设计初始化过程,完成嵌入式系统的初始化;n设

4、计硬件相关的设备驱动,完成操作系统及应用设计硬件相关的设备驱动,完成操作系统及应用程序对具体硬件的操作。程序对具体硬件的操作。嵌入式系统初始化以及BSP的功能n嵌入式系统的初始化过程是一个同时包括硬件嵌入式系统的初始化过程是一个同时包括硬件初始化和软件初始化的过程;而操作系统启动初始化和软件初始化的过程;而操作系统启动以前的初始化操作是以前的初始化操作是BSPBSP的主要功能之一的主要功能之一 n初始化过程总可以抽象为三个主要环境,按照初始化过程总可以抽象为三个主要环境,按照自底向上、从硬件到软件的次序依次为:自底向上、从硬件到软件的次序依次为:n片级初始化片级初始化n板级初始化板级初始化n系

5、统级初始化系统级初始化初始化过程n片级初始化:片级初始化:n主要完成主要完成CPUCPU的初始化的初始化n设置设置CPUCPU的核心寄存器和控制寄存器的核心寄存器和控制寄存器nCPUCPU核心工作模式核心工作模式nCPUCPU的局部总线模式等的局部总线模式等n片级初始化把片级初始化把CPUCPU从上电时的缺省状态逐步设置从上电时的缺省状态逐步设置成为系统所要求的工作状态成为系统所要求的工作状态n这是一个纯硬件的初始化过程这是一个纯硬件的初始化过程初始化过程(续1)n板级初始化:n完成CPU以外的其他硬件设备的初始化n同时还要设置某些软件的数据结构和参数,为随后的系统级初始化和应用程序的运行建立

6、硬件和软件环境n这是一个同时包含软硬件两部分在内的初始化过程初始化过程(续2)n系统级初始化:n这是一个以软件初始化为主的过程,主要进行操作系统初始化nBSP将控制转交给操作系统,由操作系统进行余下的初始化操作:n包括加载和初始化与硬件无关的设备驱动程序n建立系统内存区n加载并初始化其他系统软件模块(如网络系统、文件系统等)n最后,操作系统创建应用程序环境并将控制转交给应用程序的入口硬件相关的设备驱动程序nBSPBSP另一个主要功能是硬件相关的设备驱动另一个主要功能是硬件相关的设备驱动n与初始化过程相反,硬件相关的设备驱动程序的初始化和使用通常是一个从高层到底层的过程n尽管BSP中包含硬件相关

7、的设备驱动程序,但是这些设备驱动程序通常不直接由BSP使用n而是在系统初始化过程中由BSP把它们与操作系统中通用的设备驱动程序关联起来,并在随后的应用中由通用的设备驱动程序调用,实现对硬件设备的操作。BSP开发的前提和步骤开发的前提和步骤n开发的前提 :n熟悉硬件方面:使用CPU等n熟悉工具方面:电表,示波器,逻辑分析仪,硬件仿真器,仿真调试环境等n语言方面:汇编语言,C语言nBSP开发的一般步骤如下:n硬件主板研制,测试n操作系统的选定,BSP编程n上层应用程序的开发编写BSP函数nBSP对板卡中每个芯片的操作都通过多个函数来完成 n如果应用程序对板卡的操作都直接通过调用BSP中的函数来完成

8、,那将很不利于源程序的调试 ,并降低了程序的可移植性n把能完成某个特定功能的函数封装在一个库文件中,并放在应用程序与BSP之间 n对每个芯片来说,都应当有初始化函数和状态读取函数 设计实现BSP的一般方法nBSP的开发需要具备一定的硬件知识 n要求掌握操作系统所定义的BSP接口n两种快捷方法 n以经典BSP为参考 n使用操作系统提供的BSP模板 n设计实现BSP两部分功能时应采用以下两种不同方法 n“自底向上”地实现BSP中的初始化操作 n“自顶向下”地设计硬件相关的驱动程序BSP设计方法的不足与改进n目前BSP的设计与实现主要是针对某些特定的文件进行修改 n直接修改相关文件容易造成代码的不一

9、致性,增加软件设计上的隐形错误,从而增加系统调试和代码维护的难度 n解决这个问题的一个可行办法是:设计实现一种具有图形界面的BSP开发设计向导,由该向导指导设计者逐步完成BSP的设计和开发,并最终由向导生成相应的BSP文件,而不再由设计人员直接对源文件进行修改。LinuxLinux设备驱动程序及开发设备驱动程序及开发Linux设备驱动程序概述设备驱动程序概述nLinuxLinux设备驱动程序是处理或操作硬件控制器的软设备驱动程序是处理或操作硬件控制器的软件,被集成在内核中,是常驻内存的低级硬件处件,被集成在内核中,是常驻内存的低级硬件处理程序的共享库,设备驱动程序是系统对设备的理程序的共享库,

10、设备驱动程序是系统对设备的抽象管理与控制。抽象管理与控制。nLinuxLinux允许设备驱动程序作为内核可加载模块实现,允许设备驱动程序作为内核可加载模块实现,即除了可以在系统启动时进行注册外,还可以在即除了可以在系统启动时进行注册外,还可以在启动后进行加载注册。启动后进行加载注册。Linux驱动程序开发n建立嵌入式Linux平台,移植和编写驱动程序往往是最具挑战的工作n驱动程序的开发周期一般较长,对产品的面世时间有着重要影响n驱动程序质量的好坏,直接关系到系统工作效能和稳定性,对项目的成败起着关键作用设备驱动程序主要功能设备驱动程序主要功能n设备驱动程序主要完成如下功能:设备驱动程序主要完成

11、如下功能:n检测设备和初始化设备检测设备和初始化设备n使设备投入运行和退出服务使设备投入运行和退出服务n从设备接收数据并提交给内核从设备接收数据并提交给内核n从内核接收数据送到设备从内核接收数据送到设备n检测和处理设备错误检测和处理设备错误Linux设备驱动程序分类nLinuxLinux中所有设备被抽象出来,都看成文件中所有设备被抽象出来,都看成文件 n设备的读写和普通文件一样设备的读写和普通文件一样nLinuxLinux系统的设备分为如下三类:系统的设备分为如下三类:n字符设备字符设备(char device)(char device)n块设备块设备(block device)(block

12、device)n网络设备网络设备(network device)(network device)n字符设备是指存取时没有缓存的设备字符设备是指存取时没有缓存的设备n块设备的读写都有缓存来支持,且块设备必须块设备的读写都有缓存来支持,且块设备必须能够随机存取能够随机存取(randomaccess)n网络设备在网络设备在LinuxLinux里做专门的处理里做专门的处理 Linux设备驱动程序分类网络设备在网络设备在LinuxLinux里做专门的处理里做专门的处理nLinuxLinux的网络系统主要是基于的网络系统主要是基于BSD unixBSD unix的的socket socket 机制。在系统

13、和驱动程序之间定义有机制。在系统和驱动程序之间定义有专门的数据结构专门的数据结构(sk_buff)(sk_buff)进行数据的传递进行数据的传递n系统里支持对发送数据和接收数据的缓存,提系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持供流量控制机制,提供对多协议的支持 Linux设备驱动程序分类n典型的字符设备包括鼠标,键盘,串行口等典型的字符设备包括鼠标,键盘,串行口等n块设备主要包括硬盘、软盘设备、块设备主要包括硬盘、软盘设备、CD-ROMCD-ROM等等n一个文件系统要安装进入操作系统必须在块一个文件系统要安装进入操作系统必须在块设备上设备上Linux驱动程序介

14、绍n嵌入式嵌入式LinuxLinux驱动已经支持的设备门类齐全,已驱动已经支持的设备门类齐全,已成为其相对其他嵌入式操作系统的一大优势成为其相对其他嵌入式操作系统的一大优势n工业控制常用的串口,并口工业控制常用的串口,并口n人机输入设备如鼠标、键盘,触摸屏人机输入设备如鼠标、键盘,触摸屏n彩色、黑白液晶显示输出彩色、黑白液晶显示输出n网络的完善支持,包括网络的完善支持,包括tcp/iptcp/ip,udpudp,firewallfirewall,WLANWLAN,ip forwardingip forwarding,ipsecipsec,vpnvpnnUsbUsb的全面支持,包括的全面支持,包

15、括usbusb硬盘、硬盘、u u盘,盘,usbusb摄像头摄像头n支持丰富的文件系统,包括支持丰富的文件系统,包括FAT32FAT32,NTFSNTFS嵌入式设备框图嵌入式设备框图驱动程序的功用1 1、驱动程序直接操控硬件、驱动程序直接操控硬件n收发通讯数据n读写存储介质,比如flash或硬盘n操作输出设备和执行机构,例如打印,开关门禁等驱动程序的功用(续)2 2、驱动程序提供软件访问硬件的机制、驱动程序提供软件访问硬件的机制n应用软件通过驱动程序安全高效的访问硬件n驱动程序文件可以方便的提供访问权限控制n驱动程序作为一个隔离的中间层软件,将底 层细节隐藏起来,提高了软件的可移植性访问Linu

16、x设备驱动的方法n设备提供dev文件系统节点和proc文 件系统节点n应用程序通过dev文件节点访问驱动 程序n应用程序通过proc文件节点可以查 询设备驱动的信息驱动程序位置n驱动程序位于驱动程序位于driversdrivers目录下目录下n通常驱动程序占通常驱动程序占kernelkernel代码的代码的50%50%nLinuxLinux设备驱动程序在设备驱动程序在LinuxLinux的内核源代码中占有很大的比的内核源代码中占有很大的比例,源代码的长度日益增加,主要是驱动程序的增加。例,源代码的长度日益增加,主要是驱动程序的增加。n在在LinuxLinux内核的不断升级过程中,驱动程序的结构

17、还是相对内核的不断升级过程中,驱动程序的结构还是相对稳定。稳定。n在在2.0.xx2.0.xx到到2.2.xx2.2.xx的变动里,驱动程序的编写做了一些改的变动里,驱动程序的编写做了一些改变,但是从变,但是从2.0.xx2.0.xx的驱动到的驱动到2.2.xx2.2.xx的移植只需做少量的工的移植只需做少量的工作。作。 Linux驱动程序的特点n嵌入式Linux驱动程序需求多样n嵌入式设备硬件各异n嵌入式计算平台往往资源有限,比如处理速度、存储器容量、总线带宽、电池容量等n通常要求短的开发周期、压力大n开发驱动程序需要丰富的专业知识,包括 硬件和软件知识嵌入式Linux驱动程序特点n嵌入式系

18、统硬件更新速度加快n国际上大的嵌入式芯片提供商如Intel、 Samsung、Freescale、TI、ST每年都有大量新品推出n新的芯片功能总是需要相应的驱动程序支持Linux驱动开发流程n熟悉设备的特性熟悉设备的特性n 确定设备驱动程序类别确定设备驱动程序类别n 编写测试用例编写测试用例n 搜集可重用的代码搜集可重用的代码n 编写自己的驱动程序代码编写自己的驱动程序代码n 编码、调试、测试编码、调试、测试Linux驱动程序的开发环境n本机编译调试n开发环境配置简单n无需网络环境n适用于配置较高的x86机器n主机+目标机n主机可以自由选择Linux或Windows+Cygwinn主机和目标机

19、通过网络共享文件系统n内核崩溃不会影响主机Linux驱动程序的开发环境(续)n主机+目标机环境包括n主机运行的工具链cross gcc + glibc + gdb, 如果是windows主机还要有cygwin仿真环境n主机运行远程服务,常用的有tftp用来传送内 核映像、initrd,NFS用来共享文件系统n目标机运行ssh或telnet等远程登陆服务,用来 调试驱动程序Linux驱动程序的加载方式n驱动程序直接编译入内核n驱动程序在内核启动时就已经在内存中n可以保留专用存储器空间n驱动程序以模块形式存储在文件系 统里,需要时动态载入内核n驱动程序按需加载,不用时节省内存n驱动程序相对独立于内

20、核,升级灵活Linux驱动程序模块加载Linux驱动程序开发的任务n规划硬件资源的使用n分离硬件相关和硬件无关的代码n划分驱动程序的抽象层次n移植驱动程序到新的平台Linux驱动程序开发的任务n规划硬件资源的使用nCPU时间片分配n中断处理n系统存储器空间映射设备存储器的映射Linux驱动程序开发的任务n分离硬件相关和硬件无关的代码n划分驱动程序的抽象层次Linux驱动程序开发的任务n移植驱动程序到新的平台GPL对驱动程序开发的影响n实现非GPL授权的方法模块形 式动态加载n驱动程序可以以私有产权形式进行 商业授权设备驱动程序的代码n驱动程序的注册与注销驱动程序的注册与注销nregister_

21、chrdev()nregister_blkdev()n设备的打开与释放设备的打开与释放nopen()nrelease()n设备的读写操作设备的读写操作nread()nwrite()n设备的控制操作nioctl()设备驱动的加载n使用模块的方式动态加载驱动使用模块的方式动态加载驱动nint func_init(void)func_init(void)n Makefile:Makefile:ninsmod xx.onlsmodnrmmod xx.on将驱动静态编译到内核里面将驱动静态编译到内核里面n int _init func_init(void)int _init func_init(void

22、)n Makefile:Makefile:n启动时自动加载Linux驱动程序模块加载编写驱动程序的一些基本概念n无论是什么操作系统的驱动程序,都有一些通用的概念n操作系统提供给驱动程序的支持也大致相同n以下简单介绍网络设备驱动程序的一些基本要求 编写网络驱动程序发送和接收发送和接收 这是一个网络设备最基本的功能n如一块网卡所做的无非就是收发工作。所以驱动程序里要告诉系统发送函数在哪里,系统在有数据要发送时就会调用发送程序。n驱动程序由于是直接操纵硬件的,所以网络硬件有数据收到,最先能得到这个数据的也就是驱动程序,它负责把这些原始数据进行必要的处理,然后送给系统。n这里,操作系统必须要提供两个机

23、制:n找到驱动程序的发送函数n驱动程序把收到的数据送给系统 编写驱动程序n读写读写n几乎所有设备都有输入和输出。每个驱动程几乎所有设备都有输入和输出。每个驱动程序要负责本设备的读写操作。序要负责本设备的读写操作。n操作系统不需要知道对设备的具体读写操作操作系统不需要知道对设备的具体读写操作怎样进行,这些都由驱动程序屏蔽掉了怎样进行,这些都由驱动程序屏蔽掉了n操作系统定义好一些读写接口,由驱动程序操作系统定义好一些读写接口,由驱动程序完成具体的功能完成具体的功能n在驱动程序初始化时,需要把具有这种接口在驱动程序初始化时,需要把具有这种接口的读写函数注册进操作系统的读写函数注册进操作系统编写驱动程

24、序n中断中断n中断在现代计算机结构中有重要的地位中断在现代计算机结构中有重要的地位n操作系统必须提供驱动程序响应中断的能力操作系统必须提供驱动程序响应中断的能力n一般是把一个中断处理程序注册到系统中去一般是把一个中断处理程序注册到系统中去n操作系统在硬件中断发生后调用驱动程序的处理程序操作系统在硬件中断发生后调用驱动程序的处理程序nLinuxLinux支持中断的共享,即多个设备共享一个中断支持中断的共享,即多个设备共享一个中断编写驱动程序n时钟时钟n在实现驱动程序时,很多地方会用到时钟。如某些协在实现驱动程序时,很多地方会用到时钟。如某些协议里的超时处理,没有中断机制的硬件的轮询等。议里的超时

25、处理,没有中断机制的硬件的轮询等。n操作系统应为驱动程序提供定时机制操作系统应为驱动程序提供定时机制n一般是在预定的时间过了以后回调注册的时钟函数一般是在预定的时间过了以后回调注册的时钟函数内核模块n模块是内核的一部分,但是并没有被编译到内核里去。它们被分别编译和连接成目标文件。 n用命令insmod插入一个模块到内核中,用命令rmmod卸载一个模块 n在Linux内核中,以下内容一般编译成模块:n大多数的驱动程序大多数的驱动程序。包括SCSI设备,CD-ROM,网络设备,不常用的字符设备,如打印机,watchdog等。n大多数文件系统,理论上除了根文件系统不能是模块,其他文件系统都可以是模块

26、。n一些内核支持的不常用的可执行文件格式,如binfmt_misc。kmod和高级模块化nLinux 提供了对模块自动加载和卸载的支持 n要利用这一特性,在编译内核前进行的配置中,必须打开对 kmod 的支持选项。 n一旦内核试图访问某种资源并发现该资源不可用时,它会对 kmod 子系统进行一次特殊的调用而不仅仅是返回一个错误 n按需加载的例子 :ALSA(Advanced Linux Sound Architecture)声卡驱动程序组的实现常用的系统支持常用的系统支持n内存申请和释放 n中断n时钟 nI/O n中断打开关闭 n输出信息n注册驱动程序 内存申请和释放ninclude/linu

27、x/kernel.h里声明了kmalloc()和kfree()。用于在内核模式下申请和释放内存。n与用户模式下的malloc()不同,kmalloc()申请空间有大小限制。长度是2的整次方。可以申请的最大长度也有限制。另外kmalloc()有priority参数 nKfree()释放的内存必须是kmalloc()申请的 申请中断和释放中断nrequest_irq()、free_irq() 是驱动程序申请中断和释放中断的调用。n在include/linux/sched.h里声明时钟n时钟的处理类似中断,也是登记一个时间处理函数,在预定的时间过后,系统会调用这个函数。n在include/linux

28、/timer.h里声明n使用时钟,先声明一个timer_list结构,调用init_timer对它进行初始化。Time_list结构里expires是标明这个时钟的周期,单位采用jiffies的单位。I/OnI/O端口的存取使用:ninline unsigned int inb(unsigned short port);ninline unsigned int inb_p(unsigned short port);ninline void outb(char value, unsigned short port);ninline void outb_p(char value, unsigned

29、 short port);n在include/adm/io.h里定义 中断打开关闭n系统提供给驱动程序开放和关闭响应中断的能力 n是在include/asm/system.h n#define cli() _asm_ _volatile_ (cli:)n#define sti() _asm_ _volatile_ (sti:) 输出信息n驱动程序要输出信息使用printk() ninclude/linux/kernel.h里声明注册驱动程序n如果使用模块(module)方式加载驱动程序,需要在模块初始化时把设备注册到系统设备表里去n不再使用时,把设备从系统中卸除 n定义在drivers/net

30、/net_init.h里的两个函数完成这个工作nInt register_netdev(struct device *dev);nvoid unregister_netdev(struct device *dev);网络驱动程序的结构n所有的Linux网络驱动程序遵循通用的接口 n设计时采用的是面向对象的方法 n一个设备就是一个对象(device 结构),它内部有自己的数据和方法 n每一个设备的方法被调用时的第一个参数都是这个设备对象本身。这样这个方法就可以存取自身的数据(类似面向对象程序设计时的this引用) n一个网络设备最基本的方法有初始化、发送和接收 网络驱动程序的结构(续)n初始化程

31、序完成硬件的初始化、device中变量的初始化和系统资源的申请n发送程序是在驱动程序的上层协议层有数据要发送时自动调用的。一般驱动程序中不对发送数据进行缓存,而是直接使用硬件的发送功能把数据发送出去n接收数据一般是通过硬件中断来通知的。在中断处理程序里,把硬件帧信息填入一个skbuff结构中,然后调用netif_rx( )传递给上层处理网络驱动程序的基本方法n初始化(initialize) n打开(open) n关闭(stop )n发送(hard_start_xmit) n接收(reception) n硬件帧头(hard_header) n地址解析(xarp) n参数设置和统计数据网络驱动程序

32、的基本方法网络驱动程序的基本方法-初始化初始化n驱动程序必须有一个初始化方法n在把驱动程序载入系统的时候会调用这个初始化程序。它做以下几方面的工作:n检测设备检测设备:在初始化程序里你可以根据硬件的特征检查硬件是否存在,然后决定是否启动这个驱动程序。n配置和初始化硬件配置和初始化硬件:在初始化程序里可以完成对硬件资源的配置,比如即插即用的硬件就可以在这个时候进行配置(Linux内核对PnP功能没有很好的支持,可以在驱动程序里完成这个功能)。n配置或协商好硬件占用的资源以后,就可以向系统申请这些资源。有些资源是可以和别的设备共享的,如中断。有些是不能共享的,如IO、DMA。n初始化初始化devi

33、cedevice结构中的变量结构中的变量n让硬件正式开始工作让硬件正式开始工作 网络驱动程序的基本方法网络驱动程序的基本方法打开打开打开打开(open)(open) open这个方法在网络设备驱动程序里是在网络设备被激活的时候被调用(即设备状态由down-up)n实际上很多在initialize中的工作可以放到这里来做。比如资源的申请、硬件的激活。n如果dev-open返回非0(error),则硬件的状态还是down nopen方法另一个作用是如果驱动程序做为一个模块被装入,则要防止模块卸载时设备处于打开状态。n在open方法里要调用MOD_INC_USE_COUNT宏网络驱动程序的基本方法网

34、络驱动程序的基本方法关闭关闭关闭关闭(stop)(stop) close方法做和open相反的工作。可以释放某些资源以减少系统负担。nclose是在设备状态由up转为down时被调用的n如果是做为模块装入的驱动程序,close里 应该调用MOD_DEC_USE_COUNT,减少设备被引用的次数,以使驱动程序可以被卸载。 nclose方法必须返回成功(0=success)网络驱动程序的基本方法网络驱动程序的基本方法发送发送发送发送(hard_start_xmit)(hard_start_xmit) 所有的网络设备驱动程序都必须有这个发送方法。n在系统调用驱动程序的xmit时,发送的数据放在一个s

35、k_buff结构中。n一般的驱动程序把数据传给硬件发出去。也有一些特殊的设备比如loopback把数据组成一个接收数据再回送给系统,或者 dummy设备直接丢弃数据。 n如果发送成功,hard_start_xmit方法里释放sk_buff,返回0(发送成功)n如果设备暂时无法处理,比如硬件忙,则返回1。这时如果dev-tbusy置为非0,则系统认为硬件忙,要等到dev-tbusy置0以后才会再次发送。tbusy的置0任务一般由中断完成。网络驱动程序的基本方法网络驱动程序的基本方法发送(续)发送(续)n硬件在发送结束后产生中断,这时可以把tbusy置0,然后用mark_bh()调用通知系统可以再

36、次发送。n在发送不成功的情况下,也可以不置dev-tbusy为非0,这样系统会不断尝试重发。n如果hard_start_xmit发送不成功,则不要释放sk_buff。 n传送下来的sk_buff中的数据已经包含硬件需要的帧头。所以在发送方法里不需要再填充硬件帧头,数据可以直接提交给硬件发送。sk_buff是被锁住的(locked), 确保其他程序不会存取它。 网络驱动程序的基本方法网络驱动程序的基本方法接收接收接收接收(reception)(reception) 驱动程序并不存在一个接收方法。有数据收到应该是驱动程序来通知系统的。 n一般设备收到数据后都会产生一个中断,在中断处理程序中驱动程序

37、申请一块sk_buff(skb),从硬件读出数据放置到申请好的缓冲区里。接下来填充sk_buff中的一些信息。skb-dev = dev,判断收到帧的协议类型,填入skb-protocol(多协 议的支持)。n把指针skb-mac.raw指向硬件数据然后丢弃硬件帧头(skb_pull)。网络驱动程序的基本方法网络驱动程序的基本方法接收(续)接收(续)n还要 设置skb-pkt_type,标明第二层(链路层)数据类型。可以是以下类型: PACKET_BROADCAST : 链路层广播 PACKET_MULTICAST : 链路层组播 PACKET_SELF : 发给自己的帧 PACKET_OTH

38、ERHOST : 发给别人的帧(监听模式时会有这种帧) n最后调用netif_rx()把数据传送给协议层。netif_rx()里数据放入处理队列然后返回,真正的处理是在中断返回以后,这样可以减少中断时间。n调用netif_rx()以后,驱动程序就不能再存取数据缓冲区skb。 网络驱动程序的基本方法网络驱动程序的基本方法硬件帧头硬件帧头n硬件一般都会在上层数据发送之前加上自己的硬件帧头,比如以太网(Ethernet)就有14字节的帧头。这个帧头是加在上层ip、ipx等数据包的前面的。n驱动程序提供一个hard_header方法,协议层(ip、ipx、arp等)在发送数据之前会调用这段程序。 n硬

39、件帧头的长度必须填在dev-hard_header_len,这样协议层回在数据之前保留好硬件帧头的空间。这样hard_header程序只要调用skb_push然后正确填入硬件帧头就可以了。 网络驱动程序的基本方法网络驱动程序的基本方法硬件帧头(续硬件帧头(续1 1)n在协议层调用hard_header时,传送的参数包括(2.0.xx):n数据的sk_buff ndevice指针nProtocoln目的地址(daddr) n源地址(saddr) n数据长度(len)n数据长度不要使用sk_buff中的参数,因为调用hard_header时数据可能还没完全组织好 nsaddr是NULL的话是使用缺

40、省地址(default)ndaddr是NULL表明协议层不知道硬件目的地址n如果hard_header完全填好了硬件帧头,则返回添加的字节数。网络驱动程序的基本方法网络驱动程序的基本方法硬件帧头(续硬件帧头(续2 2)n如果硬件帧头中的信息还不完全(比如daddr为NULL,但是帧头中需要目的硬件地址。典型的情况是以太网需要地址解析(arp),则返回负字节数。hard_header返回负数的情况下,协议层会做进一步的build header的工作。n目前Linux系统里就是做arp (如果hard_header返回正,dev-arp=1,表明不需要做arp,返回负,dev-arp=0,做arp

41、)。 对hard_header的调用在每个协议层的处理程序里。如ip_output。 网络驱动程序的基本方法网络驱动程序的基本方法地址解析地址解析地址解析地址解析(xarp)(xarp) 有些网络有硬件地址(比如Ethernet),并且在发送硬件帧时需要知道目的硬件地址。这样就需要上层协议地址(ip、ipx)和硬件地址的对应。这个对应是通过地址 解析完成的。n需要做arp的的设备在发送之前会调用驱动程序的rebuild_header方法。调用的主要参数包括:n指向硬件帧头的指针n协议层地址n如果驱动程序能够解析硬件地址,就返回1,如果不能,返回0。 n对rebuild_header的调用在ne

42、t/core/dev.c的do_dev_queue_xmit()里。 网络驱动程序的基本方法网络驱动程序的基本方法参数设置和统计数据参数设置和统计数据参数设置和统计数据参数设置和统计数据 在驱动程序里还提供一些方法供系统对设备的参数进行设置和读取信息。n一般只有超级用户(root)权限才能对设备参数进行设置。n设置方法有: ndev-set_mac_address() 当用户调用ioctl类型为SIOCSIFHWADDR时是要设置这个设备的mac地址。一般对mac地址的设置没有太大意义的。 网络驱动程序的基本方法网络驱动程序的基本方法参数设置和统计数据(续)参数设置和统计数据(续)ndev-s

43、et_config() 当用户调用ioctl时类型为SIOCSIFMAP时,系统会调用驱动程序的set_config方法。用户会传递一个ifmap结构包含需要的I/O、中断等参数。 ndev-do_ioctl() 如果用户调用ioctl时类型在SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间,系统会调用驱动程序的这个方法。一般是设置设备的专用数据。 读取信息也是通过ioctl调用进行。n除次之外驱动程序还可以提供一个dev-get_stats方法,返回一个enet_statistics结构,包含发送接收的统计信息。 nioctl的处理在net/core/dev.c的dev_

44、ioctl()和dev_ifsioc()里网络驱动程序中用到的数据结构n最重要的是网络设备的数据结构。它定义在include/linux/netdevice.h nsk_buff nLinux网络各层之间的数据传送都是通过sk_buff 编写编写LinuxLinux网络驱动程序中需要注意的问题网络驱动程序中需要注意的问题n中断共享 n硬件发送忙时的处理 n流量控制(flow control) n调试 中断共享 nLinux系统运行几个设备共享同一个中断。需要共享的话,在申请的时候指明共享方式。n系统提供的request_irq()调用的定义: int request_irq(unsigned

45、int irq, void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id); n如果共享中断,irqflags设置SA_SHIRQ属性,这样就允许别的设备申请同一个中断。需要注意所有用到这个中断的设备在调用request_irq()都必须设置这个属性。系统在回调每个中断处理程序时,可以用dev_id这个参数找到相应的设备。一 般dev_id就设为device结构本身。系统处理共享中断是用各自的dev_id参数依

46、次调用每一个中断处理程序。硬件发送忙时的处理n主CPU的处理能力一般比网络发送要快,所以经常会遇到系统有数据要发,但上一包数据网络设备还没发送完。因为在Linux里网络设备驱动程序一般不做数据缓存,不能发送的数据都是通知系统发送不成功,所以必须要有一个机制在硬件不忙时及时通知系统接着发送下面的数据。 n一般对发送忙的处理在前面设备的发送方法(hard_start_xmit)里已经描述过,即如果发送忙,置tbusy为1。处理完发送数据后,在发送结束中断里清tbusy,同时用mark_bh()调用通知系统继续发送。 但在具体实现驱动程序时发现,这样的处理系统好象并不能及时地知道硬件已经空闲了,即在

47、mark_bh()以后,系统要等一段时间才会接着发送。造成发送效率很低。n实现时不把tbusy置1,让系统始终认为硬件空闲,但是报告发送不成功。系统会一直尝试重发。这样处理就运行正常了。流量控制n网络数据的发送和接收都需要流量控制。这些控制是在系统里实现的,不需要驱动程序做工作。n每个设备数据结构里都有一个参数dev-tx_queue_len,这个参数 标明发送时最多缓存的数据包。在Linux系统里以太网设备(10/100Mbps) tx_queue_len一般设置为100,串行线路(异步串口)为10。n实际上,设置了dev-tx_queue_len并不是为缓存这些数据申请了空间。这个参数只是

48、在收到协议层的数据包时判断发送队列里的数据是不是到了tx_queue_len的限度,以决定这一包数据加不加进发送队列。发送时另一个方面的流控是更高层协议的发送窗口(TCP协议里就有发送窗口)。n达到了窗口大小,高层协议就不会再发送数据。 n接收流控也分两个层次。netif_rx()缓存的数据包有限制。另外高层协议也会有一个最大的等待处理的数据量。 n发送和接收流控处理在net/core/dev.c的do_dev_queue_xmit()和netif_rx() 中。调试n很多Linux的驱动程序都是编译进内核的,形成一个大的内核文件。但对调试来说,这是相当麻烦的。调试驱动程序可以用module方

49、式加载。n支持模块方式的驱动程序必须提供两个函数:int init_module(void)和void cleanup_module(void)。 ninit_module()在加载此模块时调用,在这个函数里可以register_netdev()注册设备。init_module()返回0表示成功,返回负表示失败。ncleanup_module()在驱动程序被卸载时调用,清除占用的资源,调用unregister_netdev()。 n模块可以动态地加载、卸载。在2.0.xx版本里,还有kerneld自动加载模块,但是2.2.xx中已经取消了kerneld。手工加载使用insmod命令,卸载用rm

50、mod命令,看内核中的模块用lsmod命令。 n编译驱动程序用gcc,主要命令行参数-DKERNEL -DMODULE。并且作为模块加载的驱动程序,只编译成obj形式(加-c参数)。编译好的目标文件放在/lib/modules/2.x.xx/misc下,在启动文件里用insmod加载 Linux驱动程序可利用资源互联网上有很多驱动程序资源:驱动源代码驱动源代码驱动源代码驱动源代码驱动源代码编译驱动程序应用程序编译应用程序背景知识:Linux设备管理主要内容n概述n驱动程序基础n中断处理n辅助函数n设备驱动程序n模块编程基础n字符设备n块设备n网络设备概述n输入输出子系统: 下层:设备驱动程序

51、上层:设备无关部分VFS in Linux?nUnix和Linux的设备管理方法: VFS设备管理总体结构示意用户程序系统调用接口文件系统高速缓存字符设备块设备驱动程序硬件设备输入输出系统层次结构用户进程用户进程设备无关软件设备无关软件设备设备驱动驱动程序程序设备服务子程序设备服务子程序中断处理程序中断处理程序硬件硬件I/O请求请求I/O应答应答进行进行I/O调用;调用;格式化格式化I/O命名、保护、阻塞、缓命名、保护、阻塞、缓冲、分配冲、分配建立设备寄存器、检测建立设备寄存器、检测状态状态I/O结束时,唤醒设备结束时,唤醒设备服务子程序服务子程序执行执行I/O操作操作驱动程序基础I/O空间n

52、Linux中的三种地址空间:CPUUntranslatedAddressCPUTranslatedAddressBusAddress:一般PC机中是一组寄存器命令more/proc/ioportsn常见总线ISAVESAEISAPCI驱动程序基础命名空间n并行设备:lp软盘:fdSCSI盘:sdIDE硬盘:hda1,hda2,hdb等网络设备:ethn,slipn,pppn等n在写驱动程序的时候,需要给函数名加上选择的前缀来避免任何混淆。如:foo_read(),foo_write()等。驱动程序基础内存分配n函数kmalloc()内存以2的幂大小的块分配有一个优先级参数n宏kfree()和函

53、数kfree_s()kfree()调用kfree_s(),和free()一样工作可以直接调用kfree_s(),但是需要知道释放内存块的大小驱动程序基础设备分类n字符设备:不使用缓冲区,顺序读写foo_read()&foo_write()n块设备:需要使用缓冲区,随机读写策略规程n网络设备采用了特殊的处理方法。Structdevice驱动程序基础设备号n主设备号&次设备号主设备号相同的设备使用相同的驱动程序次设备号区分具体设备的实例n命令:lsl/dev/had*驱动程序基础中断vs轮询n工作机制的区别n编程上的区别:UNIX的系统调用:执行模式的改变内核模式下的进程访问进程原来所在的用户空间

54、的存储:get_fs_*()和memcpy_fromfs()读用户空间,put_fs_*()和memcpy_tofs()写入用户空间内存。在进程运行时调用,不需要考虑地址的问题。在中断发生时,这些宏不能使用在中断发生时,这些宏不能使用。因为它们可能覆盖其他运行着的进程的随机空间。必须提供临时空间存放信息。对于块设备,由cache缓冲机制自动提供;字符设备需要驱动程序分配。驱动程序基础DMA方式n用于传送大规模的数据nPC机上的ISADMA控制器8条DMA通道。每条通道联系着一个16位地址寄存器和16位计数器nDMA直接访问物理内存nDMA通道不能被共享。一些设备拥有固定的DMA通道。nStru

55、ctdma_chan结构:每个通道拥有一个此结构两个域:指向该通道拥有者的字符串指针指示该通道是否已分配的标志驱动程序基础睡眠唤醒机制nTASK_INTERRUPTIBLE TASK_UNITERUPTIBLE,决定于睡眠是否能够被系统调用一类的事情打断。一般来说,如果设备比较慢、可以被无限阻塞,包括终端、网络设备或伪设备,睡眠应该是可中断的n_sleep_on()nStructwait_queuestructtask_struct*task;structwait_queue*next;驱动程序基础设备文件n设备管理的“上半部分”nStructfile结构include/linux/fs.hn

56、增加一个设备时需要用mknod命令为该设备创建一个inode驱动程序基础file_operationsnlseek():转到所需的偏移。structinode*inode指向此设备inode结构的指针。Structfile*file指向此设备的文件结构的指针。Off_toffset要转移到的相对origin指示的基准的偏移地址。Intorigin0=采用相对于绝对地址0(开始)的偏移量。1=采用相对于当前位置的偏移量。2=采用相对于末尾的偏移量。Lseek()在出错是返回出错码errno,否则返回lseek操作以后的绝对地址(=0)。nread()和write()struct inode *i

57、node:指向代表要访问的设备的特殊文件的指针。sturct file *file:指向该设备的文件结构的指针。 Char *buf:一个读写的字符缓冲区。位于用户空间内存中,可以用get_fs*(),put_fs*()和memcpy*fs()访问。 Int count:缓冲区中读或写的字符的计数。它是buf的大小,也是知道怎样到达buf的末尾的手段,因为buf是没有保证以NULL结尾的。 nSelect()structinode*inode:指向该设备的inode结构的指针。Structfile*file:指向设备的文件结构的指针。Intsel_type:可以执行的选择类型SEL_INrea

58、dSEL_OUTwriteSEL_EXexceptionSelect_table*wait如果设备没有准备好,调用select_wait(),并且返回0。如果设备准备好,返回1。nioctl()函数:处理ioctl调用。结构:首先差错检查,然后用一个大的switch语句来处理所有可能的ioct。参数:Structinode*inodeStructfile*fileUnsignedintcmd:ioctl命令。一般用于做case语句的switch参数。Unsignedintarg这是此命令的参数,由用户定义。返回:出错返回-error。其他情况下返回由用户定义。nmmap()函数函数Struct

59、inode*inodeStructfile*fileUnsignedlongaddr需要映射进入的主存开始地址。Size_tlen需要映射的存储空间长度。Intprot下面中的一个:PROT_READ可以读的区域。PROT_WRITE可写的区域PROT_EXEC可执行的区域PROT_NONE不可访问的区域Unsignedlongoff需要映射的文件偏移地址。这个地址将被映射到addr。n open()和release()函数Structinode*inode指向此设备的inode结构的指针。Structfile*file指向此设备的文件结构的指针。Open()在设备特殊文件打开时调用。是用来保

60、证一致性的策略机制。Release()只在进程关闭它打开的最后一个文件描述子的时候调用?ninit()函数函数内核第一次启动时调用:在正确的位置调用init():字符设备drivers/char/mem.c中的chr_dev_init()把file_operation注册到VFS中:对于字符设备register_chrdev()打印关于设备的信息,并且报告找到的硬件printk()中断处理n文件/proc/interruptsn函数request_irq()n函数free_irq()n睡眠与唤醒n中断共享nISR的上部和下部(bottomhalf)辅助函数请求调度nStaticvoidadd_

61、request(structblk_dev_struct*dev,structrequest*req)Staticvoidend_request(structblk_dev_struct*dev,structrequest*req)staticvoidmake_request(intmajor,intrw,structbuffer_head*bh)voidll_rw_block(intrw,intnr,structbuffer_head*bh)make_request()调用add_request()ll_rw_block()对请求队列排序,只能通过buffercache调用。n电梯算法:读在

62、写前低次设备号请求在高次设备号前低块号在高块号前drivers/block/ll_rw_block.c辅助函数定时器管理nvoidadd_timer(structtimer_list*timer)voiddel_timer(structtimer_list*timer)voidinit_timer(structtimer_list*timer)nstructtimer_list辅助函数中断管理nexternintrequest_irq(unsignedintirq,void(*handler)(int,void*,structpt_regs*),unsignedlongflags,constc

63、har*device,void*dev_id);voidfree_irq(unsignedintirq)ncli()sti()辅助函数端口读写nvoidout*()unsignedcharbyte,unsignedportnunsignedin*()参数:unsignedport*:b,w,ln用in*()来清空某些状态值?辅助函数内存管理&设备号nkmalloc()nkfree()kfree_s()n设备号由主、次设备号拼接而成。#defineMAJOR(dev)(dev)8)#defineMINOR(dev)(dev)&0xff)辅助函数设备的注册和注销nintregister_chrde

64、v(unsignedintmajor,constchar*name,structfile_operations*fops)intregister_blkdev(unsignedintmajor,constchar*name,structfile_operations*fops)intunregister_chrdev(unsignedintmajor,constchar*name)intunregister_blkdev(unsignedintmajor,constchar*name)#include#include辅助函数内存空间转换ninlinevoidmemcpy_tofs(void*t

65、o,constvoid*from,unsignedlongn)inlinevoidmemcpy_fromfs(void*to,constvoid*from,unsignedlongn)#includen#defineget_user(ptr)(_typeof_(*(ptr)_get_user(ptr),sizeof(*(ptr)#defineput_user(x,ptr)_put_user(unsignedlong)(x),(ptr),sizeof(*(ptr)#includen在用户空间和内核空间拷贝内存n属于隐含的I/O操作,不要再临界代码中使用,因为它可能冲破cli()和sti()的保护

66、辅助函数缓冲区管理nfs.cstructbuffer_head*getblk(kdev_tdev,intblock,intsize);voidbrelse(structbuffer_head*buf);voidll_rw_block(intrw,intnr,structbuffer_head*bh);辅助函数其他nintprintk(constchar*fmt,.)#include在内核中打印信息,是printf的内核版本可能导致隐含的I/O操作。不要在cli()保护的代码段中使用,因为它可能导致开中断。n一些与进程相关的系统调用模块编程基础n模块的基本概念:可以动态的加载到内核中成为kern

67、el的一部分;加载后可以访问内核的数据结构;用户空间的程序或进程可以通过某个模块和内核交互。nmodule在需要的时可通过符号表(symboltable)使用核心资源。n而且module一般需要调用核心的资源,所以必须注意module的版本和核心的版本的相配问题。一般在module的装入过程中检查module的版本信息。模块之间的函数调用 内核可以使用其它模块或内核的函数,也可以export一些函数供其他模块或内核使用。 模块栈:如果模块A使用了模块B的函数,那么B必须在A之前加载,否则加载A的命令不成功。模块可以使用的函数: 自身定义; 其他module提供; 内核提供命令ksyms a:列

68、出已经加载的模块的函数或变量。Symbol table:记录module导出的函数或变量。所有声明为global的函数或变量都意味着被导出,可以被其他模块使用。模块编程基础常用命令nlsmod把现在kernel中已经安装的modules列出来ninsmod 把某个module安装到kernel中。nrmmod把某个没在用的module从kerne中卸载。ndepmod 制造moduledependencyfile,以告诉将来的insmod要去哪儿找modules来安装。这个dependencyfile放在/lib/modules/当前kernel版本/modules.dep。模块基础装入nIn

69、smod命令n内核kerneld守护进程(daemon)自动装入。守护进程:在超级用户下运行的一个用户进程,与核心建立一个IPC通道。Kerneld调用insmod和rmmond来装入和移出模块。kerneld装入的module,一般放在/lib/modules/kernel-version目录下。ninsmod命令调用sys_get_kernel_sys()系统调用收集核心中所有符号来解决module中资源引用问题。模块基础装入n符号表的记录有两个域:符号的名字(symbolname)和符号的值(一般是符号的地址)。核心提供的符号表在module链表最尾module中。ninsmod调用sy

70、s_create_module(),为新module分配一个module数据结构,挂在module_list头上,置新module状态为UNINITIALIZED。n当初始化module时,insmod调用sys_init_module()系统调用,将module的初始化和清除函数作为参数传递。修改核心的符号表,同时系统需要修改新module依赖的所有module中的相关指针。 模块基础卸载nRmmod命令nKerneld进程自动卸载自动卸载的机制为:每隔一定的时间,kerneld调用sys_delete_module()系统调用,将它装入的且不在被使用的module从系统中卸载。它遍历mod

71、ule_list,检查被它装入(AUTOCLEAN)并且不用(VISITED标志)的模块。内核模块必须有两个函数: int init_module():为内核中的某些东西注册一个句柄,或者把内核中的程序提换成它自己的代码(通常是进行一些工作以后再调用原来工作的代码)。 void clean_module():模块要求撤销init_module进行的所有修改,使得模块可以被安全的卸载。 在insmod和rmmod命令中使用这两个函数。Use count:记录使用本模块的进程数或模块数。 MOD_INC_USE_COUNT:增加use count MOD_DEC_USE_COUNT:减少use c

72、ount MOD_IN_USE:检查use count是否是0模块基础数据结构nstructmodulestructmodule*next;structmodule_ref*ref;/*所有引用该模块的模块,也用链表连接*/structsymbol_table*symtab;/*符号表*/constchar*name;/*模块的名字,存放在module结构后面的64个字节里*/intsize;/*sizeofmoduleinpages*/void*addr;/*addressofmodule*/intstate;/*三种状态:未初始化,运行,删除*/void(*cleanup)(void);/

73、*cleanuproutine*/;struct symbol_table int size; /* 包括string table的总长度 */int n_symbols; int n_refs;struct internal_symbol symbol0; struct module_ref ref0; ; 后面定义的是两个零大小的数组声明,便于动态分配空间。 symbol包含一组字符串指针,指向真正的符号字符串表struct internal_symbol /*符号信息*/void *addr;const char *name; /*指向string table*/;struct modu

74、le_ref /*引用信息*/struct module *module;struct module_ref *next;string table的内容是该模块导出的函数名和变量名模块基础系统调用nSys_create_module为模块分配空间,将模块链入系统的模块链中nSys_init_module初始化模块,修正指针使模块正常工作nSys_delete_module从系统模块链中删除模块,释放内存空间nSys_get_kernel_syms将系统的所有符号表全部取出到用户空间insmod先调用系统调用sys_get_kernel_syms,将当前加到系统中的模块和核心的符号表全部输出到k

75、ernel_sym结构中,为后面使用。这个结构的内容在insmod用户进程空间。将Mymodule目标文件读进insmod用户进程空间,成为一个映像。根据第一步得到的信息,将Mymodule映像中的地址没有确定的函数和变量一一修正过来。调用系统调用sys_create_module、sys_init_module,将Mymodule链入到系统中去。 n内核模块的编译 需需要要用用-c-c选选项项进进行行编编译译。所有的内核模块都必须包含特定的标志:_KERNEL_:这个标志告诉头文件此代码将在内核模块中运行,而不是作为用户进程。MODULE:这个标志告诉头文件要给出适当的内核模块的定义。LIN

76、UX:从技术上讲,这个标志不是必要的。用于比较正规的内核模块,在多个操作系统上编译,这个标志将会使你感到方便。它可以允许你在独立于操作系统的部分进行常规的编译。例:gcc-Wall -DMODULE -D_KERNEL_ -DLINUX hello.c-D表示加入标志用户空间设备驱动程序n有时不需要真正的驱动程序:没有两个以上的应用程序使用设备并且不需要响应中断没有多个进程访问不管理资源n例:vgalib库早期的鼠标转换设备驱动程序框架接口nLinux设备驱动程序与外界的接口1.设备驱动程序与操作系统内核的接口,通过file_operations(include/linux/fs.h)完成。2

77、.驱动程序与系统引导的接口,初始化设备。3.驱动程序与设备的接口。与具体设备相关。驱动程序框架功能n驱动程序的注册与注销n设备的打开与释放n设备的读写操作n设备的控制操作n设备的中断和轮询处理初始化函数的调用关系n系统转入核心,调用函数start_kernel()。它调用kernel_thread(init,NULL,0),创建init进程进行系统配置(其中包括所有设备的初始化工作)。sys_setup()device_setup()chr_dev_init()/blk_dev_init()Kernel_thread()init()setup()注册与注销n注册和注销函数:register_*

78、dev()unregister_*dev()/include/linux/fs.hn所谓注册就是在内核的chrdevs或blkdevs中添加一项。structdevice_structconstchar*name;structfile_operations*fops;相同主设备号的fops元素内容相同。打开与释放n打开设备:open()检查与设备有关的错误,如未准备好。如果是首次打开,则初始化设备。确定次设备号,根据需要可更新设备的f_op。如果需要,分配且设置文件中的private_data。递增设备使用的计数器。如果只允许一个进程使用设备,则需要设忙标志。 释放设备:release() 递

79、减设备使用的计数器 释放设备文件中的私有数据所占空间 如果是独占设备,则要清除忙标志,使其他进程可以使用 如果是最后一个释放,则关闭设备设备的读写操作n字符设备:foo_read()和foo_write()n块设备block_read和block_write()策略规程,不需要在驱动程序中实现。通过缓冲区读写,只在数据不在缓冲区时才真正执行数据传输,通过request_fn()完成。structblk_dev_structstructrequest设备的控制nioctl() 一般做法是: 首先差错检查, 然后用一个大的switch语句(可能是内嵌的)来处理所有可能的ioctl命令。返回:出错返

80、回-erro其他情况由用户定义字符设备驱动程序n数据结构n注册与注销n轮询和中断对应驱动程序的“三个接口”。添加一个简单的字符设备n确定主设备号n编写file_operations中的函数以及中断处理函数。n编写初始化函数foo_init()n在chr_dev_init()中添加调用和返回初始化函数的代码。n修改修改drivers/char/Makefiledrivers/char/Makefile;假设我们把所以必要的函数写foo.c中,则在“L_OBJS := tty_io.o n_tty.o console.o ”行把“foo.o”加到其中。将将 该该 设设 备备 私私 有有 的的 *.

81、c, *.h复复 制制 到到 目目 录录drivers/char下。下。用用命命令令:make clean;make dep;make zImage重重新编译内核。新编译内核。用用mknod命命令令在在目目录录/dev下下建建立立相相应应主主设设备备号号的的用于读写的特殊文件用于读写的特殊文件 mknod命令:建立设备特殊文件 格式: mknod 文件名 类型 主设备号 次设备号 类型:c或b,代表字符设备或块设备块设备驱动程序n数据结构n注册与注销n读写请求及其处理增加一个块设备的方法和字符设备差不多。块设备不需要编写file_operations结构里的read和write函数,但是也需要

82、read和write在request中调用。需要有请求处理函数,以及中断处理函数。嵌入式网络技术嵌入式网络技术TCP/IP协议简介协议简介nTCP/IP协议是一套把因特网上的各种系统互连起来的协议组,保证因特网上数据的准确快速传输n参考开放系统互连(OSI)模型,TCP/IP通常采用一种简化的四层模型:n应用层n传输层n网络层n链路层协议的实现n协议是面向连接的、端对端的可靠通信协议。n它采用了许多机制来保证可靠传输,应用于嵌入式系统显得过于复杂n协议数据传输可分为三个阶段:建立连接、传输数据和断开连接。n它的实现过程可以用状态机来描述。TCP连接建立n建立连接有两种方法,即主动打开和被动打开

83、n服务器端是一种被动打开,它一直在侦听连接请求n而客户端是一种主动打开,它发送连接请求以建立连接。TCP连接断开n断开连接有两种方式:一是主动断开连接;另一是被动断开连接n被动断开连接的处理较为简单,但标准协议的主动断开连接的状态机部分过于复杂。n经过实验发现,在需要主动断开连接的时候,发送一个数据报;接收到对数据报的确认后,再发送一个数据报,即可顺利完成一次主动断开连接。n标准的协议使用慢启动的滑动窗口机制协议n协议是的基础n为不同网络的主机之间发送数据报的操作序列提供无连接服务n通过在数据报前添加协议头,使每个数据报具有寻址能力。n嵌入式系统只把作为传输工具,进行简化以完成主要的操作其它协

84、议n协议为位地址到对应的位以太网地址之间提供动态映射。n嵌入式系统中仅响应请求,发送回答包。n请求者广播出包含请求的以太帧、目的以太网地址为全的广播地址。本机收到后,由目的地址发现自己是目的主机,发送一个回答。n通过协议传输其报文。协议是无连接的,它无法将报文和错误信息传到最初的主机,将状态信息和错误信息发送到发报文的主机。嵌入式嵌入式TCP/IP协议栈应用前提协议栈应用前提n连接在互联网上的电子装置不一定比单独使用的电子装置具有更高的智能功能,但连通意味着提高智能化管理水平nTCP/IP是一项应用广泛的标准,利用它可以接通并控制电子装置,通过绝大多数传输媒体几乎可以和运行在所有操作系统上的软

85、件进行通信n通过TCP/IP与基础设施连接十分简单嵌入式嵌入式TCP/IP协议栈协议栈适用的范围n在商业系统,利用它来进行远程监视服务很有意思n嵌入式TCP/IP的最大优越性也许在于它可以使得嵌入式电子装置支持嵌入式的万维网服务器n嵌入式TCP/IP的主要用途是进行远程监测n万维网服务器还可以对一个电子装置进行远程配置存在的局限n首先嵌入式栈是建在专用的软插座API之上的n提供可靠传输,占用了大量的资源n体积太大,许多场合不适用实施的方法实施的方法n采用软件的方式n硬件方法n采用iReady的芯片或芯核,虽然使用的是4位微处理器也能够和互联网实现直接连接nDSP方法n也可以选用DSP为基础的T

86、CPIP协议栈采用方法选择n根据所设计的电子装置的实际情况来决定n使用硬件功能如何?n打算如何来实现和互联网的连接?n需要发送和接收那些种类的信息?n将软件或硬件芯片整合到所设计的电子装置中去,有没有困难?n增加一个协议栈,是否需要对所设计的电子装置进行重大更改等等构件化协议框架概述构件化协议框架概述nTCP/IP协议是发展至今最成功的通信协议n路由器则是Internet的基石n目前的路由器大部分都支持多个协议,即多协议路由器n目前的通讯设备逐步向着多CPU发展n协议构件化框架NSPCF(NetworksSub-ProtocolComponentFrame),应用构件技术将通讯协议划分为子构件

87、,完成高性能路由器上的高效通讯n构件技术把单个的应用程序分割成多个独立的构件,某一块构件可独立的被新的构件更新、替换NSPCF网络子协议构件框架组成网络子协议构件框架组成n传统网络协议和服务设计模式(面对过程)越来越不能满足网络增长和发展的需求nNSPCF主要由四个部分组成:协议构件、构件库、协议构件操作系统、构件开发平台NSPCF模型模型 需求分析需求分析协议模块化协议模块化程序员程序员协议构件协议构件构件开发平台构件开发平台构件库构件库构件操作系统构件操作系统协议运行,提供网络服务协议运行,提供网络服务NSPCF特征特征nNSPCF具有传统CBSD具有的一切特征,包括封装性、复用性、扩展性

88、,同时提供一组扩展特性,诸如系统安全、动态加载、跨平台、分布式、开放性 nNSPCF框架继承于CBSD,基本执行模块是与对象等价的构件 nNSPCF的复用模型是要建立一种基于代码和二进制级的复用模型 n在NPCF框架中,有三种类型的成员public、private、protected n通过设计一个安全进程SP(security process)对系统安全性进行管理 n跨平台性构件跨平台实现构件库构件库构件系统CTECTEDICDICDDCDDC网络协议构件化拆分网络协议构件化拆分n对于传统的按层次划分的网络协议,我们必须先进行模块化,然后才能构件化,组装成协议构件n协议模块化的目的在于控制协

89、议的粒度n构件的粒度越小,协议划分得越细,协议构件越多;构件粒度越大,协议划分得越粗,协议构件就越少n按层次构件化、按功能构件化、按使用对象构件化协议构件的组装构件A1构件A2构件A3构件B1构件B2构件b1构件b2按层次构件化按功能构件化按使用对象构件化n还可以按照协议构件的使用对象对协议进行构件化。n对于某一个网络协议,使用对象可以分为多种,有服务端使用,有客户端使用;有给同一层协议使用的,有给上一层协议使用的;有给一般用户使用的,也有给超级用户使用的,这些使用对象的特性,都可以用来对协议进行构件化。n应用程序在使用网络协议时,有可能只是使用到了协议的某一个模块,例如客户端模块。这时候,就

90、可以提供协议构件中的客户端构件给应用程序。协议构件库设计协议构件库设计n所有的协议构件都被统一放置在构件库PCB(ProtocolComponentBase)中进行统一管理n协议构件库是针对网络通讯需求特点开发的、不断完善改进的、用来对构件化的协议进行使用、管理和维护的软件构件库n管理和维护涉及一系列问题:n构件的有效分类、快捷检索和准确理解机制;n用户权限控制能力;n构件库体系的可定制性与库间互操作性技术问题。n协议构件库是一个由构件数据库、数据库管理系统、网络通信模块等组成的一个完整的体系。构件库结构构件索引n基于层次的构件索引n在协议构件化时,按照OSI参考模型的层次,对每层的协议进行构

91、件化。构件化的协议放在不同的层次中。n基于功能的构件索引n在协议构件化时,按照协议不同组成部分的功能进行划分和构件化。此时,构件化的协议没有层次的要求,但是被构件化的协议应该可以划分出独立的功能模块。n基于使用对象的构件索引n在协议构件化时,按照服务、协议,对每层的协议进行构件化。构件化的协议放在不同的层次中。构件分类n基本构件。基本构件是整个协议构件库的根本,协议和服务最终由基本构件组装而成,因此,在构件库中的实际上是基本构件。n协议构件。协议构件是一种虚拟的构件。即在构件库中实际不存在这种构件,但是为了更方便快捷的检索,建立索引,将常用的协议看成是一种构件。n服务构件。与协议构件一样,它也

92、是一种虚拟的构件,同样,也是对常用的服务建立索引表。协议组装协议组装n协议构件本身是无法单独为通信设备提供服务的,因此需要一种机制,能够将这些被拆分的对象进行组合,以提供通信服务。n针对网络构件化之后,协议栈的动态重构的情况,通过建立构件化协议组装模型来达到协议组装重用和定制通信服务的目的。n构件化协议组装模型从各种协议构件中选择符合需求的模块,按照协议层次重新组装使用。n采用构件化和封装方法后,在对协议进行拆分后产生的构件,将在某一时刻在重新组成协议栈、协议和服务。在进行这个重组时,采用组装模型来完成这个工作协议组装模型作用协议组装模型作用n组装模型与操作系统和构件库的通信,通信设备端与构件库端的通信。n对服务对象性能参数的跟踪、选择和协商。n对服务对象的组装工作。n组装完成的服务对象的检测和初始化。n服务对象的管理工作。组装模型体系结构n用户:用户说明需要的目标服务n通信器:负责与用户和其他模块的通信和交流n组装器:负责将各个构件组装成对应的协议,协调构件关系n测试器:对组装好的服务对象使用典型测试数据进行测试n监控器:负责监控和记录构件执行的各项参数,在适当的时候反馈给构件库n管理器:负责控制和维护不同的通信服务

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号