收藏 分享(赏)

linux第7章 内核编程.pptx

上传人:gnk289057 文档编号:8291434 上传时间:2019-06-18 格式:PPTX 页数:50 大小:492.53KB
下载 相关 举报
linux第7章 内核编程.pptx_第1页
第1页 / 共50页
linux第7章 内核编程.pptx_第2页
第2页 / 共50页
linux第7章 内核编程.pptx_第3页
第3页 / 共50页
linux第7章 内核编程.pptx_第4页
第4页 / 共50页
linux第7章 内核编程.pptx_第5页
第5页 / 共50页
点击查看更多>>
资源描述

1、第7章 内核编程,本章内容,Linux内核体系结构 内核引导与设置 内核构建 系统调用,1、Linux内核体系结构,2、内核引导与设置,加电 BIOS/OF 引导装入 初始化内核 /sbin/init或系统初始化 系统运行 切断 断电,BIOS/OF,加电后处理器首先访问通常位于只读内存(一般是Flash ROM或仅仅是Flash)中的某一地址。 BIOS(基本输入输出)是x86系统加电后最先运行的代码。引导系统并与硬件相关的系统初始化代码,功能见下页。 Open Firmware是PPC(PowerPC)系统加电后最先运行的代码。,BIOS功能,自检及初始化程序; 自检,对CPU,640K基

2、本内存,1M以上的扩展内存,ROM,主板,CMOS存储器,串并口,显示卡,软硬盘子系统及键盘进行测试等。 初始化,包括创建中断向量、设置寄存器等。 引导程序 ,引导DOS或Linux等操作系统。 硬件中断处理;系统在加电引导机器时,要读取CMOS信息,用来初始化机器各个部件的状态。它靠系统电源和后备电池来供电,系统掉电后其信息不会丢失。 程序服务请求;程序服务处理程序主要是为应用程序和操作系统服务,这些服务主要与输入输出设备有关,例如读磁盘、文件输出到打印机等,引导装入程序(Boot Loaders),格式化磁盘时,会创建主引导记录(MBR),该记录存储在引导设备的第一个扇区(0扇区、0磁道、

3、0磁头)。包含: 一个小程序 一张四入口点的分区表 结束标识符(0XAA55),用来做MBR的有效性检测。 GRUB(Grand Unified Bootloader),基于x86的引导装入程序,用来加载Linux。 LILO(Linux Loader)x86中Linux的加载程序。 Yaboot是基于PowerPC及其OF的引导装入程序。,GRUB运行步骤,第一阶段 初始化; 检测正在装载的驱动器; 加载第二阶段的第一个扇区; 跳转到第二阶段。 第二阶段 加载第二阶段的剩余部分; 跳转到已加载的代码,LILO运行步骤,第一阶段 开始执行并显示“L.”; 检测磁盘集合信息并显示“I.”; 加载

4、第二阶段的代码。 第二阶段 开始执行并显示“L.”; 确定引导数据和操作系统的位置,并显示“O.”; 确定启动哪个操作系统,并跳转到该操作系统。,GRUB与LILO,LILO将配置信息存储在主引导记录中。若有任何改动,必须运行/sbin/lilo来更新主引导记录。 LILO不能读取不同的文件系统。 LILO没有交互式的命令接口。 LILO 不支持网络引导,而 GRUB 支持。 LILO 将关于可以引导的操作系统位置的信息物理上存储在 MBR 中。如果修改了 LILO 配置文件,必须将 LILO 第一阶段引导加载程序重写到 MBR。相对于 GRUB,这是一个更为危险的选择,因为错误配置的 MBR

5、 可能会让系统无法引导。使用 GRUB,如果配置文件配置错误,则只是默认转到 GRUB 命令行界面。,体系结构相关的内存初始化,X86和PowerPC在硬件方面都具有支持实寻址和虚寻址的内存管理特征。 Linux的内存管理依赖于底层的硬件结构。 现在PPC和x86的代码都集中在init/main.c的start_kernel()中,位于与体系结构无关的代码段中,调用特定体系结构的例程来完成内存初始化。,开始:start_kernel(),Init/main.c中start-kernel(),执行进程0(即超级用户线程root thread),进程0又产生进程1(即init进程),然后进程0就变

6、成CPU的空闲进程。 Linux内核只提供了轻量进程的支持,限制了更高效的线程模型的实现。目前最流行的线程机制LinuxThreads所采用的就是线程-进程“一对一”模型,调度交给核心,而在用户级实现一个包括信号处理在内的线程管理机制。,3、内核构建,Linux集成套件包括多种内核,能够处理各种机器。通过编译内核,选择符合硬件类型的驱动等,可以调整Linux系统,使其更合理地安装到计算机中。 重新编译内核以便实现一些新功能,如将Linux系统设置为一个临时路由器。 使得全世界内核设计者提供的各种为改进性能而设计的内核得到充分利用。,构建Linux内核,Linux官方源代码发布网址:www.ke

