内核FAQ(2001.05.26~2001.06.06)
http://LinuxAid.com.cn axing 〖 返回〗〖转发〗 1、 mm/slab.c 文件的内容2、 怎样在内核中获得拦截文件的全路径3、 LKM编写初级问题4、 insmod可卸载内核问题5、 关于bootsect.S的一个问题1、mm/slab.c 文件是关于存储管理的某一方面,如果能简要分析一下内容的话,在下感激不尽!! Slab Allocator分配算法的实现基于对象缓存机制,其使用的的对象复用技术比传统的分配内存块方式优越。该算法基于这样一个事实:有一部分内核数据结构由于经常被使用,所以它们可以经常被复用。因此该算法为这些经常使用的内核数据结构分配内存,并将它们视为对象进行统一管理,对象被创建并使用完毕后,并不是立即把对象释放,而是暂时保留,当对相同的对象又有新的要求时就可以立即使用被保留的对象,这样就可以省去很多的内核内存分配和回收操作,减轻了内核的工作负担。 另外,Slab Allocator分配算法的可以控制被分配的内存的粒度,可以对特定的数据结构进行度身订造,大大减少了内存的浪费。该算法腥闶莩橄螅夯捍?kmem_cache_t),Slab(kmem_slab_t),对象(kmem_bufctl_s)。缓存集中管理Slab,Slab集中管理对象。每个捍胬锩嬗卸喔鯯lab,而每个Slab中的则含有多个相同类型的对象。Cache有两种类型:通用cache和专用cache。通用cache仅被slab分配器用于本身的特定目的,而专用cache则用于内核的剩下部分用途。通用cache由kmem_cache_init()和kmem_cache_sizes_init() 在内核初始化时建立。专用cache则由kmem_cache_create()函数创建。通用cache中,第一个cache名为cache_cache,里面的内容为专用cache的描述符。第二个cache名为cache_slabp,里面的内容是那些没有保存在slab中的slab描述符。还有13个cache,大小从2^5-----2^17字节,分别由cache_sizes[]中的13个元素指向。专用cache则是应具体应用要求而创建的,在系统初始化时就是要把通用cache以及一部分专用cache构建起来。每个新创建的cache的描述符都会被插入到通用cache cache_cache中。需要注意的是,一旦cache被创建后就不能被删除。2、怎样在内核中获得拦截文件的全路径 我在内核中对open系统调用进行拦截,拦截后得到的文件路径,当别人使用相对路径时为相对路径,只有别人在调用open时使用了全路径我才能在内核中拦截到打开文件的绝对路径。不知当别人用相对路径打开文件时,怎样才能在内核中得到所打开文件的绝对路径? 既然是相对路径,自然是对当前路径而言,当前进程的task_struct中有两个变量fs,files含有当前打开文件信息,具体内容看看两个数据结构吧。3、LKM编写初级问题 我现在在学内核模榈谋嘈?但是连一个最简单的HELLO WORLD都通不过:我是REDHAT7.0内核是2.2.16.我的程序如下#include <linux/module.h>#include <linux/kernel.h>#if CONFIG_MODVERSIONS==1#define MODVERSIONS#include <linux/modversions.h>#endifint init_module(){printk("hello,world");return 0;}void cleanup_module(){printk("short is the life of a kernel module");}Makefile为CC=gccMODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUXhello.o: hello.c /usr/include/linux/version.h$(CC) $(MODCFLAGS) -c hello.c然后编译提示头文件有错我发现我的modversions.h为以下内容#error Modules should never use kernel-headers system headers,#error but headers from an appropriate kernel-source 我用源码src中的modversions.h代替,然后又把源码中的models目录拷贝过来结果虽然编译通过,但是一运行就提示hello.o:kernel -module version mismatchhello.o was compiled for kernel version 2.4.0-0.26while this kernel is version 2.2.16-22望高手指点,不要跟我说升级内核,因为我要做的东西必须要在2.2.16下运行如果我只是包含#include <linux/module.h>#include <linux/kernel.h>两个头文件,然后用gcc -c -O3 hello.c编译又提示什么版本号出错!!I KNOW WHY!!Hmmm...You are programming in kernel and its version is 2.2.16,so you should do following: (I HAVE JUST SAID IT :< )cd /usr/includemv linux linux.bakmv asm asm.bakln -s /usr/src/linux/include/linux linuxln -s /usr/src/linux/include/asm asmThen Try...Good Luck!这样行不行? 只包喊两个头文件,遍译时加上 -I/usr/include/linux/version.h我把源代码中includ拷入includ中就可以了!其实原因很简单redhat在发布软件时搞错啦,指的是2.2.16版本所以,你可疑如下操作cd /usr/includerm -rf linux asmcp -a /usr/src/linux/include/linux .cp -a /usr/src/linux/include/asm .主要目的就是替换掉kernel.headers包4、insmod可卸载内核问题 我找到了一个包过滤防火墙源程序,编译通过,但insmod 时出错。报错说 unresolved symbol htons 但如果不用这个(htons)函数,我就不能把主机字节排序换成网络字节排序。我看ip_fw.c也用到了 ntohs 这个函数,为什么他能用我不能用?另外 mm_segment_t 是什么东西? get_fs() 、 set_fs()呢?这是一位高手交给我的解决之道,但可能我用的不对,依然出错。 模块编程属于内核编程,必须使用内核向外公开的函数(内核函数),htons时属于用户级,所以insmod时在内核公开符号表(用ksyms看)找不到,内核如何分别进程此时在内核级或用户级呢,主要时通过进程的task_struct中addr_limit,get_fs和set_fs,实际就是对她的操作.使用:mem_segment_t old_fs;old_fs=get_fs();//保存。。。。。。。。set_fs(get_ds());。。。。。。。set_fs(old_fs)恢复 我本来又一篇介绍这方面的文章,暂时找不到,等发现在帖出来,到时你可以参考一下。 建议:你可以追踪htons源码,寻找其中被内核开放的函数,直接使用,这是一种内核编程的方法。 您老人家似乎是在用gcc编译的时候未加 -O3选项,加上以后再试试。 我按照大侠指点的作了一下。我把mem_segment_t old_fs old_fs=get_fs() set_fs(get_fs())放在函数开始 set_fs(old_fs)放在函数最后。 还是有错。是不是 mm_segment_t ?改正后 gcc -Wall -02 -c myfirewall.c时出错说warning:implicit declaration of function get _fsimcompatale types in assignmentwarning:implicit declaration of function get _fs我查了一下 htons 他用 __bswap16()但是这个函数好像也是在应用级运行。 我查不到__bswap16的源代码。 5、关于bootsect.S的一个问题 本人在研究linux的启动代码时发现一个问题,百思不得其解,希望那位高人指点一下: 作为bootloader, bootsect.S被读进绝对地址:0x7c00后,立即进行自我搬迁,挪到0x90000处。我认为这次的搬迁是没有意义的,因为在bootsect.S执行过程中根本不会对0x7c00以及附近的内存区进行写操作,虽然在setup.S中有可能对内核进行重定位,将内核搬到0x1000处,但那时bootsect.S已经没有存在意义了,因为它已经把setup.S以及内核读进内存了,其任务也就完成了。所以将其覆盖也无所谓。因此bootsect.S的自我搬迁就显得毫无意义了。 我怀疑这可能是为了遵守某种协议或约定所致的,但又找不到相关的材料,那位高手对这方面有研究的话,能否指点一下? 你讲得对,不搬迁也是可以的。我以前改过一回,也能用。不过bootsect.S是小问题,只是在你使用软盘时才用这段代码,硬盘上的lilo是不会理会它的。也就是说,硬盘lilo时,直接跳过bootsect.S的所有代码进入setup.S。 仅供参考:如果你仅有一个linux系统,正如你所说得,但当你有多个系统时,如果你选择得启动系统不是linux,比如dos,在bootsect完成工作前要将dos引导扇区读入0x07c00,做完这一步,控制权要交还给bootsect,至于为什么要是0x07c00则是pc得向后兼容的要求。 责任编辑:axing(2001-06-06 16:57) |