原创:http://blog.sina.com.cn/u/2312748742
一、概述:
1、linux体系架构:hardware platform(硬件) <<-- archrecture dependent kernel(汇编) <<-- kernel(内核) <<-- system call interface(系统调用接口) <<-- GNU c library(glibc 链接库) <<-- user application
2、linux由用户空间和和内核空间组成。
3、linux内核既不是应用程序也不是C应用程序库。
4、内核运行在管理模式svc,用户空间运行在用户模式usr
5、X86有4种不同的级别,ring0-ring3 内核代码在ring0 用户在ring3
6、内核空间和用户空间是程序执行的两种不同状态,他们使用不同的地址区间,linux系统只能通过系统调用和硬件中断才能完成从用户空间到内核空间的转移。
7、linux内核的构成,由arch,设备驱动dd,内存管理mm,网络堆栈,进程管理pm,虚拟文件系统vfs,系统调用接口sci组成。
8、内存管理主要作用控制多个进程安全的共享内存区域。
9、虚拟文件系统vfs隐藏各种文件系统的具体细节,为所有的类型文件提供统一的接口。应用程序-->> 虚拟文件系统 -->>ext2,fat,nfs,设备文件。
二、配置编译内核:
1、内核的源代码放在 usr/src/目录下
2、ipc文件夹是放进程间通信的
3、arch/arm 目录下有 boot、mm、kernel等文件夹,分别为内核引导,内存管理,系统调用。
4、清除以前的信息可以用 make distclean 或者 make mrproper
5、(1)配置内核可以用 make config (基于文本模式的交互式命令)
(2)make menuconfig (基于图形的交互式)
6、可以用之前的配置:make oldconfig 或者 make xconfig。这个需要有文件.config 。有一个可以引用。cp /boot/config-2.4.20.8 ./.config
7、make config 和make menuconfig 将生成一个.config(非c语音格式)
8、make uImage 将.config(非c语言格式)转化成 include/linux/autoconfig.h(c语言格式)文件的。
9、配置完后用dep命名建立模式的依赖文件。
三、模块的编译
1、工作由gcc-c 命令来完成。 gcc -c -I/usr/src/linux-2.4/include hello.c 输出 hello.o文件。
2、insmod,rmmod,lsmod,modprobe
modprobe 同insmod 加载一个模块到内核,不同在于它查看加载的模块,看它是否还依赖其他模块。如果是modprobe 找到这些模块,把它们先加载内核。
3、确定是否被卸载。系统为每个模块保留了一个使用计数(lsmod查看),用于记录正在使用该模块的用户数。只有当使用计算=0.模块才可以被卸载。
以下3个宏在内核中用来维护使用计数。
4、MOD_INC_USE_COUNT 模块计数加1.
5、MOD_DEC_USE_COUNT 模块计数减1
6、MOD_IN_USE模块计数非0时返回真。
7、模块加载函数:安装模块时被系统自动调用的函数,通过module_init宏来指定,在helloworld.模块中。
8、卸载模块,调用函数module_exit宏来指定。
9、许可证申明: MODULE_LICENSE被告知内核,该模块带有一个许可证,有效的许可证有“GPL”,"GPL v2","GPL and additional rights",“Dual BSD/GPL","Dual MPL/GPL"和"Proprietary"
10、模块参数:
通过MODULE_PRAM指定模块参数。模块参数用于在加载模块时传递参数给它
MODULE_PRAM(name,type)有两个参数,name时模块参数的名称。type是参数的类型。类型包括以下几种:b:比特型;h:短整型,i:整型;l:长整型;s:字符串型。
在传递字符串型的参数时,这个模块参数需要在模块中用char* 来声明。系统会自动为其分配内存空间。
如:
int a=3;
char *st;
MODULE_PARM(A,“i");
MODULE_PARM(st,"s");
四、注意:
1、使用gcc编译模块时使用 -c 编译选项。
2、在 gcc编译选项中定义宏 -DMODULE
-D __KERENL__
或者:#define MODULE
#define __KERNEL__
3、内核模块版本是由其所依赖的内核源代码版本所决定,位于内核源代码所处的顶层Makefile中:如:
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 20
EXTRAVERSION =-8
4、使用gcc编译内核模块时,需要通过增加编译选项
-I/xxx/include 来指定内核源代码头文件目录,并且还要保证内核源代码必须是配置过(make menuconfig),make dep过的。
xxx代表内核源代码的绝对路径,如:/usr/src/linux-2.4/
5、版本与正在运行的内核版本(uname -r 查询)不一致时用 insmod -f 强行插入
6、在包含任何头文件前,必须先定义预定义符号__KERNEL__,这个符号用于控制选择头文件的哪一个部分。
7、另一重要符号MODULE, 必须在包含<linux/module.h>前定义这个符号。它用于告诉头文件这是一个模块,如果编译进内核,必须去掉这个定义。
五、1、printk 是内核中出现最频繁的函数之一,通过将printk和printk对比,不同的:
printk在内核中使用,printf在应用程序中使用。
printk允许根据严重程度通过附加的优先级来对消息分类。
2、 <linux/kernel.h>定义8中记录级别,按照优先级递减顺序分别:
KERN_EMERG 用于紧急消息,常常是那些崩溃前的消息。
KERN_ALERT 需要立即行动
KERN_CRIT 严重情况,常常与严重的硬件或者软件失效有关。
KERN_ERR:用来报告错误情况。设备驱动常常使用 KERN_ERR来报告硬件故障
KERN_WARNING有问题的警告,这些情况自己不会引起系统的严重问题。
KERN_NOTICE:正常情况,但是仍然值得注意。
KERN_INFO:消息型信息。在这个级别,很多驱动在启动时打印它们发现的硬件信息。
KERN_DEBUG; 做调试信息
没有指定优先级的printk默认使用DEFAULT_MESSAGE_LOGLEVEL优先级,他是一个在kernel/printk.c中定义的整数4
六、内核安装:系统内核在: /lib/modules/2.4.20-8/kernel/
两种方法:
1、 1)make 2)make modules 模块编译 3)make modules_install 新模块安装 4)make install
2、1)cp arch/i386/boot/bzImage/boot/vmlinuz-$version
2)cp System.map /boot/System.map-$version
3)rm /boot/System.map
4)ln -s /boot/System.map-$version /boot/System.map
5)修改 /etc/grub.conf 或者 /etc/lilo.conf
七、补充:
1)rpm -qa | grep kernel 查找包
2)下载内核代码后可以用 md5sum /etc/passwd产生一个数字和字母列,看是否下载完全,和另一个文件对比下。
3)make menucofig是产生.config的。 make menucofig如果不能用看三个,一、gcc ,ncurses-devel ,display 是否够大。 查看是否有ncurses-devel 安装了。用rpm -qa |grep ncurses
make gconfig 要有gcc, gtk-devel,display 是否够大
make qt-config 要有gcc ,qt-devel,display 是否够大
4)make menuconfig里面的那个条目是由各个目录里的kconfig决定。
5)vi makefile前面几个是该版本号的。
6)make menuconfig 后用 make vmImage 编译出内核,非压缩的,建议用make bzImage编译出压缩内核
一、
编译步骤:1) make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- clean
2) make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- davinci_dm365_defconfig (配置板信息此时会产生.config文件)
3)make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- menuconfig (配置)
4)make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage (生产uImage,在arch/arm/boot/uImage)
二、
1)make menuconfig 这个产生.config
2)make bzImage (将*的编译进内核中,产生一个压缩的kernel)
3)make modules(将M的编译成模块,)
4)make modules_install(将刚才生产的模块就行归类,放在/lib/modules/2.6.9-??.EL/kernel/...)
5)make install (这步它自动完成三件事:
1、cp /arch/i386/boot/bzImage /boot/Vmlinux-2.6.9-100 (将bzImage 重命名并拷贝到boot目录下。)
2、mkinitrd /boot/initrd-2.6.9-100.img 2.6.9-100(版本号) <这步是做一个镜像的辅助文件,用于辅助kernel的,例如kernel里面是有ext2的驱动在kernel里面,但kernel是放在ext3的文件系统中,那么不就少了ext3的驱动了吗?因此就用这个辅助的镜像文件,当bzImage启动后,辅助镜像文件中的ext3驱动也在内存中了,因此kernel也就有了ext3驱动了>,,这个一般是跟启动有关的驱动会放这里,不相关的一般不放这里,跟根目录的文件系统有关系的,kernel可以加载这里的驱动找到根目录,一般像scsi.ko也会放这里面,如果内核启动不了出现kernel panic 就有可能是这里驱动不够,)
3、vi /boot/grub/grub.conf (自动修改这个配置文件。)
注:编译时可以启动2条线等。加快编译。如make -j2 modules