




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、大连东软信息学院 嵌入式系统导论课程组嵌入式系统导论第3章 嵌入式开发环境的搭建3.1嵌入式开发环境概述13.2Flash程序烧写23.3BootLoader程序33.4内核的裁剪的编译43.5根文件系统的构建53.6驱动程序原理与开发63.1嵌入式开发环境概述1.建立开发环境2.配置开发主机,配置MINICOM3.建立引导装载程序bootloader4.下载他人曾经移植好的linux操作系统5.建立根文件系统6.建立运用程序的falsh分区7.开发运用程序8.烧写内核、根文件系统、运用程序9.发布产品第3章 嵌入式开发环境的搭建3.1嵌入式开发环境概述13.2Flash程序烧写23.3Boo
2、tLoader程序33.4内核的裁剪的编译43.5根文件系统的构建53.6驱动程序原理与开发63.2 Flash程序烧写烧写:即利用特殊工具向开发板中下载代码。实例:向ARM板裸机上烧写BootLoader、内核、根文件系统前提:存在目录。./img,其下有曾经预备好的各个部分软件的映像文件即用交叉编译器编译好的可执行文件,分别为:VIVI:针对S3C2410的BootLoader映像文件zImage:经裁剪的Linux内核映像文件root.cramfs:根文件系统映像文件sjf2410:完成烧写的程序3.2 Flash程序烧写详细烧写步骤1.安装JTAG驱动程序将整个giveoio目录JTA
3、G驱动所在目录复制到c:WINDOWS下,并将该目录下的giveio.sys文件复制到系统盘驱动目录下,如c:WINDOWSsystem32drivers在控制面板中添加该驱动程序2.设置超级终端按照波特率115300,数据位8,无奇偶校验,停顿位1,数据流控为无进展设置3.烧写引导程序运用sjf2410程序对vivi进展第一次烧写vivi启动后,运用bon part命令对flash进展分区运用load命令对vivi进展第二次烧写4.烧写内核运用load命令对kernel进展烧写5.烧写根文件系统运用load命令对rootfs进展烧写第3章 嵌入式开发环境的搭建3.1嵌入式开发环境概述13.2
4、Flash程序烧写23.3BootLoader程序33.4内核的裁剪的编译43.5根文件系统的构建53.6驱动程序原理与开发63.3.1 BootLoader程序原理对于PC系统,引导加载程序BIOS固件程序和位于磁盘MBR主引导记录中系统引导程序LILO和GRUB等一同组成。BIOS完成硬件检测和资源分配后,将硬盘MBR中的引导程序读到系统的内存中,然后将控制权交给引导程序。引导程序的主要义务就是将内核映像从硬盘上读到内存中,然后跳转到内核的入口点去运转,即开场启动操作系统。在嵌入式系统中,主要运用flash作为系统的存储煤介,很少用磁盘,因此整个系统的加载启动义务就完全由引导程序也称为Bo
5、otloader来完成。就是在操作系统内核运转之前运转的一段小程序。通过这段小程序,可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个适宜的形状,以便为最终调用操作系统内核预备好正确的环境。嵌入式系统中的bootloader概念Bootloader的功能1.硬件设备初始化CPU的主频、SDRAM、中断、串口等2.内核启动参数3.启动内核4.与主机进展交互,从串口、USB口或者网络口下载映象文件,并可以对FLASH等存储设备进展管理Bootloader特点1.依赖于硬件:每种不同的CPU体系构造都有不同的bootloader2.bootloader还依托详细的嵌入式板级设备
6、的配置Boot Loader 的安装媒介1. 系统加电或复位后,一切的处置器通常都从某个预先安排的地址上取指令。比如,ARM在复位时从地址0 x0取指。2. 嵌入式系统中通常都有某种类型的固态存储设备比如:ROM、EEPROM 或 FLASH 等被映射到这个预先安排的地址上。因此在系统加电后,处置器将首先执行 Boot Loader 程序 3. Bootloader是最先被系统执行的程序固态存储设备的典型空间分配构造Bootloader的烧写方式1.经过JTAG口2.经过以太网口3.经过串口4.其中前两种方式比后一种快得多Boot Loader的控制方式1. 主机和目的机之间普统统过串口建立衔
7、接,Boot Loader 软件在执行时通常会经过串口来进展通讯,比如:输出打印信息到串口,从串口读取用户控制字符2. 也可以经过JTAG等其他接口通讯Boot Loader 的操作方式大多数 Boot Loader 都包含两种不同的操作方式:1.启动加载方式2.下载方式从最终用户的角度看,Boot Loader 的作用就是用来加载操作系统,而并不存在所谓的启动加载方式与下载任务方式的区别启动加载方式 启动加载方式,称为“自主Autonomous方式 Boot Loader 从目的机上的某个固态存储设备上将操作系统加载到 RAM 中运转,整个过程并没有用户的介入。这种方式是 Boot Load
8、er 的正常任务方式,因此在嵌入式产品发布的时侯,Boot Loader 显然必需任务在这种方式下。Boot Loader 的操作方式下载方式 在下载方式下,目的机上的 Boot Loader 将经过串口衔接或网络衔接等通讯手段从主机下载文件,如:下载内核映像和根文件系统映像等从主机下载的文件通常首先被 Boot Loader 保管到目的机的 RAM 中,然后再被 Boot Loader 写到目的机上的FLASH 类固态存储设备中。这种方式通常在第一次安装内核与根文件系统时被运用;此外,以后的系统更新也会运用 Boot Loader 的这种任务方式。任务于这种方式下的 Boot Loader
9、通常都会向它的终端用户提供一个简单的命令行接口。Boot Loader 的操作方式BL的典型构造框架大多数 Boot Loader 都分为 stage1 和 stage2 两大部分。依赖于处置器体系构造和板级初始化的代码,通常都放在 stage1 中,用汇编言语实现而 stage2 那么通常用C言语来实现,这样可以实现更复杂的功能,而且代码会具有更好的可读性和可移植性。 Boot Loader 的 stage1 通常包括以下步骤(以执行的先后顺序):硬件设备初始化。为加载 Boot Loader 的 stage2 预备 RAM 空间。拷贝 Boot Loader 的 stage2 到 RAM
10、空间中。设置好堆栈跳转到 stage2 的 C 入口点。BL的典型构造框架Boot Loader 的 stage2 通常包括以下步骤(以执行的先后顺序):初始化本阶段要运用到的硬件设备。检测系统内存映射(memory map)。将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。为内核设置启动参数。调用内核。 stage2 的代码通常用 C 言语来实现,以便于实现更复杂的功能和获得更好的代码可读性和可移植性。与普通 C 言语运用程序不同的是,在编译和链接 boot loader 这样的程序时,我们不能运用 glibc 库中的任何支持函数。BL的典型构造框架3.3.2
11、几种流行的Linux BootLoader1.U-Boot2.BLOB3.RedBoot4.VIVI3.3.3 S3C2410平台上的VIVI分析 vivi是由韩国Mizi公司开发的一种Boot Loader,适宜于ARM9处置器,支持S3C2410UP-NETARM2410平台的引导程序启动方式和下载方式构造简单支持Linux内核引导,可以传送内核参数支持分区bon命令行vivi的Stage1文件head.S关WATCH DOG:上电后,WATCH DOG默许是开着的 制止一切中断初始化系统时钟初始化内存控制存放器一共13个检查能否从掉电方式唤醒,假设是,那么调用WakeupStart函数进
12、展处置点亮一切LED 初始化UART0将vivi一切代码(包括阶段1和阶段2)从nand flash复制到SDRAM中跳到bootloader的阶段2运转vivi的Stage1文件head.Svivi的Stage2文件main.c1.打印vivi的信息,包括版本号等2.调用假设干个初始化函数3.boot_or_vivi():判别能否有“r,回车或空格键按下,假设有,那么进入vivi shell;假设没有,那么执行boot命令,启动内核4.boot命令执行后,找到kernel分区,找它的偏移量和大小,执行boot_kernel()函数,拷贝内核映象5.设置linux启动参数,打印Now Boot
13、ing Linux6.调用call_linux()函数,启动内核第3章 嵌入式开发环境的搭建3.1嵌入式开发环境概述13.2Flash程序烧写23.3BootLoader程序33.4内核的裁剪的编译43.5根文件系统的构建53.6驱动程序原理与开发63.4.1内核的裁减ARM上的 linux内核移植预备任务1.下载linux2.6.0内核及其关于ARM平台的补丁,如:Patch2.6.0-rmkl.gz2.给linux2.6.0打补丁3.预备交叉编译环境4.修正内核目录下的makefile文件Linux 内核的编译菜单有好几个版本:1make config:进入命令行,可以一行一行的配置。2m
14、ake menuconfig:开发人员比较熟习的menuconfig 菜单。3make xconfig:在2.4.X 以及以前版本中xconfig 菜单是基于TCL/TK 的图形库的。 3.4.1内核的裁减2.4.X 版本xconfig 配置菜单:2.4.X 版本menuconfig 配置菜单 :2.6.X 版本 xconfig配置菜单 :内核模块处置方式要添加对某部分功能的支持,可以把相应部分编译到内核中,也可以把该部分编译成模块,动态调用。假设编译到内核中,在内核启动时就可以自动支持相应部分的功能,这样的优点是方便、速度快,机器一启动,他就可以运用这部分功能了;缺陷是会使内核变得庞大起来,
15、经常运用的部分直接编译到内核中,比如网卡。假设编译成模块,就会生成对应的.o文件,在运用的时候可以动态加载,优点是不会使内核过分庞大,缺陷是他得本人来调用这些模块。 在选择相应的配置时,有三种选择方式: Y 将该功能编译进内核 N 不将该功能编译进内核 M 将该功能编译成可以在需求时动态插入到内核中的模块 Linux 内核的编译菜单有好几个版本:1make config:进入命令行,可以一行一行的配置。2make menuconfig:开发人员比较熟习的menuconfig 菜单。3make xconfig:在2.4.X 以及以前版本中xconfig 菜单是基于TCL/TK 的图形库的。 3.
16、4.2内核的编译1make clean:清楚当前环境2make dep:设置变量依赖关系 3make zImage:编译内核,生成zImage编译命令编译完成的Linux内核在哪里?./vmlinux,elf格式未紧缩内核arch/arm/boot/compressed/vmlinux,紧缩以后的elf格式内核,此文件是从非紧缩的内核映像产生的。arch/arm/boot/zImage,可自解压的紧缩内核的映像文件第3章 嵌入式开发环境的搭建3.1嵌入式开发环境概述13.2Flash程序烧写23.3BootLoader程序33.4内核的裁剪的编译43.5根文件系统的构建53.6驱动程序原理与开
17、发63.5 根文件系统的构建Linux根文件系统目录构造运用busybox生成工具集构建根文件系统Linux根文件系统目录构造Linux根文件系统目录构造bin 必要的用户命令二进制文件*boot 引导加载程序运用的静态文件dev 设备文件及其他特殊文件etc 系统配置文件*home 用户主目录lib 必要的链接库,例如:C链接库、内核模块mnt 暂时挂载的文件系统的挂载点注:“* 目录在嵌入式Linux上为可选的。Linux根文件系统目录构造*opt 附加软件的安装目录proc 提供内核和进程信息的proc文件系统*root root用户主目录sbin 必要的系统管理员命令tmp 暂时文件目
18、录usr 大多数用户运用的运用程序和文件目录var 监控程序和工具程序存放的可变数据Linux根文件系统目录构造/etc目录系统配置文件fstab 挂载文件系统的配置文件passwd Password文件inetd.conf Inetd守护进程的配置文件groupGroup文件init.d/rcS 缺省的 sysinit 脚本Linux根文件系统目录构造运用Busybox生成工具集很小的运用程序提供完好的工具集的功能Init进程Shell文件系统、网络系统等等的工具集/运用Busybox生成工具集Busybox的配置和交叉编译1在/downloads/ 下载Busybox:busybox-1.
19、1.0.tar.bz2解压后,进入配置菜单:make menuconfig运用Busybox生成工具集Busybox的配置和交叉编译1运用Busybox生成工具集1. 假设在开发板上运用devfs,那么需求设置Gereral Configuration选项*Support for devfs2. 配置交叉编译器:Build Options* Do you want to build BusyBox with a Cross Compiler? (/usr/local/arm/3.4.1/bin/arm-linux-) Cross Compiler prefix 需求在接下来的输入栏中输入宿主机
20、中交叉编译器安装的途径,如“/opt/host/armv41/bin/armv41-unknown-linux-Busybox的配置和交叉编译2运用Busybox生成工具集3. 选择Busybox的编译方式:Build OptionsBuild BusyBox as a static binary (no shared libs) 缺省配置为运用链接库Busybox的配置和交叉编译2运用Busybox生成工具集配置其他工具集:Archival Utilities工具:tar、zip、unzip Coreutils常用命令:basename cat chgrp chmod date dd df
21、echo env ln ls mkdir mknod mv pwd rm rmdir sleep sort sync wc whoami等等Console UtilitiesDebian UtilitieEditors编辑命令:vi awk sed等Finding Utilities查找命令:find grep xargsBusybox的配置和交叉编译3配置其他工具集:Init Utilities * init * Support reading an inittab file? * Support running init from within an initrd?Busybox的配置和交
22、叉编译3运用Busybox生成工具集配置其他工具集:Login/Password Management UtilitiesLogin:getty login passwdMiscellaneous UtilitiesLinux Module UtilitiesNetworking Utilities网络命令集:hostname ifconfig inetd netstat ping routeProcess Utilities进程命令:free ps sysctl topShells shell工具:ash等 System Logging Utilities日志工具:syslogd klogd
23、 Linux System Utilities系统工具:dmesg fdisk getopt more mount umount运用Busybox生成工具集Busybox的配置和交叉编译3编译Busybox:1make dep 2make3make install运用Busybox生成工具集Busybox的配置和交叉编译4编译生成的目录构造 _install :/bin/linuxrc/sbin/usr/usr/bin/usr/sbin运用Busybox生成工具集Busybox的配置和交叉编译5构建根文件系统在_install下创建其它的目录Dev:存放设备文件Proc:Lib:库文件所在目录
24、Mnt:暂时挂载点Tmp:暂时目录Usr:用户目录Var:Etc:存放系统设置文件目录,在此目录下创建如下文件Inittab:指定运转级别文件Fstab:挂载文件系统的配置文件inetd.conf :Inetd守护进程配置文件profile :shell配置脚本Passwd:用户管理文件Hosts:静态域名解析文件利用cramfs工具创建根文件系统映象文件mkcramfs _install root.cramfsroot.cramfs即是最后根文件系统的可执行映像文件构建根文件系统第3章 嵌入式开发环境的搭建3.1嵌入式开发环境概述13.2Flash程序烧写23.3BootLoader程序33
25、.4内核的裁剪的编译43.5根文件系统的构建53.6驱动程序原理与开发6驱动开发简介设备驱动分类Linux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发驱动开发简介驱动程序是运用程序与硬件之间的一个中间软件层;驱动程序应该为运用程序展现硬件的一切功能,不应该强加其他的约束,对于硬件运用的权限和限制应该由运用程序层控制。 驱动程序有时会被多个进程同时运用,这时我们要思索如何处置并发的问题,就需求调用一些内核的函数运用互斥量和锁等机制。 概念:驱动开发简介Linux输
26、入/输出系统层次构造和功能:用户运用程序设备文件系统设备驱动程序物理设备控制器输入/输出恳求输入/输出呼应物理设备物理设备控制器驱动开发简介Linux驱动程序与外界的接口:设备驱动程序接口详细设备驱动程序与设备间接口系统初始化接口操作系统内核数据构造file_operations各设备初始化交互进展实现驱动开发简介设备驱动分类Linux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发设备驱动分类目前Linux 支持的设备驱动大体可分为三种:字符设备character
27、 device;块设备block deivce;网络接口设备network interface。设备类型:设备驱动分类一切可以像字节流一样访问的设备比如文件等在Linux 中都经过字符设备驱动程序来实现。在Linux 中它们也被映射为文件系统的一个节点,常在/dev目录下。运用程序对于字符设备的每一个I/O操作,都会直接传送给系统内核对应的驱动程序;字符设备驱动程序普通要包含open,close,read,write 等几个系统调用。Eg:如串口、触摸屏、并口、虚拟控制台、AD等。 字符设备:设备驱动分类Linux 的块设备通常是指可以包容文件系统的存储设备。与字符设备类似,块设备也是经过文件
28、系统来进展访问,它们之间的区别仅仅在于内核内部管理数据的方式不同。Linux 中的块设备包含整数个块,每个块包含2 的几次幂的字节。 运用程序对于块设备的操作,要经过系统的缓冲区管理,间接传送给驱动程序处置。Eg:诸如磁盘,内存,Flash等。块设备:设备驱动分类 网络接口设备比较复杂,通常它们指的是硬件设备,但有时也可是一个软件设备如回环接口loopback。由内核中网络子系统驱动,担任发送和接纳数据包,而且它并不需求了解每一项事务是如何映射到实践传送的数据包的。在Linux 中采用给网络接口设备分配一个独一名字的方法来访问该设备。Eg:eth0等。网络接口设备:驱动开发简介设备驱动分类Li
29、nux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发Linux下字符型设备管理设备文件的概念来一致对设备的访问接口,在引入设备文件系统devfs之前Linux将设备文件放在/dev目录下。设备的命名普通为设备文件名数字或字母表示的子类,例如/dev/hda1、/dev/hda2、/dev/ttyS0等。在LINUX2.4 /2.6内核中引入了设备文件系统devfs,一切的设备文件作为一个可以挂装的文件系统,这样就可以被文件系统进展一致管理,从而设备文件就可以挂装到
30、任何需求的地方。命名规那么也发生了变化,普通将主设备建立一个目录,再将详细的子设备文件建立在此目录下。Eg: 串口1 设备为:/dev/tts/0。 设备文件及设备文件系统概念:Linux下字符型设备管理传统方式中的设备管理中,除了设备类型外,内核还需求一对称作主次设备号的参数, 才干独一标识一个设备。主设备号一样的设备运用一样的驱动程序,次设备号用于区分详细设备的实例。 设备操作宏MAJOR()和MINOR()可分别用于获取主次设备号,宏MKDEV()用于将主设备号和次设备号合并为设备号,这些宏定义在include/linux/kdev_t.h 中。主设备号和对应的驱动程序系统会将其记录在/
31、proc/devices里主设备号和次设备号(1/2):Linux下字符型设备管理系统添加一个驱动程序就要赋予它一个主设备号。这一赋值过程在驱动程序的初始化过程中进展:对于字符设备:int register_chrdev(unsigned int major, const char*name,struct file_operations *fops);主设备号和次设备号(2/2):Linux下字符型设备管理/mnt/yaffsls /dev -l crw- 1 root root 5,1 Jan 1 00:00 console crw-r- 1 root root 1, 4 Jan 1 00:
32、00 port crw- 1 root root 108, 0 Jan 1 00:00 ppp crw-rw-rw- 1 root root 5, 0 Jan 1 00:00 tty crw- 1 root root 4, 64 Jan 1 00:11 ttyS0 crw- 1 root root 4, 65 Jan 1 00:00 ttyS1 crw-rw-rw- 1 root root 1, 5 Jan 1 00:00 zero 查看/dev目录下的设备的主次设备号:Linux下字符型设备管理为该模块建立一个设备节点。命令: mknod /dev/ts c 254 0 其中/dev/ts表
33、示我们的设备名是ts,“c 阐明它是字符设备,“254 是主设备号,“0 是次设备号。一旦经过mknod 创建了设备文件,它就不断保管下来,除非我们手工删除它。手工设备管理:Linux下字符型设备管理动态分配:初始化时动态分配设备号;在Documentation/devices.txt文件中可以找到曾经静态分配给大部分设备的列表由于许多数字曾经分配了,为新设备选择一个独一的号码是很困难的假设调用register_chrdev时的major为零,函数就会选择一个空闲号码并做为前往值前往动态管理(1/2):Linux下字符型设备管理动态分配的主设备号不能保证总是一样的,无法事先创建设备节点可以从/
34、proc/devices读取cat /proc/devices利用脚本动态创建设备文件节点动态管理(2/2):Linux下字符型设备管理在Linux 2.4的内核里引入了devfs来处理linux下设备文件管理的问题在驱动程序中经过devfs_register()函数创建设备文件系统的节点 其原型为: devfs_registerdevfs_handle_t dir, const char *name, unsigned int flags,unsigned int major, unsigned int minor, umode_t mode, void *ops, void *info)系
35、统启动的时候mount设备文件系统一切需求的设备节点都由内核自动管理。/dev目录下只需挂载的设备注:在linux-2.6.12之后的内核的处理方法:udev文件系统/pub/linux/utils/kernel/hotplug/udev.html运用设备文件系统-devfs :Linux下字符型设备管理udev 完全在用户态 (userspace) 任务,利用设备参与或移除时内核所发送的hotplug 事件 (event) 来任务。关于设备的详细信息是由内核输出 (export) 到位于 /sys 的 sysfs 文件系统的。一切的设备命名战略、权限控制和事件处置都是在用户态下完成的。与此相
36、反,devfs 是作为内核的一部分任务的。 运用设备文件系统- udev :驱动开发简介设备驱动分类Linux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发Linux驱动编译和加载方式一种是直接编译到内核,当内核启动之后,新的驱动程序随之运转;二是编译为模块,动态加载运转对模块操作需求运用module-utiles:insmod将编译的模块直接插入内核rmmod从内核中卸载模块lsmod显示已安装的模块gcc编译参数: -D_KERNEL_ -DMODULE I$
37、(KERNELDIR_INCLUDE)在调试的过程中普通运用模块动态加载的方式,它的调试效率较高。当驱动调试完成后,在发行的过程就集成进内核。但编译进内核是某些驱动运转的独一方法。例如:console驱动,flash驱动和对至少一种文件系统的支持等等。Eg:DA实验: insmod da.o ; CAN实验: insmod can.oLinux驱动编译和加载方式:驱动开发简介设备驱动分类Linux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发Linux内核模块构造
38、引见#include /一切模块都需求的头文件#include / init&exit相关宏static int _init hello_init (void)printk(Hello module initn);return 0;内核模块的根本框架1/2:Linux内核模块构造引见static void _exit hello_exit (void)printk(Hello module exitn);module_init(hello_init);module_exit(hello_exit); 内核模块的根本框架(2/2):Linux内核模块构造引见gcc -D_KERNEL_ -DMO
39、DULE -DLINUX -I /usr/src/linux2.4/include -c -o hello.o hello.c insmod ./hello.o rmmod hello 内核模块的编译和加载:驱动开发简介设备驱动分类Linux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发简单Linux字符型设备驱动程序驱动程序在Linux 内核中往往是以模块方式出现的。与运用程序的执行过程不同,模块通常只是预先向内核注册本人,当内核需求时呼应恳求。内核模块的编译和
40、加载:简单Linux字符型设备驱动程序设备驱动程序流程图:insmodrmmodinit_module()clean_module()模块内核设备功能设备注册设备卸载用户调用简单Linux字符型设备驱动程序重要的数据构造file_operations(1/3):阐明:设备驱动程序接口:file_operations 数据构造通常所说的设备驱动程序接口是指构造file_operations构造,它定义在include/linux/fs.h 中。file_operations 构造是整个Linux内核的重要数据构造简单Linux字符型设备驱动程序重要的数据构造file_operations(2/3
41、):struct file_operations struct module *owner; ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*open) (struct inode *, struct file *); int (*re
42、lease) (struct inode *, struct file *); / ; 简单Linux字符型设备驱动程序重要的数据构造file_operations(3/3):运用:“标志化 方法为该构造进展初始化 : static struct file_operations s3c44b0_fops = owner: THIS_MODULE, open: s3c44b0_ts_open, read: s3c44b0_ts_read, release: s3c44b0_ts_release, ; 简单Linux字符型设备驱动程序重要的数据构造file :阐明:file构造定义在头文件linu
43、x/fs.h 中。它代表一个翻开的文件,由内核在调用open 时创建。并传送给在该文件上进展操作的一切函数,直到最后的close 函数被调用。在文件的一切实例都封锁时,内核释放这个数据构造。注:与inode的区别,inode表示磁盘文件,而file表示一个翻开的文件简单Linux字符型设备驱动程序设备注册:驱动程序模块经过函数register_chrdev来完成向内核注册的。int register_chrdev (unsigned int major, const char *name, struct file_operations *fops);其中unsigned int major 为
44、主设备号,const char *name 为设备名, struct file_operations *fops 为文件操作构造指针。 简单Linux字符型设备驱动程序设备卸载:驱动程序模块经过函数unregister_chrdev来完成向内核卸载的。int unregister_chrdev (unsigned int major, const char *name);其中unsigned int major 为主设备号,const char *name 为设备名。简单Linux字符型设备驱动程序翻开设备:驱动程序模块经过函数open来完成翻开设备的。提供应驱动程序初始化设备的才干,为后续的
45、操作做预备此外普通会递增运用计数,防止文件封锁前模块被卸载通常情况下,open完成如下任务:递增运用计数检查特定设备错误假设设备是初次翻开,那么对其进展初始化识别次设备号,如有必要,那么修正f_op指针分配并填写filp-private_data中的数据简单Linux字符型设备驱动程序释放设备:驱动程序模块经过函数release来完成释放设备的。与open正好相反释放由open分配的filp-private_data中的数据在最后一次封锁操作时封锁设备运用计数减一简单Linux字符型设备驱动程序读写设备(1/3):read函数将数据从内核拷贝到运用程序空间,write函数那么将数据从运用程序空
46、间拷贝到内核。ssize_t read(struct file *filp,char _user *buff,size_t count,loff_t *offp);ssize_t write(struct file *filp,char _user *buff,size_t count,loff_t *offp);其中,filp是文件指针,count是恳求传输的数据长度。参数buff是指向用户空间的缓存区,这个缓存区或者保管要写入的数据,或者是一个存放新读入数据的空缓冲区,最后的offp是一个指向“long offset type长偏移量类型对象的指针,这个对象指明用户在文件中进展存取操作的位
47、置简单Linux字符型设备驱动程序读写设备(2/3):注:buff为用户空间的地址指针,内核代码不能直接援用其中的内容缘由:用户空间的指针能够是无效的,该地址能够根本就无法映射到内核空间用户空间的内存可以被换出,因此能够会出现页面失效的问题从平安角度思索处理方法:运用内核函数进展数据拷贝简单Linux字符型设备驱动程序处理函数:unsigned long copy_to_user(void *to, const void* from, unsigned long count);unsigned long copy_from_user(void *to, const void *from,uns
48、igned long count);其中:to表示数据目的缓冲区 from表示数据源缓冲区 count表示数据长度前往值:胜利,前往数据长度 失败,前往EFAULT这两个函数不仅要拷贝数据,还要检查指针有效性读写设备(3/3):简单Linux字符型设备驱动程序ioctl函数:int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);其中,inode和filp对应于运用程序传过来的文件描画符fd,cmd是用户空间传送给驱动程序的命令,arg为附加的命令参数读写以外的I/O操作:简单
49、Linux字符型设备驱动程序printk函数:int printk(const char *fmt,);其中,fmt为日志级别前往值:胜利,前往1,失败,前往1。如:printkKERN_DEBUG,Here I am:%s:%in,_FILE_,_LINE_;打印信息:简单Linux字符型设备驱动程序驱动程序的编译、加载及卸载:驱动程序的编译以demo.c为例Makefile的方式命令行的方式rootRedHatAS $ gcc -c-D_KERNEL_ -DMODULE-I /usr/src/linux-2.4/include demo.c -o demo.o加载驱动rootRedHatA
50、S $ insmod demo.o卸载驱动rootRedHatAS $ rmmod demo.o简单Linux字符型设备驱动程序驱动程序的编译、加载及卸载阐明:依赖关系问题当模块与内核链接时,insmod 会检查模块和当前内核版天性否匹配; 每个内核版本都需求特定版本的编译器的支持,高版本的编译器并不适宜低版本的内核;简单Linux字符型设备驱动程序驱动程序的测试:/test.c#include#include#includeint main()int fd;fd=open(/dev/demo, O_RDWR);if(fd 0)exit(fd);/your code hereread(fd,
51、buffer, size);write(fd, buffer, size);.close(fd);return 0;驱动开发简介设备驱动分类Linux下字符型设备管理Linux驱动编译和加载方式Linux内核模块构造引见简单Linux字符型设备驱动程序驱动程序与运用程序的区别字符型设备驱动demo分析3.6 驱动程序原理与开发驱动程序与运用程序的区别运用程序普通有一个main 函数,从头到尾执行一个义务;驱动程序却不同,它没有main 函数,经过运用宏module_init(初始化函数名),将初始化函数参与内核全局初始化函数列表中。经过宏module_exit(退出处置函数名)注册退出处置函数。 驱动程序与运用程序的区别 1/2:驱动程序与运用程序的区别运用程序可以和GLIBC 库衔接,因此可以包含规范的头文件,比如、等,;在驱动程序中是不能运用规范C 库的,因此不能调用一切的C 库函数, 只能调用内核的函数,eg:比如输出打印函数只能运用内核的print
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论