2009年6月14日 星期日

systemtap

SystemTap是一種新穎的Linux內核診斷工具,提供了一種從運行中的Linux內核快速和安全地獲取信息的能力。 SystemTap 是内核开发人员和系统管理员的福音,因为这使得他们可以通过编写或者重用简单的脚本来收集内核的实时数据,而不需要再忍受修改源码、编译内核、重启系统的漫长煎熬。 SystemTap是內核開發人員和系統管理員的福音,因為這使得他們可以通過編寫或者重用簡單的腳本來收集內核的實時數據,而不需要再忍受修改源碼、編譯內核、重啟系統的漫長煎熬。 本文介绍了SystemTap 的安装、使用和基本原理,并用一些有趣的例子揭示了SystemTap 提供的强大能力。本文介紹了SystemTap的安裝、使用和基本原理,並用一些有趣的例子揭示了SystemTap提供的強大能力。

在SystemTap 出现之前,对于Linux 程序员或者系统管理员而言,调试内核往往是一场噩梦。在SystemTap出現之前,對於Linux程序員或者係統管理員而言,調試內核往往是一場噩夢。 例如,你怀疑传递给系统调用read 的参数fd 出了问题,想把它打印出来,你需要做的是:首先得到一份内核源码,找到sys_read() 的函数体中插入printk() 语句,接下来重新编译内核,然后用新的内核重新启动系统。例如,你懷疑傳遞給系統調用read的參數fd出了問題,想把它打印出來,你需要做的是:首先得到一份內核源碼,找到sys_read()的函數體中插入printk()語句,接下來重新編譯內核,然後用新的內核重新啟動系統。 谢天谢地,你总算看到了你想要看到的东西,不过你马上会发现遇到了一个新的麻烦:除非重新启动系统到原来的内核,printk() 会无休止地打印下去。謝天謝地,你總算看到了你想要看到的東西,不過你馬上會發現遇到了一個新的麻煩:除非重新啟動系統到原來的內核,printk()會無休止地打印下去。

SystemTap 的目的就是要把人们从这种泥潭中解救出来。 SystemTap的目的就是要把人們從這種泥潭中解救出來。 SystemTap 提供了一个简单的命令行接口和强大的脚本语言,同时预定义了丰富的脚本库。 SystemTap提供了一個簡單的命令行接口和強大的腳本語言,同時預定義了豐富的腳本庫。 基于内核中的kprobe,SystemTap允许你自由地从运行中的内核无害地收集调试信息和性能数据,来用于之后的分析和处理。基於內核中的kprobe,SystemTap允許你自由地從運行中的內核無害地收集調試信息和性能數據,來用於之後的分析和處理。 你可以随时开始或者停止这种收集过程,而无需漫长的修改代码、编译内核和重启系统的悲惨循环。你可以隨時開始或者停止這種收集過程,而無需漫長的修改代碼、編譯內核和重啟系統的悲慘循環。 SystemTap 使得上面的问题变得简单了,简单得只需要一条命令就可以做到: SystemTap使得上面的問題變得簡單了,簡單得只需要一條命令就可以做到

2009年6月12日 星期五

kgdb

GDB 支援 遠端除錯 已經有好一段時間了。 這個模式經由序列埠使用一個簡單的協定來進行除錯。不像上面提到的其 他除錯方式,你需要兩台電腦才能使用此種方式進行除錯。其中主機提供 除錯環境,包括所有的原始碼與一份包含所有的符號的核心副本,而目的 機器上則執行與著與主機的核心非常接近的版本(但是精簡過除錯資訊)。
你應該在核心設定檔中加入 DDB 選項,然後執行 config -g 指令,接著再編譯核心。這樣做會讓你 得到一個很肥大的核心,因為裡面包含了除錯的資訊。將這個核心拷貝到 目標機器上,執行 strip -x 來精簡除錯符號,然 後重開機,並在 boot 提示符號下輸入 -d 參數。從 主機的任何 sio 裝置連線到目標機器上─設有 "flags 080"─的 sio 裝 置。接著在除錯機器切換到核心編譯目錄,

執行 gdb :% gdb -k kernel
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (i386-unknown-freebsd),
Copyright 1996 Free Software Foundation, Inc...
(kgdb)

執行以下指令來初始化遠端除錯連線(在此假設使用第一個序列埠來 進行除錯):(kgdb) target

remote /dev/cuaa0
接著在目標機器上(在開始偵測裝置前就進入 DDB 模式那台機器)輸 入:Debugger("Boot flags requested debugger")
Stopped at Debugger+0x35: movb $0, edata+0x51bc
db> gdb

DDB 會回應Next trap will enter GDB remote protocol mode
每當你輸入 gdb 時,會在遠端 GDB 模式跟本地 DDB 模式之間切換。要立刻強迫切換到觸發動作,你只要打個 s 即可。你主機的 GDB 將會取得目標機器的核心的 控制權:Remote debugging using /dev/cuaa0
Debugger (msg=0xf01b0383 "Boot flags requested debugger")
at ../../i386/i386/db_interface.c:257
(kgdb)
你可像使用其他 GDB 連線一樣來使用這個連線,包括全權存取原始碼、 在一個 Emacs 視窗內以 gud 模式執行之(另一個 Emacs 視窗會自動顯示原 始程式碼)等等。

task in uc/OS II

想讓 uC/OS-II 管理使用者的 task,使用者必須要先建立 task。使用者可以透過傳遞 task 地址和其他參數到以下兩個函式之一來建立 task:OSTaskCreate() 或 OSTaskCreateExt()。
OSTaskCreate() 與 uC/OS 是向下相容的,OSTaskCreateExt() 是 OSTaskCreate() 的擴展版本,提供了一些附加的功能。用兩個函式中的任何一個都可以建立 task。task 可以在多工排程開始前建立,也可以在其他 task 的執行過程中被建立。在開始多工排程 (即呼叫 OSStart()) 前,使用者必須建立至少一個 task。task 不能由 ISR 來建立。