7、rnel.org,gzip压缩的.tar.gz包,bzip2压缩的.tar.bz2。这些压缩包的源代码适用于任何体系结构。Linux源代码分为: 与系统结构相关的部分 与系统结构无关的部分 文档和工具,与体系结构相关的源代码,(usr/src/linux-2.6/)arch/目录包含了所有与系统结构相关的代码,每个子目录对应一种支持的体系结构。如: Arch/i386 Arch/ppc,与体系结构无关的源代码,Crypto:保存加密的API及各种加密解密算法; Drivers:设备驱动程序代码; Fs:VFS及Linux支持的所有文件系统代码; Include:头文件; Init:引导程序代码

8、以及初始化代码; Ipc:支持进程间通信的代码; Kernel:内核空间特有代码; Lib:函数库的代码; Mm:用于内存管理的代码; Net:支持各种网络协议的代码; Sound:支持音频系统的代码。,其他文件,COPYING:Linux的GPL许可证; CREDITS:列出了对Linux作出贡献的人名; MAINTAINERS:当提交内核改动时设计的维护人员及说明; README:发布说明; REPORTING-BUGS:描述报告“bug”的过程; Documentation/:包含了Linux内核及其源代码的有关文档,当内核有所更新时,这里含有丰富的改动信息; Scripts/:编译内核

9、时可以使用的功能及脚本。,Linux内核的Makefiles文件,源代码树的每个子目录下都有一个makefile文件。 在源代码树的根目录下执行make,则调用顶层makefile文件,它定义了随后要输出到其他makefile的变量,以及向子目录中的每个makefile发出make调用。 Script/makefile.build中定义了makefile向下级子目录递归并编译的规则。,编译内核过程,预处理 配置内核 生成内核 安装内核 建立模块,预处理,Linux内核源文件缺省位置:/usr/src/linux 从Internet下载最新版本到你创建的主目录。 如Li 清除以前试图建立内核过程

10、遗留下的多余文件。 Make mrproper,配置内核,make config:手工逐项配置 make menuconfig:菜单选项配置 make xconfig: XWindow配置 修改配置文件/linux/.config 注意,make mrproper命令要删除这个文件,可以从/linux/arch/i386/defconfig拷贝复制一个。,生成内核,有三步: 1、make dep:生成相关性 例如:如果激活“Set Version Information For All Symbols On Modules”选项,那么它为所建立的模块确定其版本信息。 2、make clean:

11、清除一些目录中现有文件,将存储创建的新文件。 3、make bzImage:编译内核本身,花费时间长。对于新内核规模小,可以使用make zImage,如果不确定,最好还是使用bzImage。 建立/linux/arch/i386/boot/bzImage,安装内核,大多数集成套件使用LILO作为引导装入程序。 /etc/lilo.conf文件中的“image” su命令成为超级用户登录,把刚创建的bzImage拷贝到/boot中。 cp Li/linux/arch/i386/boot/bzImage /boot/vmLinuz 修改lilo.conf文件中“image”行。 告诉LILO更新

12、其配置信息:/sbin/lilo,建立模块,配置Linux内核时,可将许多选项配置为模块而不是放进内核。 每个模块可以分别装入和卸载。 /linux目录下 make modules:创建在配置过程中要求的模块,但是并不安装。 Make modules_install:将已经完成的模块拷贝到对应该内核版本的/lib/modules/子目录中。,管理多内核,不同的情况使用不同的内核 如笔记本电脑在公司和在家时因为网络接口或打印机等的不同而使用不同的内核 lilo.conf文件delay=15 #15-second delayimage=/boot/vnlinuxlabel=Linuximage=/

13、home/Li/bzImageLabel=TestKernel 最后,执行/sbin/liloAdded Linux * (表示Linux标记为缺省内核)Added TestKernel(表示添加新内核),4、系统调用,每个系统调用都是通过一个单一的入口点多路传入内核。eax 寄存器用来标识应当调用的某个系统调用,这在 C 库中做了指定(来自用户空间应用程序的每个调用)。 当加载了系统的 C 库调用索引和参数时,就会调用一个软件中断(0x80 中断),它将执行 system_call 函数(通过中断处理程序),这个函数会按照 eax 内容中的标识处理所有的系统调用。 在经过几个简单测试之后,使

14、用 system_call_table 和 eax 中包含的索引来执行真正的系统调用了。从系统调用中返回后,最终执行 syscall_exit,并调用 resume_userspace 返回用户空间。然后继续在 C 库中执行,它将返回到用户应用程序中。,使用中断方法的系统调用的简化流程,系统调用表和各种链接,系统调用接口的核心是系统调用多路分解表。这个表如左图所示,使用 eax 中提供的索引来确定要调用该表中的哪个系统调用(sys_call_table),系统调用多路分解 有些系统调用会由内核进一步进行多路分解。例如,BSD(Berkeley Software Distribution)soc

