嵌入式Linux系统的搭建与配置过程_第1页
嵌入式Linux系统的搭建与配置过程_第2页
嵌入式Linux系统的搭建与配置过程_第3页
嵌入式Linux系统的搭建与配置过程_第4页
嵌入式Linux系统的搭建与配置过程_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目录1 .摘要 22 .UBOOT , LINUX内核,文件系统的介绍及相互关系.32.1 嵌入式系统简介 32.2 嵌入式Linux概述32.3 UBOOT 简介.43 .UBOOT的启动过程 .64 .内核的主要功能和裁剪 74.1 Linux 的编译 74.2 嵌入式Linux的配置和剪裁 .85 .文件系统的制作过程86 .交叉编译器的搭建和环境变量的设置 .97 .驱动程序的编写过程与关键点 117.1 Linux网络驱动程序的结构 117.2 网络驱动程序的基本方法 127.3 网络驱动程序中用到的数据结构 .127.4 常用的系统支持.147.5 编写Linux网络驱动程序中需要

2、注意的问题 18.208 .参考文献摘要嵌入式系统是以应用为中心,以计算机为基础,并且软硬件可裁剪,适用于应用系统对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统。嵌入式系统一般由嵌入式微处理器、外围硬件设备、嵌入式操作系统以及用户的应用程序 4 部分组成,用于实现对其它设备的控制、监视或管理等功能。其广泛应用于控制领域、消费电子产品等行业,已成为现代电子领域的重要研究方向之一。嵌入式 Linux 的研究已经成为当前信息技术研究的热点,它的应用蕴含着巨大的商业价值,并且己经广泛的应用于各种信息家电、通讯产品、工业控制中。论文首先介绍了ARM 和嵌入式Linux 操作系统的特点和当前的

3、发展概况。然后阐述了嵌入式Linux开发流程以及移植到具体硬件平台需要完成的工作,如U-Boot 的移植、 Linux 内核的编译与裁剪、文件系统的制作、驱动程序的编写等。关键字:嵌入式;ARM ;嵌入式Linux;Linux 内核;驱动程序2 . LINUX , UBOOT ,文件系统的介绍及相互关系2.1 嵌入式系统简介嵌入式系统是以应用为中心,以计算机为基础,并且软硬件可裁剪,适用于应用系统对功能、可靠性、 成本、 体积、 功耗有严格要求的专用计算机系统。单片机、单板机控制系统以及一些专用的工业控制计算机都可以称作嵌入式系统,它是嵌入式系统领域的重要组成部分,只是更着重于对各自硬件系统的

4、研究。嵌入式系统更着重于对软件系统进行研究,顺应了软硬件协同设计以及应用需求的发展。目前,嵌入式系统己逐步发展成为一门学科,朝着系统化和规范化的方面发展。嵌入式系统学科和产业的发展使得设计人员能够从容地面对越来越复杂的应用需求,通过软件和硬件的模块化设计大大地简化和加快应用系统的开发.嵌入式系统主要包括硬件和软件两部分。硬件包括处理器、存储器及外部设备、I 0端口和图形控制器等;软件部分包寸S操作系统(OS)和用户应用程序。嵌入式系统硬件的核心是嵌入式微处理器。它的功能、外设集成度、速度、功耗、体积、成本、 可靠性和电磁兼容性等方面均受到应用要求的制约,是各个半导体厂商之间竞争的热点。嵌入式系

5、统的软件是实现嵌入式系统功能的关键,软件要求固化存储, 代码的高质量、高可靠性和高实时性在许多场合也是基本要求。多任务嵌入式操作系统是知识集成的平台,是嵌入式系统走向工业标准化道路的基础,是嵌入式系统研究的重要方向。现在人们讲嵌入式系统时,某种程度上是指近些年来比较热门的具有操作系统的嵌入式系统。2.2 嵌入式 Linux 概述Linux操作系统源于芬兰一位大学生一LinusTorvalds的课余作品,随着Intemet的发展,Linux 操作系统在全球计算机爱好者的关怀下,不断地发展和成长,己成为当前最流行的免费操作系统,任何人都可以自由的使用Linux 源程序。 嵌入式Linux操作系统的