OSTaskCreate() 需要四個參數:task 是 task 程式碼的指標, pdata 是當 task 開始執行時傳遞給 task 的參數的指標,ptos 是分配給 task 的堆疊的頂端指標 (參看 task 堆疊),prio 是分配給 task 的優先權。

每個 task 都有自己的堆疊空間。堆疊必須宣告為 OS_STK 型別,並且由連續的記憶體空間組成。 使用者可以靜態分配堆疊空間 (在編譯的時候分配) 也可以動態地分配堆疊空間 (在運行的時候分配)。

uc/OSII 上的memory managment

在 ANSI C 中可以用 malloc() 和 free() 兩個函式動態地分配記憶體和釋放記憶體。但是,在嵌入式即時操作系統中,多次這樣做會把原來 很大的一塊連續記憶體區域,逐漸地分割成許多非常小而且彼此又不相鄰的記憶體區域,也就是記憶體破碎。由於這些碎片的大量存在,使得程式到後來連非常小的記憶體也分配不到。 Task Stack malloc() 函式來分配堆疊時,曾經討論過記憶體破碎的問題。另外,由於記憶體管理演算法的原因,malloc() 和 free() 函式執行時間是不確定的。

在 uC/OS-II 中,kernel 把連續的大塊記憶體按分區來管理。每個分區中包含有整數個大小相同的記憶體塊,為了便於記憶體的管理,在 uC/OS-II 中使用記憶體控制塊 (Memory Control Blocks, MCB) 的資料結構來跟蹤每一個記憶體分割區,系統中的每個記憶體分割區都有它自己的 MCB。

2009年6月11日 星期四

linux kernel 記憶體管理機制

Linux Kernel 的穩定,有一部份可以歸功於它優良的記憶體管理機制,而探討該機制,有助於瞭解記憶體是如何被 Kernel 所使用,老師上課時有提到Linux Kernel 的記憶體管理機制,所以我就把他詳細的寫在網誌上,其主要由兩大部份組成:
(1)Buddy System (就如同 大盤商)
(2)Slab Allocator (就如同中盤商)

Buddy System(buddy allocator)如一般的 Operating System Design,Linux Kernel 一樣是以 Page 為記憶體管理的單位,因此設計了一層針對 page(或稱分頁)的管理機制,該機制在 Linux Kernel 裡被稱為『Buddy System (buddy allocator,簡稱 buddy)』,buddy 是 Kernel 最底層的記憶體管理機制,日後所有的記憶體配置,最後都要經過 buddy 才能取得或釋放記憶體。

而且Buddy System是以 page 為單位來計算而不是使用以 1 byte 為單位來配置,所以不當使用 page會造成記憶體的浪費和 fragmentation。

Slab Allocator 用來確保記憶體分頁的配置效率和完整性,它實作了一個 cache 的架構對系統程式下的記憶體需求群組化,以達到管理的目的。一般的程式可以藉由向 Slab 註冊 cache,以得到記憶體的配置。

2009年6月9日 星期二

Reentrant code

LINUX一開始,第一章裡的一個重點: Reentrant function

non-self-modifying code. If code is reentrant, then it never changes during execution. 即程式執行時自己不能改自己的程式碼。但最標準的 reentrant code 是指,在一個多工環境下,一個 process A 在執行一個程式 x,執行到一半因為context switch 或一些原因而暫停,或 process B 來執行 x,B 做一做後A又回來繼續做,這時A仍然可以得到正確的結果。故 reentrant code 不但自己不能修改自己,而且也不能去修改 external 的變數。

Lazy context switch

昨天上課老師講到 Lazy context switch

目地: 因為大部份的process是不需要使用到FPU instruction, 而且讀取和儲存fpu state是會耗掉很多的cpu cycles 所以為了節省掉不必要進行的context switch,才會有此機制。


作法: FPU在硬體上會有個硬體的暫存器去判斷目前是那個FPU context. process在處理context switch時,若是此process需要儲存fp 指令。 則FPU context switch的動作會被往後延遲,直到有不同的process嘗詴想去使用FPU指令為止。 若是其它process嘗詴去使用FPU指令的話,則會把fpu_owner設為此process, 並把old fpu context儲存起來,而且會把new fpu context讀入fpu registers。

2009年6月6日 星期六

Kernel control path

最近老師上課有講到Kernel control path,

所以就來講一下Kernel control path吧!!

kernel control path 是指核心為了處理一個system call

或exception或interrupt所執行的一系列指令。通常來講,

CPU會照著KCP裡面的指令循序的執行,但如果有底下其

中一個事件發生,則會產生一個新的KCP插入目前正在執

行的KCP中。 在user mode發出一個system call,但該sys

tem call的條件無法立刻滿足。執行KCP中,CPU偵查到某

個exception。所執行的KCP允許中斷產生,且偵測到一個

中斷訊號。CPU啟用kernel preemption功能,且發生中斷

事件。

2009年6月2日 星期二

thread 與 process 比較

整體來說我覺得使用thread 會比process還要好,理由如下

(一)thread management cost較低
例如在thread creation 或context switching方面,其負擔均較process低,且因為 thread 彼此間有共享的code section ,data section 及其他的 os reaources

(二)從較能利用multiprocessors 的平行化程度來看,同一個process內的不同threads 可以分配到不同的cpu執行,增加平行化程度

(三)當process內的thread 於執行時blocking,則可以切換cpu給不同thread 執行,process不會因此而block,增加process throughput,縮短user response time