核心FAQ 2 (2001.05.26~2001.06.06) (轉)

worldblog發表於2007-12-07
核心FAQ 2 (2001.05.26~2001.06.06) (轉)[@more@]

核心FAQ(2001.05.26~2001.06.06)

">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都通不過:
我是7.0核心是2.2.16.
我的如下
#include 
#include 
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include 
#endif
int init_module()
{
printk("hello,world
");
return 0;
}
void cleanup_module()
{
printk("short is the life of a kernel module
");
}
Makefile為
CC=gcc
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX

hello.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-

 我用原始碼src中的modversions.h代替,然後又把原始碼中的models目錄複製過來結果雖然編譯透過,但是一執行就提示
hello.o:kernel -module version mismatch
hello.o was compiled for kernel version 2.4.0-0.26
while this kernel is version 2.2.16-22
望高手指點,不要跟我說升級核心,因為我要做的東西必須要在2.2.16下執行
如果我只是包含#include 
#include 
兩個標頭檔案,然後用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/include
mv linux linux.bak
mv asm asm.bak
ln -s /usr/src/linux/include/linux linux
ln -s /usr/src/linux/include/asm asm

Then Try...
Good Luck!

這樣行不行? 只包喊兩個標頭檔案,遍譯時加上 -I/usr/include/linux/version.h

我把中includ拷入includ中就可以了!

其實原因很簡單
redhat在釋出時搞錯啦,
指的是2.2.16
版本

所以,你可疑
如下操作
cd /usr/include
rm -rf linux asm
cp -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 my.c
時出錯說
warning:implicit declaration of function get _fs
imcompatale types in assignment
warning:implicit declaration of function get _fs
我查了一下 htons 他用 __bs16()
但是這個函式好像也是在應用級執行。 我查不到__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)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-989566/,如需轉載,請註明出處,否則將追究法律責任。

相關文章