6、组成,我们可以和PC机相对应来理解,在PC机上,Windows 的启动大致有BIOS、内核、文件系统和初始化程序几个部分;那么相对而言,嵌入式 Linux 的移植有Bootloader、 Linux 内核、文件系统、初始化和用户的应用程序几部分,Bootloader完成系统的初始化和引导。Linux 操作系统具有以下几大特点:(1)开放源码,丰富的软件资源Linux 遵循 GPL(GNU 通用许可证), 用法律保障了用户免费获得内核源代码的权利。由于嵌入式系统千差万别,往往需要针对某一具体应用去修改和优化系统,这样,能否获得源代码就至关重要。Linux 是自由的操作系统,它的开放源代码使用户获

7、得了最大的自由度。Linux 上的软件资源十分丰富,每种通用程序在Linux 上都可以找到,并且每天都在增加。在Linux 上往往不需要从头做起,而是先选择一个类似的自由软件,进行二次开发。这就大大节省了开发工作量,缩短了开发时间。(2)功能强大的内核,性能高效、稳定、多任务Linux 的内核非常稳定。它的高效和稳定性已经在各个领域,尤其在网络服务器领域得到了事实的验证,而且Linux 内核小巧灵活,易于裁剪。这使Linux 能很适合嵌入式系统的应用。(3)支持多种体系结构Linux 能支持 X86, ARM, MIPS, POWERP,ALPHA,SPARC 等多种体系结构。目前, Linu

8、x 己被移植到数十种硬件平台上,几乎所有流行的CPU, Linux 都支持。(4)完善的网络通信、图形和文件管理机制Linux 自产生之日起就与网络密不可分,网络是 Linux 的强项。 另外, 它支持ext2,fatl6, fat32, romfs 等多种文件操作系统。在图形系统方面,Linux 上既有成熟的xWindow,也有embedcd QT,MiniGUI等嵌入式图形用户界面 GUI,还有ysvgalib, framebuffer 等优秀工具,可以适合不同的用途。(5)支持大量的周边硬件设备,驱动丰富Linux 上的驱动己经非常丰富了,支持各种主流硬件设备和最新硬件技术,而且随着 L

9、inux 的广泛应用,许多芯片厂家也已经开始提供Linux 上的驱动。这一步促进了 Linux 各种硬件平台上的应用。(6)大小功能都可定制Linux 继承了 Unix 的优秀设计思想,内核与用户界面是完全独立的。它非常灵 活,各部分的可定制性都很强,能适合多种需求。2.3 UBOOT 简介U-Boot是一个非常复杂的东酉,它也体现了嵌入式系统的一个非常重要的特 征:自己定制。它脱胎于 PC机的Linux,可从网站上直接下载,U. Boot和其 它任何 BOOTLOADER 都是一样的,主要实现对系统进行初始化、系统引导、FLASH操作等功能。开发平台的U. Boot主要是对板子的硬件进行初始

10、化,包 括:时钟和PLL、定时器、调试用D(DebugDART)等等。有了 U. B00t我们可 以在主机的超级终端通过调试串口和目标机进行通信和设置。2.3.1 编译 U-Boot在Linux系统下,用下面的命令对 U . Boot进行编译$cdU. BOOT;进入目录Smakeat91rm9200dk_eonfig 编译Smakeall$gzip_cu-boot. bin>u-boot. gz; 压缩为 gz 文件编译boot bin$cdBootSmake编译loader bin$cdLoaderSmake2.3.2 U. Boot命令在本系统中,采用的是U-Boot, U-Boo

11、t在嵌入式系统中相当于Pc机的BIOS加上操作系统引导头部的内容,并且引导操作系统进行装载和运行,U Boot 启动后有一系列的命令,使得我们能够方便的对FLASH 、 RAM 进行操作,U Boot已经对系统的频率、定时器进行了设置,初始化了一个调试串口,我们可以通过串口或者以太网进行数据的下载。下面是U. Boot常用的命令:go 一在地址addr'处开始程序执行run 一运行命令bootm 一从内存中进行应用程序影像运行bootp 一通过网络用BootP/TFTP协议来启动影像tf砸boot 一通过网络用TFTP协议、设置服务器和客户机的IP地址进行影像文 件传送loadb -通