15、ket 调用(socket、bind、 connect 等)都与一个单独的系统调用索引(_NR_socketcall)关联在一起,不过在内核中会进行多路分解,通过另外一个参数进入适当的调用。请参看 ./linux/net/socket.c 中的 sys_socketcall 函数。,对用户空间进行读写,Linux 内核提供了几个函数,可以用来将系统调用参数移动到用户空间中,或从中移出。 方法包括一些基本类型的简单函数(例如 get_user 或 put_user)。 要移动一块数据(如结构或数组),可以使用另外一组函数: copy_from_user 和 copy_to_user。 可以使用专

16、门的调用移动以 null 结尾的字符串: strncpy_from_user 和 strlen_from_user。 通过调用 access_ok 来测试用户空间指针是否有效。这些函数都是在 linux/include/asm/uaccess.h 中定义的。,对用户空间进行读写(续),要在内核和用户空间移动一些简单类型(例如 int 或 long 类型),可以使用 get_user 和 put_user 轻松地实现。这两个宏都包含一个值以及一个指向变量的指针。get_user 函数将用户空间地址(ptr)指定的值移动到所指定的内核变量(var)中。 put_user 函数则将内核变量(var)

17、指定的值移动到用户空间地址(ptr)。 如果成功,这两个函数都返回 0。 在第二个系统调用中采用了put_user函数,向一块用户内存写数据。,int get_user( var, ptr ); int put_user( var, ptr );,内核中进行输出(printk),当函数在内核中运行时,只能使用内核空间的资源,不能使用用户态的资源,例如C库。所以在输入信息的时候使用printk。 printk是printf的一个简化版本,不能输出像浮点数之类的复杂数据类型。 与printf不同的是,printk按照相关的记录级或优先级将消息严格分类。 在第三个系统调用中采用了prink函数输出一

18、些信息,到/var/log/messages中。,Linux2.4内核添加系统,(1)添加新函数,在linux/kernel/sys.c中,添加三个系统调用函数到内核,命名和功能如下: myca1 根据输入(1,2,3)返回我们小组三个人的学号。 myca2 返回当前的时钟滴答数 jiffies,并将其写入一个用户指针。 myca3 输出一些信息。,myca1函数的定义,myca2、myca3函数的定义,函数说明,在linux/kernel/sys.c中,添加三个系统调用函数到内核,命名和功能如下: myca1 根据输入(1,2,3)返回我们小组三个人的学号。 myca2 返回当前的时钟滴答数

19、 jiffies,并将其写入一个用户指针。 myca3 输出一些信息。,(2)更新头文件,在linux/include/asm-i386/unistd.h中,添加三个系统调用函数号。如下图所示:,(3)针对这个新函数更新系统调用表,在linux/arch/i386/kernel/entry.S中的syscall_table中,添加三个系统调用表项。如下图所示:,(4)重新编译内核,编译内核前,如果用的是VMWare,务必记住进行一下快照,以免将来内核编译失败,可以返回修改代码后的状态。 将/etc/modules.conf的scsi_hostAdapter BusLogic一行注释掉,避免将来

20、的编译错误。 cd /usr/src/linux ,将Makefile中版本号里的custom去掉,防止内核版本冲突。,编译内核,make mrproper;/*清除上次编译内核的文件*/ make xconfig;必选的配置选项如下: SCSI device support-SCSI low-level drivers- BusLogic SCSI support Fusion MPT device support- Fusion MPT (base + ScsiHost) drivers和Fusion MPT misc device (ioctl) driver(这个要用模块形式加载) N

21、etwork devices support-Ethernet (10 or 100Mbit)- AMD PCnet32 PCI support block devices-RAM disk support 和Initial disk(initrd) support Filesystems-ext3 jourmalling systemsupport,编译内核(续),make dep; make bzImage; make modules; make modules_install; make insall; 这之后新内核已经安装在了系统中,我们只需重启一下系统。,运行测试程序(1),编辑源代

22、码如下:,运行测试程序结果,运行结果如下:,运行测试程序(2),编辑源代码如下:,运行测试程序结果,运行结果如下:,运行测试程序(3),编辑源代码如下:,运行测试程序结果,运行结果如下:,Linux2.6内核添加系统调用,内核空间: 1./usr/src/kernel/linux-2.6.18/include/linux/syscalls.h 末尾添加两行,声明系统调用asmlinkage long sys_cqtest1(void);asmlinkage long sys_cqtest2(void); 2./usr/src/kernel/linux-2.6.18/kernel/sys.c 添

23、加相应的系统调用函数 3./usr/src/kernel/linux-2.6.18/include/asmx86_64/unistd.h中添加系统调用号#define _NR_cqtest1 280 _SYSCALL(_NR_cqtest1, sys_cqtest1) #define _NR_cqtest2 281_SYSCALL(_NR_cqtest2, sys_cqtest2),Linux2.6内核添加系统调用,用户空间: 1./usr/include/asm/unistd 末尾加上#define _NR_cqtest1 280_SYSCALL(_NR_cqtest1, sys_cqtest1) #define _NR_cqtest2 281_SYSCALL(_NR_cqtest2, sys_cqtest2) 2./usr/include/bits/syscall.h 末尾加上 #define SYS_cqtest1 _NR_cqtest1#define SYS_cqtest2 _NR_cqtest2,本章小结,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报