一、Linux内核介绍linux内核图:linux系统架构:linux内核架构:arm有7种工作模式,x86也实现了4种不同的级别RING0-RING3,RING0级别**,这样linux用户代码运行在RING3下,内核运行在RING0下,使系统本身得到充分的保护。虚拟文件系统VFS:VFS(virtualfilesystem)隐藏了各种文件系统的具体细节,为文件操作提供了统一的接口II.Linux内核源代码linux内核下载www.kernel.org目录结构:linux内核解压后目录tararch:根据不同cpu架构划分的代码block:一些块设备驱动crypto:加密、压缩、CRC校验算法文档:内核文档驱动:devicedriverfs(virtualfilesystemvfs):filesysteminclude:kernel需要的头文件,(平台无关的头文件在include/linux)lib:库文件代码(平台相关)mm:实现内存管理,硬件架构-independent(硬件架构相关的在arch)net:网络协议codesamples:内核编程的一些例子scripts:配置内核安全的脚本:SElinux模块sound:音频设备驱动usr:cpio命令实现,用于创建rootfilesystem把系统和内核放在一起的命令)virt:kernel虚拟机linuxDOC编译生成:linuxsourcerootdirectory/Documentation/00-INDEX:目录indexlinux源码根目录/Documentation/HOWTO:linux内核帮助文档生成指南:在linux源码根目录(Documentation)执行makehtmldocsubuntu16,需要执行sudoapt-getinstallxmlto安装生成doc文档的插件在后期开发中,arch和drivers中的代码经常会发生变化。3.Linux内核配置及编译清理文件(linux源码根目录下):makeclean:只清理所有生成的文件makemrproper:清理所有生成的文件和config配置文件makedistclean:清理所有生成的文件和config配置文件,编辑和补丁文件配置(收集cpu型号,网卡等硬件信息...):makeconfig:基于文本模式的交互式配置makemenuconfig:基于文本模式的菜单模式(推荐)makeoldconfig:使用现有的.config,但是会询问新的配置项makexconfig:Graphicalconfiguration(需要安装图形系统)配置方法:1)使用makemenuconfig操作方法:1>按y:编译>连接>镜像文件2>按m:compile3>按n:donothing4>按"Space":y,n交替配置并保存,linux源码根目录下会生成一个.config文件注意:apt-getinstalllibncurses5必须是在ubuntu11-dev上执行安装支持包2)使用已有的配置文件模板(.config)1>linux源代码根目录/arch//configs/<某个特定的CPU文件>,复制对应的文件inside并改名为.config到linux源码根目录2>使用当前运行的现有文件(使用ls/boot/-a查看)复制/boot/config-2.6.18-53.e15并重命名为.config到linux源码根目录下执行以上操作,然后在复制的.config文件上使用makemenuconfig修改文件。编译内核:1)makezImage2)makebzImage区别:在X86平台上,zimage只能用于获取小于512k的内核详细编译信息:makezimageV=1ormakebzimageV=1编译内核在目录:arch//boot/注意:编译内核前,将.config配置文件cp到根目录,必须进入makemenuconfig并保存退出(否则无法运行)编译安装模块:1)编译内核模块:makemodules2)安装内核模块:makemodules_installINSTALL_MOD_PATH=/lib/modules更换本机内核:将编译好的内核模块从内核源码目录复制到/lib/modulesmakeinitramdisk():输入并执行命令mkinitrdinitrd-2.6。39(any)2.6.39(查询/lib/modules下目录即可)注:mkinitrd命令在redhat中,ubuntu命令为:mkinitramfs-k/lib/modules/module安装位置-oinitrd-2.6.39(任意)2.6.39(查询/lib/modules下目录可得)如果ubuntu中没有mkinitramfs命令,可以使用apt-getinstallinitrd-tools安装内核模块:1)手动1>cplinux根目录/arch/x86/boot/bzImage/boot/mylinux-2.6.392>cplinux根目录/initrd-2.6.39/boot/initrd-2.6.39***修改/etc/grub.conf或/etc/lilo.conf文件2)自动1>makeinstall:该命令会自动完成以上操作(查看当前内核版本:uname-r)--------------------------------------------------------------------------四。Linux内核模块开发说明:linux内核组件非常多,内核ximage并不包含某个组件,而是在需要使用该组件(也可以卸载)时动态添加到运行内核中,这种机制是称为“内核模块”机制内核模块通常使用makefile文件编译模块。模块安装和卸载:1)加载:insmodhello.ko2)卸载:rmmodhello3)查看:lsmod4)加载(自动查找模块依赖):modprobehellomodprobe会根据文件/lib/modules/version/modules.dep检查要加载的模块,看是否还依赖于其他模块,如果有,会先找到这些模块,加载到内核实例分析中:1)moduleDep/1(amodule'sCompile)1#include2#include34//模块入口函数5//__init:表示代码段中的子段,里面的内容只运行一次,回收内存.6staticint__inithello_init(void)7{8printk(KERN_EMERG"helloworld!\n");9return0;10}11//模块卸载函数12//__exit:13staticvoid__exithello_exit(void)14{15printk(KERN_EMERG"helloexit!\n");16}17//内核符号导出函数18intadd_integar(inta,intb)19{20returna+b;21}22intsub_integar(inta,intb)23{24returna-b;25}2627module_init(hello_init);28module_exit(hello_exit);29//Functionexport30EXPORT_SYMBOL(add_integar);31EXPORT_SYMBOL(sub_integar);makefile:#第一次执行KERNELRELEASE为空,所以执行ifneq($(KERNELRELEASE),)inelseifneq($(KERNELRELEASE),)obj-m:=hello.o#elseblockelseKDIR:=/lib/modules/2.6.18-53.el5/buildall:#KDIR取决于内核模块源代码路径(内核编译安装路径)#PWD表示内核代码所在位置(当前目录))#modules编译模块make-C$(KDIR)M=$(PWD)modulesclean:rm-f*.ko*.o*.mod.o*.mod.c*.symvers*.orderendif2)moduleDep/2(编译两个模块)#include#include//模块可选信息MODULE_LICENSE("GPL");//许可证声明MODULE_AUTHOR("liyuan");//作者声明MODULE_DESCRIPTION("Thismoduleisaparamexample.");//模块说明MODULE_VERSION("V1.0");//模块别名MODULE_ALIAS("asimplemodule");//模块别名//模块参数staticchar*name="liyuanarg";staticintage=30;//S_IRUGO为参数权限,也可以使用numbersmodule_param(age,int,S_IRUGO);module_param(name,charp,S_IRUGO);//使用外部文件函数externintadd(inta,intb);//声明外部内核符号函数externintadd_integar(inta,intb);externintsub_integar(inta,intb);staticint__initmains_init(void){//多文件编译printk(KERN_EMERG"paramhi");intvle=add(1,2);printk(KERN_EMERG"addvalue:%d\n",vle);//模块参数printk(KERN_EMERG"name:%s\n",name);printk(KERN_EMERG"age:%d\n",age);//使用其他模块的函数(内核符号导出)intadds=add_integar(3,1);intsubs=sub_integar(3,1);printk(KERN_EMERG"add_integar:%d\n",adds);printk(KERN_EMERG"sub_integar:%d\n",subs);return0;}staticvoid__exitmains_exit(void){printk("paramexit!");}module_init(mains_init);52module_exit(mains_exit);add.cintadd(inta,intb){returna+b;}makefileifneq($(KERNELRELEASE),)#两个或多个内核源文件生成单独的内核模块名ma#kernelmaobj-m:=ma.o#下面的ma-objs前面一定要和上面一样mama-objs:=mains.oadd.oelseKDIR:=/lib/modules/2.6.18-53.el5/buildall:make-C$(KDIR)M=$(PWD)modulesclean:rm-f*.ko*.o*.mod.o*.mod.c*.symvers*.orderendif运行模块,参数:insmodhello.koname=yuanage=12kernelsymbolexport(/proc/kallsyms记录了内核中所有导出符号的名称和地址):一个内核模块的运行依赖于另一个内核模块的功能实现,必须先运行第一个内核模块,这样内核符号需要导出注意:错误信息:disagreesaboutversionofsymbolstruct_moduleinsmod:errorinserting...开发内核模块时会出现,内核模块不匹配。是因为你当前运行的linux内核与编译连接所依赖的内核版本不匹配。解决方法:使用modprobe--force-modversion强制插入。您可以使用uname-r查看当前运行的内核版本。printk内核打印:在中,printk有8个优先级,优先级降低的是:KERN_EMERG0用于紧急消息,通常是那些崩溃的KERN_ALERT1用于需要立即采取行动的消息KERN_CRIT2临界条件KERN_ERR3错误情况KERN_WARNING(printk默认级别)4有问题的警告KERN_NOTICE5正常情况,但仍值得注意KERN_INFO6信息消息KERN_DEBUG7作为调试消息使用,无论是什么级别,都会打印在/var/log/messages(可以删除messages后,运行内核测试内核打印情况)console打印(优先配置/proc/sys/kernel/printk)6417console_loglevelDefault_message_loglevelminimum_console_levelDefault_console_loglevelvm+redhat安装2.6.39时内核错误,启动报告找不到文件系统'/dev/root'解决方法a。通过makemenuconfigOptionGeneralsetup-->[*]enabledeprecatedsysfsfeaturestosupportolduserspacetools选择下面对应的成功后下面的就是*b。修改.config文件修改.config文件中的CONFIG_SYSFS_DEPRECATED_V2,将注释掉的CONFIG_SYSFS_DEPRECATED_V2改为CONFIG_SYSFS_DEPRECATED_V2=y