12、过用口线(kermitmode)来装载二进制文件 pfintcnv 一打印环境变量 .setcnv -设置环境变量saveenv 保存环境变量到内存 下面是U. Boot的简单环境变量 baudrate 一波特率 bootdelay-Boot 延迟 bootcmd -Boot 命令 bootargs Boot 参数 ipaddr 一客户机IP地址 servefip 一服务器地址 loadaddr 一装载地址 etlladdr 一网卡MAC地址3 .UBOOT的启动过程嵌入式Linux系统一般没有自举程序,必须通过启动程序来引导硬件系统进入操 作系统。启动程序的工作包括:改变系统时钟、关闭WAT

13、CHDOG始化存储控制器等。本文针对本嵌入式控制系统所需的硬件方案,植入 Uboot1-3.4启动程 序。U-Boot是一种功能强大的引导转载程序。它不仅支持Linux、Vxworks等操作系统,还支持PowerPC ARM?多种系列处理器。Uboot启动过程分为两个阶 段。第一阶段由汇编来实现,用于完成依赖于CP冰系结构的初始化,并调用第 二阶段的代码。第二阶段由C语言实现,完成相关初始化后,进入命令循环以等 待用户命令,或将参数传给内核,引导Linux内核启动。图中给出了 Uboot的启 动流程。Uboot-1.3.4 中对at91rm9200dk系列的开发板有很好的支持,只需做少 量修改

14、即可使用。但是在目前 U-Boot-1.3.4引导系统中,不能识别本论文中采 用的 8MB NOR Flash! (SPANSIO淤司的 S29GL064N90TFI04 和 1GB NAND Flash (SAMSUNG司的K9K8G08U0A两款芯片,需要自行移植。4 .Linux的编译,内核配置和裁剪4.1 Linux的编译在配置内核前的须做必要的设置, 主要在内核原码中设置文件 Makefile,用下列 指令打开 Makefile 文件:$viMakefile在Makefile中主要设置两个地方: ARCH CROSSCOMPILE。ARCH: =arm;表示目标板为arm。CROSS

15、 COMPILE=交叉编译工具的地址 ; 设置交叉编译工具的地址,例如 CRoSSCOMPILE=lusr/10cal/arm/2. 95. 3、 birdarm. linux。还要在脚本文件 mkimage中把路径改为9200/bootldr/ u-boot-1. 0. O/toolSo (具体的路径和你的u-boot放的位置有关)然后按如下命 令顺序进行内核编译即可:内核配置:Smake menuconfig 或 makcxeon!ig 内核编译:Smaketiean $make dep $make $. /mkimage; 运行 mkimage脚本文件4 . 2嵌入式Linux的配置和剪

16、裁在 Linux 下,用 makemenuconfig或 makexeontig进入酉己置界面。在内核酉已置中, 一般有四种选择:Y(选择)、N(不选)、M(模块)和数字,用户可以根据剪裁需要 进行设置,最后配置完毕,选择是否对配置结果进行保存?保存为.eonfig文件。5 .嵌入式Linux文件系统的制作过程嵌入式系统可以使用硬盘和光盘,但是这与嵌入式系统的便携式特性相违背, 所 以一般采用Flash作为存储介质。和硬盘相比,Flash有自己独特的物理特性,所 以必须使用专门的文件系统。嵌入式系统对文件的操作是通过层次结构实现的。对于用户程序来说,文件是有结构的文件,用户程序通过文件I/O函

17、数操作文件。嵌入式文件系统是嵌入式系统的一部分,它的任务是对逻辑文件进行管理, 其工作包括提供对逻辑文件的操作(复制、删除、修改等)接口,方便用户操作文 件和目录。在文件系统的内部,又根据存储设备的特点,适用不同的文件组织模 式来实现文件的逻辑结构,比如磁带终使用的顺序文件以及大多数操作系统适用 的树状文件。止匕外,文件系统要对管理文件的安全性负责。目前支持闪存的文件 系统技术有以下几种:eJFFS2和Yaffso这些文件系统可以使用在没有初始化的NANDFlash和有CFI接口的NORFlash中。eTrueFFS,该文件系统相当于 Linux中的MTD层,必须 配合其他文件系统。eFTL/

18、NTFL,它是一种中间层解决方案的统称,为上层文 件系统提供接口。eRAMFS、CRAMFS和ROMFS,这些文件系统用于早期的小 容量闪存设备,系统功能比较简单,仅提供基本接口,只属于只读的闪存文件系统。适合存储空间小 的系统。可按照如下步骤制作自己的文件系统:解开压缩的文件系统: $gamzipramdisk. gz 文件系统挂载:$mount_oloopramdisk/ mnt/nweramdisk(注:newramdisk 是新建的目录)。进入newramdisk目录进行操作,随意的增减文件:Sod/ nmt/newramdisk(注:进入目录后敲入命令随意的增减文件) 退出newra

19、mdisk目录后御载文件系统:Sumount/ mnt/ newramdisic压缩文件系统,生成新的文件系统映象:$gzip-c-、,9ramdisk>. / newramdisk6 .Linux中交叉编译器的搭建和环境变量的设置1.安装标准的C开发环境,由于Linux安装默认是不安装的,所以需要先安装 一下(如果已经安装好的话,就可以免去这一步了):#sudo apt-get install gcc g+ libgcc1 libg+ make gdb2 . 下载 arm-linux-gcc-3.4.1.tar.bz2 到任意的目录下。3 .解压 arm-linux-gcc-3.4.1

20、.tar.bz2#tar -jxvf arm-linux-gcc-3.4.1.tar.bz2解压过程需要一段时间,解压后的文件形成了 usr/local/文件夹,进入该文 件夹,将arm文件夹拷贝到/usr/local/下# cd usr/local/#cp -rv arm /usr/local/现在交叉编译程序集都在/usr/local/arm/3.4.1/bin下面。4.修改环境变量,把交叉编译器的路径加入到PATH。方法一:修改/etc/bash.bashrc文件#vim /etc/bash.bashrc在最后加上:export PATH = $PATH:/usr/local/arm/3

21、.4.1/binexport PATH方法二:修改/etc/profile文件:# vim /etc/profile增加路径设置,在末尾添加如下,保存/etc/proMe文件:export PATH =$PATH:/usr/local/arm/3.4.1/bin方法三:#export PATH = $PATH:/usr/local/arm/3.4.1/bin注:(这只能在当前的终端下才是有效的!)5 .立即使新的环境变量生效,不用重启电脑:对应方法一:#source /root/.bashrc对应方法二: # source /etc/profile6 .检查是否将路径加入到PATH :# ec

22、ho $PATH显示的内容中有/usr/local/arm/bin ,说明已经将交叉编译器的路径加入 PATH。至此,交叉编译环境安装完成。7 .测试是否安装成功# arm-linux-gcc -v上面的命令会显示arm-linux-gcc信息和版本:Reading specs from /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1/specsConfigured with:/work/crosstool-0.27/build/arm-linux/gcc-3.4.1-glibc-2.3.2/gcc-3.4.1 /configure -target=a

23、rm-linux -host=i686-host_pc-linux-gnu-prefix=/usr/local/arm/3.4.1 -with-headers=/usr/local/arm/3.4.1/arm-linux/include -with-local-prefix=/usr/local/arm/3.4.1/arm-linux -disable-nls -enable-threads=posix -enable-symvers=gnu -enable-_cxa_atexit-enable- languages=c,c+ -enable-shared -enable-c99 -enabl

24、e-long-long Thread model: posixgcc version 3.4.18.编译Hello World程序,测试交叉工具链写下下面的Hello World程序,保存为hello.c#include <stdio.h>int main()printf("Hello World!/n");return 0;执行下面的命令:# arm-linux-gcc -o hello hello.c修改环境变量这一步修改/etc/profile文件在path中添力口 arm-linux-gcc 路径if "'id -u、" -e

25、q 0 ; thenPATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/arm/3.4.1/bin”elsePATH="/usr/local/bin:/usr/bin:/bin:/usr/games” fi再source /etc/profile就可以刷新环境变量7.驱动程序的编写过程与关键点7.1 Linux网络驱动程序的结构所有的Linux网络驱动程序遵循通用的接口。设计时采用的是面向对象的方法。一个设备就是一个对象(device结构),它内部有自己的数据和方法。每一

26、个设 备的方法被调用时的第一个参数都是这个设备对象本身。这样这个方法就可以存取自身的数据(类似面向对象程序设计时的this引用)。一个网络设备最基本的 方法有初始化、发送和接收。deliver packets | receive packets queue|(dev_queue_xmit()| |them(netif_rx() | | methods and variables(initialize,open,close,hard_xmit,| | interrupt handler,config,resources,status)II|send to hardware |receivce f

27、rom hardware | hardware media |初始化程序完成硬件的初始化、device中变量的初始化和系统资源的申请。发送程序是在驱动程序的上层协议层有数据要发送时自动调用的。一般驱动程序中不对发送数据进行缓存,而是直接使用硬件的发送功能把数据发送出去。接收数据一般是通过硬件中断来通知的。在中断处理程序里,把硬件帧信息填入一个skbuff结构中,然后调用netif_rx()传递给上层处理。7.2 网络驱动程序的基本方法网络设备做为一个对象,提供一些方法供系统访问。正是这些有统一接口的方法,掩蔽了硬件的具体细节,让系统对各种网络设备的访问都采用统一的形式,做到硬件无关性。下面是最

28、基本的方法。(1) 初始化(initialize)(2)打开(open)(3)关闭(stop)( 4)发送(hard_start_xmit)( 5)接收(reception)( 6)硬件帧头(hard_header)1.1 7)地址解析(xarp)1.2 8)参数设置和统计数据1.3 网络驱动程序中用到的数据结构最重要的是网络设备的数据结构。定义在include/linux/netdevice.h 里。1.4 常用的系统支持1.4.1 内存申请和释放include/linux/kernel.h里声明了 kmalloc()和kfree()。用于在内核模式下申请和释 放内存。Void *kmall

29、oc(unsigned int len,int priority);void kfree(void *_ptr);与用户模式下的malloc()不同,kmalloc()申请空间有大小限制。长度是 2的整次 方。可以申请的最大长度也有限制。另外 kmalloc()有priority参数,通常使用时 可以为GFP_KERNEL,如果在中断里调用用GFP_ATOMIC参数,因为使用GFP_KERNEL则调用者可能进入sleep状态,在处理中断时是不允许的。Kfree()释放的内存必须是kmalloc()申请的。如果知道内存的大小,也可以用kfree_s()释放。1.4.2 request_irq()

30、、 free_irq()这是驱动程序申请中断和释放中断的调用。在include/linux/sched.h里声明。RequestJrq()M 用的定义:int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id);irq是要申请的硬件中断号。在Intel平台,范围0-15。Handler是向系统登记的中断处理函数。这是一个回调函数,中断发生时,系统调

31、用这个函数,传入的参数包括硬件中断号,device id,寄存器值。Dev_id就是下面的request_irq时传递给系统的参数dev_id。 Irqflags 是中断处理的一些属性。比较重要的有SA_INTERRUPT ,标明中断处理程序是快速处理程序(设置SA_INTERRUPT)还 是慢速处理程序(不设置SA_INTERRUPT)。快速处理程序被调制时屏蔽所有中 断。慢速处理程序不屏蔽。还有一个SA_SHIRQ 属性,设置了以后运行多个设备共享中断。Dev_id 在中断共享时会用到。一般设置为这个设备的device 结构本身或者NULL 。中断处理程序可以用dev_id 找到相应的控制

32、这个中断的设备,或者用irq2dev_map找到中断对应的设备。Void free_irq(unsigned int irq,void *dev_id);1.4.3 时钟时钟的处理类似中断,也是登记一个时间处理函数,在预定的时间过后,系统会调用这个函数。在include/linux/timer.h 里声明。Struct timer_list struct timer_list *next;struct timer_list *prev;unsigned long expires;unsigned long data;void (*function)(unsigned long);voidadd

33、_timer(struct timer_list * timer);int del_timer(struct timer_list * timer);voidinit_timer(struct timer_list * timer);使用时钟,先声明一个timer_list 结构, 调用 init_timer 对它进行初始化。Time_list结构里expires是标明这个时钟的周期,单位采用jiffies的单位。Jiffies是Linux 一个全局变量,代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位 就是1/HZ。I

34、ntel 平台 jiffies 的单位是1/100 秒,这就是系统所能分辨的最小时间间隔了。所以 expires/HZ 就是以秒为单位的这个时钟的周期。Function 就是时间到了以后的回调函数,它的参数就是timer_list中的data Data这个参数在初始化时钟的时候赋值,一般赋给它设备的device 结构指针。在预置时间到系统调用function,同时系统把这个time_list从定时队列里清除。所以如果需要一直使用 定时函数,要在function里再次调用add_timer()f巴这个timer_list加进定时队列。1.4.4 I/OI/O 端口的存取使用:inline uns

35、igned int inb(unsigned short port);inline unsigned int inb_p(unsigned short port);inline void outb(char value, unsigned short port);inline void outb_p(char value, unsigned short port);在 include/adm/io.h 里定义。Inb_p()、outb_p()与 inb()、outb_p()的不同在于前者 在存取I/O时有等待(pause厂适应慢速的I/O设备。为了防止存取I/O时发生冲突, Linux 提供对

36、端口使用情况的控制。在使用端口之前,可以检查需要的I/O是否正在被使用,如果没有,则把端口标记为正在使用,使用完后再释放。系统提供以下几个函数做这些工作。Int check_region(unsigned int from, unsigned int extent);void request_region(unsigned int from, unsigned int extent,const char *name);void release_region(unsigned int from, unsigned int extent);其中的参数from表示用到的I/O端口的起始地址,exte

37、nt标明从from开始的端 口数目。Name为设备名称。1.4.5 中断打开关闭系统提供给驱动程序开放和关闭响应中断的能力。是在include/asm/system.h 中的两个定义。#define cli() _asm_ _volatile_ ("cli":)#define sti() _asm_ _volatile_ ("sti":)1.4.6 打印信息类似普通程序里的printf() ,驱动程序要输出信息使用printk() 。在 include/linux/kernel.h 里声明。Int printk(const char* fmt, .);其

38、中fmt是格式化字符串。是参数。都是和printf()格式一样的。1.4.7 注册驱动程序如果使用模块(module)方式加载驱动程序,需要在模块初始化时把设备注册到系 统设备表里去。不再使用时,把设备从系统中卸除。定义在drivers/net/net_init.h里的两个函数完成这个工作。Int register_netdev(struct device *dev);void unregister_netdev(struct device *dev);dev就是要注册进系统的设备结构指针。在register_netdev()寸,dev结构一般填写前面11项,即到init,后面的暂时可以不用初

39、始化。最重要的是name指针和init方法。Name指针空(NULL)或者内容为'0或者name0为空格(space)则系 统把你的设备做为以太网设备处理。以太网设备有统一的命名格式,ethX。对以太 网 这 么 特 别 对 待 大 概 和 Linux 的 历 史 有 关 。 Init 方 法 一 定 要 提 供 , register_netdev(法调用这个方法让你又t硬件检测和设置。Register_netdev(返回0表示成功,非0 不成功。1.4.8 sk_buffLinux 网络各层之间的数据传送都是通过sk_buff。 Sk_buff 提供一套管理缓冲区的方法,是Linux

40、 系统网络高效运行的关键。每个sk_buff 包括一些控制方法和一块数据缓冲区。控制方法按功能分为两种类型。一种是控制整个buffer 链的方法,另一种是控制数据缓冲区的方法。Sk_buff 组织成双向链表的形式,根据网络应用的特点,对链表的操作主要是删除链表头的元素和添加到链表尾。Sk_buff的控制方法都很短小以尽量减少系统负荷。(translated from article written byAlan Cox)常用的方法包括:.alloc_skb() 申请一个sk_buff 并对它初始化。返回就是申请到的sk_buff。.dev_alloc_skb(段似alloc_skb,在申请好缓

41、冲区后,保留 16字节的帧头空间。 主要用在Ethernet驱动程序。.kfree_skb() 释放一个sk_buff。.skb_clone()复制一个sk_buff,但不复制数据部分。.skb_copy()完全复制一个 sk_buff。.skb_dequeue()从一个sk_buff链表里取出第一个元素。返回取出的sk_buff,如果链表空则返回NULL 。这是常用的一个操作。.skb_queue_head()在一个sk_buff链表头放入一个元素。.skb_queue_tail()在一个sk_buff链表尾放入一个元素。这也是常用的一个操作。网络数据的处理主要是对一个先进先出队列的管理,s

42、kb_queue_tail()和 skb_dequeue(亢成这个工作。.skb_insert() 在链表的某个元素前插入一个元素。.skb_append()在链表的某个元素后插入一个元素。一些协议(如TCP)对没按顺序到达的数据进行重组时用到 skb_insert()和skb_append(>.skb_reserve() 在一个申请好的sk_buff 的缓冲区里保留一块空间。这个空间一般是用做下一层协议的头空间的。.skb_put() 在一个申请好的sk_buff 的缓冲区里为数据保留一块空间。在alloc_skb以后,中请到的sk_buf的缓冲区都是处于空(free)状态,有一个ta

43、il指 针指向free空间,实际上开始时tail就指向缓冲区头。Skb_reserve(而free空间 里申请协议头空间,skb_put()申请数据空间。见下面的图。.skb_push() 把 sk_buff 缓冲区里数据空间往前移。即把 Head room 中的空间移一部分到Data area。.skb_pull() 把sk_buff缓冲区里Data area中的空间移一部分到 Head room中。| Tail room(free) |After alloc_skb() | Head room | Tail room(free) |After skb_reserve() | Head ro

44、om | Data area | Tail room(free) |After skb_put() |Head| skb_ | Data | Tail room(free) | |room| push | | | | | Data area | |After skb_push() | Head | skb_ | Data area | Tail room(free) | | pull | | | Head room | | |After skb_pull()1.5 .编写Linux网络驱动程序中需要注意的问题1.5.1 中断共享Linux 系统运行几个设备共享同一个中断。需要共享的话,在申请的

45、时候指明共享方式。系统提供的request_irq()调用的定义: int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname,void *dev_id);如果共享中断,irqflags 设置 SA_SHIRQ 属性,这样就允许别的设备申请同一个中断。需要注意所有用到这个中加勺设备在调用requestjrq()®必须设置这个属性。系统在回调每个中断处理程序时,可以用d

46、ev_id 这个参数找到相应的设备。一般dev_id就设为device结构本身。系统处理共享中断是用各自的dev_id参数 依次调用每一个中断处理程序。1.5.2 硬件发送忙时的处理主 CPU 的处理能力一般比网络发送要快,所以经常会遇到系统有数据要发,但上一包数据网络设备还没发送完。因为在 Linux 里网络设备驱动程序一般不做数据 缓存,不能发送的数据都是通知系统发送不成功,所以必须要有一个机制在硬件不 忙时及时通知系统接着发送下面的数据。一般对发送忙的处理在前面设备的发送方法(hard_start_xmit)里已经描述过, 即如果发送忙,置tbusy为1。处 理完发送数据后,石发送结束中

47、断里消tbusy,同时用mark_bh()调用通知系统继续发送。 但在具体实现我的驱动程序时发现,这样的处理系统好象并不能及时地知道硬件已经空闲了,即在 mark_bh()以后,系统要等一段时间才会接着发送。造成发送效率很低。2M 线路只有10%不到的使用率。内核版本为2.0.35。我最后的实现是不把tbusy 置 1,让系统始终认为硬件空闲,但是报告发送不成功。系统会一直尝试重发。这样处理就运行正常了。但是遍循内核源码中的网络驱动程序,似乎没有这样处理的。不知道症结在哪里。1.5.3 流量控制(flow control)网络数据的发送和接收都需要流量控制。这些控制是在系统里实现的,不需要驱动程序做工作。每个设备数据结构里都有一个参数dev->tx_queue_len, 这个参数标 明 发 送 时 最 多 缓 存 的 数 据 包 。 在 L

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论