新聞中心
linux scull是一種Linux內(nèi)核的可擴展性和自適應性的操作系統(tǒng)。與傳統(tǒng)的Linux內(nèi)核相比,Scull內(nèi)核具有更高的可擴展性和自適應性,使其在各種應用場景下都具有很好的表現(xiàn)。

Scull內(nèi)核的可擴展性
Scull內(nèi)核的可擴展性主要表現(xiàn)在兩個方面,即可擴展的體系結(jié)構(gòu)和動態(tài)擴展能力。
可擴展的體系結(jié)構(gòu)
Scull內(nèi)核的體系結(jié)構(gòu)是可擴展的,這意味著它能夠擴展到不同類型的處理器架構(gòu)上。這種體系結(jié)構(gòu)的可擴展性非常重要,因為它能夠讓Scull內(nèi)核在不同平臺上工作,并且也能夠充分利用各種不同類型的處理器架構(gòu)。
動態(tài)擴展能力
Scull內(nèi)核還擁有強大的動態(tài)擴展能力,這使得它能夠通過添加新的模塊來擴展其功能,同時保證系統(tǒng)的穩(wěn)定性和安全性。Scull內(nèi)核的模塊系統(tǒng)使得Scull內(nèi)核更具可擴展性,同時能夠支持更多的設備和驅(qū)動程序。
Scull內(nèi)核的自適應性
Scull內(nèi)核的自適應性主要表現(xiàn)在兩個方面,即動態(tài)性和適應性。
動態(tài)性
Scull內(nèi)核具有動態(tài)性,可以適應不同的系統(tǒng)資源需求,并且能夠通過調(diào)整內(nèi)存管理和進程調(diào)度等策略來優(yōu)化系統(tǒng)性能。這種動態(tài)性非常重要,因為可以確保系統(tǒng)的高效和穩(wěn)定性,同時能夠減少資源浪費。
適應性
Scull內(nèi)核還具有適應性,能夠適應不同的應用場景和不同的使用者需求。例如,Scull內(nèi)核可以為不同的設備驅(qū)動程序提供不同的速率和優(yōu)先級,從而保證其具有更高的可靠性和性能。
結(jié)論
Linux Scull內(nèi)核具有強大的可擴展性和自適應性,這使得它能夠應對不同類型的操作系統(tǒng)需求,并且能夠在不斷變化的市場中保持其競爭優(yōu)勢。雖然Scull內(nèi)核的開發(fā)和部署需要更多的資源和投入,但是它能夠提供更好的性能和系統(tǒng)穩(wěn)定性,使得企業(yè)和用戶都能夠從中受益。
成都網(wǎng)站建設公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設、網(wǎng)站制作、網(wǎng)頁設計及定制高端網(wǎng)站建設服務!
如何調(diào)試驅(qū)動開發(fā)過程中的Oops
驅(qū)動程序開發(fā)的一個重大難點就是不易調(diào)試。本文目的就是介紹驅(qū)動開發(fā)中常用的幾種直接和間接的調(diào)試手段,它們是:
1、利用printk
2、查看OOP消息
3、利用strace
4、利用內(nèi)核內(nèi)置的hacking選項
5、利用ioctl方法
6、利用/proc 文件鬧笑系統(tǒng)
7、使用kgdb
前兩種如下:
一、利用printk
這是驅(qū)動開發(fā)中最樸實無華,同時也是最常用和有效的手段。scull驅(qū)動的main.c第338行如下,就是使用printk進行調(diào)試的例子,這樣的例子相信大家在閱讀驅(qū)動源碼時隨處可見。
338 //printk(KERN_ALERT “wakeup by signal in process %d\n”, current->pid);
printk的功能與我們經(jīng)常在應用程序中使用的printf是一樣的,不同之處在于printk可以在打印字符串前面加上內(nèi)核定義的宏,例如上面例子中的KERN_ALERT(注意:宏與字符串之間沒有逗號)。
#define KERN_EMERG “”
#define KERN_ALERT “”
#define KERN_CRIT “”
#define KERN_ERR “”
#define KERN_WARNING “”
#define KERN_NOTICE “”
#define KERN_INFO “”
#define KERN_DEBUG “”
#define DEFAULT_CONSOLE_LOGLEVEL 7
這個宏是用來定義需要打印的字符串的級別。值越小,級別越高。內(nèi)核中有個參數(shù)用來控制是否將printk打印的字符串輸出到控制臺(屏幕或者/sys/log/syslog日志文件)
# cat /proc/sys/kernel/printk
之一個6表示級別高于(小于)6的消息才會被輸出到控制臺,第二個4表示如果調(diào)用printk時沒有指定消息級別(宏)則消息的級銀孝別為4,第三個1表示接受的更高(最小)級別是1,第四個7表示系統(tǒng)啟動時之一個6原來的初值是7。
因此,如果你發(fā)現(xiàn)在控制臺上看不到你程序中某些printk的輸出,請使用echo 8 > /proc/sys/kernel/printk來解決。
在復雜驅(qū)動的開發(fā)過程中,為了調(diào)試會在源碼中加入成百上千的printk語句。而當調(diào)試完畢形成最終產(chǎn)品的時候必然會將這些printk語句刪除想想驅(qū)動的使用者而不是開發(fā)者吧。記?。杭核挥?,勿施于人),這個工作量是不小的。最要命的是,如果我們將調(diào)試用的printk語句刪除后,用戶又報告驅(qū)動有bug,所以我們又不得不手工將這些上千條的printk語句再重新加上。oh,my god,殺了我吧。所以,我們需要一種能方便地打開和關閉調(diào)試信息的手段。哪里能找到這種手段呢?哈哈,遠在天邊,近在眼前??纯磗cull驅(qū)動或者leds驅(qū)動的源代碼吧!
#define LEDS_DEBUG
#undef PDEBUG
#ifdef LEDS_DEBUG
#ifdef __KERNEL__
#define PDEBUG(fmt, args…) printk( KERN_EMERG “l(fā)eds: ” fmt, ## args)
#else
#define PDEBUG(fmt, args…) fprintf(stderr, fmt, ## args)
#endif
#else
#define PDEBUG(fmt, args…)
#endif
#undef PDEBUGG
#define PDEBUGG(fmt, args…)
這樣一來,在開發(fā)驅(qū)動的過程中,如果想打印調(diào)試消息,我們就可以用PDEBUG(“address of i_cdev is %p\n”, inode->i_cdev);,如果不想看到該調(diào)試消息,就只需要簡單的將PDEBUG改為PDEBUGG即可。而當我們調(diào)試完畢形成最終產(chǎn)品時,只需要簡單地將第1行注釋掉即可。
上邊那一段代碼中的__KERNEL__是內(nèi)核中定義的宏,當我們編譯內(nèi)核(包括模塊)時,它會被定義。當然如果你不明白代碼中的…和##是什么意思的話,就請認真查閱一下gcc關于預處理部分的資料吧!如果你實在太懶不愿意去查閱的話,那就充當VC工程師把上面的代碼copy到你的代碼中去吧。
二、查看OOP消息
OOP意為驚訝。當鋒彎稿你的驅(qū)動有問題,內(nèi)核不驚訝才怪:嘿!小子,你干嗎亂來!好吧,就讓我們來看看內(nèi)核是如何驚訝的。
根據(jù)faulty.c(單擊下載)編譯出faulty.ko,并 inod faulty.ko。執(zhí)行echo yang >/dev/faulty,結(jié)果內(nèi)核就驚訝了。內(nèi)核為什么會驚訝呢?因為faulty驅(qū)動的write函數(shù)執(zhí)行了*(int *)0 = 0,向內(nèi)存0地址寫入,這是內(nèi)核絕對不會容許的。
52 ssize_t faulty_write (struct file *filp, const char __user *buf, size_t count,
loff_t *pos)
54 {
*(int *)0 = 0;
return 0;
58 }
1 Unable to handle kernel NULL pointer dereference at virtual address
2 pgd = c
3 *pgd=, *pte=, *ppte=
4 Internal error: Oops: 817 PREEMPT
5 Modules linked in: faulty scull
6 CPU: 0 Not tainted (2.6.22.6 #4)
7 PC is at faulty_write+0×10/0×18
8 LR is at vfs_write+0xc4/0×148
9 pc : lr : psr: a
10 sp : c3871f44 ip : c3871f54 fp : c3871f50
11 r10:c r9 : cr8 :
12 r7 :r6 : c3871f78 r5 :r4 : c38e5160
13 r3 : c3871f78 r2 :r1 :r0 :
14 Flags: NzCv IRQs on FIQs on Mode SVC_32 Segment user
15 Control: c000717f Table:DAC:
16 Process sh (pid: 745, stack limit = 0xc)
17 Stack: (0xc3871f44 to 0xc)
18 1f40:c3871f74 c3871f54 c0088eb8 bf00608cc38e5180 c38e5160
19 1f60: c3871fc3871fa4 c3871f78 c0088ffc c0088e000000
20 1f80:004 c002c0ec3871fa8
21 1fa0: c002bf40 c0088fc
22 1fc0:021765c
23 1fe0:beac 401adb
24 Backtrace:
25 (faulty_write+0×0/0×18 ) from (vfs_write+0xc4/0×148)
26 (vfs_write+0×0/0×148) from (sys_write+0x4c/0×74)
27 r7:r6:c3871f78 r5:c38e5160 r4:c38e5180
28 (sys_write+0×0/0×74) from (ret_fast_syscall+0×0/0x2c)
29 r8:c002c0e4 r7:r6:r5:r4:
30 Code: e1a0c00d e92dd800 e24cb004 e3a00000 (e)
1行驚訝的原因,也就是報告出錯的原因;
2-4行是OOP信息序號;
5行是出錯時內(nèi)核已加載模塊;
6行是發(fā)生錯誤的CPU序號;
7-15行是發(fā)生錯誤的位置,以及當時CPU各個寄存器的值,這最有利于我們找出問題所在地;
16行是當前進程的名字及進程ID
17-23行是出錯時,棧內(nèi)的內(nèi)容
24-29行是?;厮菪畔ⅲ煽闯鲋钡匠鲥e時的函數(shù)遞進調(diào)用關系(確保CONFIG_FRAME_POINTER被定義)
30行是出錯指令及其附近指令的機器碼,出錯指令本身在小括號中
反匯編faulty.ko( arm-linux-objdump -D faulty.ko > faulty.dis ;cat faulty.dis)可以看到如下的語句如下:
c :
7c: e1a0c00dmov ip, sp
80: e92ddstmdb sp!, {fp, ip, lr, pc}
84: e24cbsub fp, ip, #; 0×4
88: e3amov r0, #0 ; 0×0
8c: e str r0,
90: e89daldmia sp, {fp, sp, pc}
定位出錯位置以及獲取相關信息的過程:
9 pc : lr : psr: a
25 (faulty_write+0×0/0×18 ) from (vfs_write+0xc4/0×148)
26 (vfs_write+0×0/0×148) from (sys_write+0x4c/0×74)
出錯代碼是faulty_write函數(shù)中的第5條指令((0xbf00608c-0xbf00607c)/4+1=5),該函數(shù)的首地址是0xbf00607c,該函數(shù)總共6條指令(0×18),該函數(shù)是被0xc0088eb8的前一條指令調(diào)用的(即:函數(shù)返回地址是0xc0088eb8。這一點可以從出錯時lr的值正好等于0xc0088eb8得到印證)。調(diào)用該函數(shù)的指令是vfs_write的第49條(0xc4/4=49)指令。
達到出錯處的函數(shù)調(diào)用流程是:write(用戶空間的系統(tǒng)調(diào)用)–>sys_write–>vfs_write–>faulty_write
OOP消息不僅讓我定位了出錯的地方,更讓我驚喜的是,它讓我知道了一些秘密:1、gcc中fp到底有何用處?2、為什么gcc編譯任何函數(shù)的時候,總是要把3條看上去傻傻的指令放在整個函數(shù)的最開始?3、內(nèi)核和gdb是如何知道函數(shù)調(diào)用棧順序,并使用函數(shù)的名字而不是地址? 4、我如何才能知道各個函數(shù)入棧的內(nèi)容?哈哈,我漸漸喜歡上了讓內(nèi)核驚訝,那就再看一次內(nèi)核驚訝吧。
執(zhí)行 cat /dev/faulty,內(nèi)核又再一次驚訝!
1 Unable to handle kernel NULL pointer dereference at virtual addres
2 pgd = c3a88000
3 *pgd=33a79031, *pte=, *ppte=
4 Internal error: Oops: 13 PREEMPT
5 Modules linked in: faulty
6 CPU: 0 Not tainted (2.6.22.6 #4)
7 PC is at vfs_read+0xe0/0×140
8 LR is at 0xffffffff
9 pc : lr : psr:
10 sp : c38d9f54 ip :c fp : ffffffff
11 r10:r9 : c38d8000 r8 :
12 r7 :r6 : ffffffff r5 : ffffffff r4 : ffffffff
13 r3 : ffffffff r2 :r1 : c38d9f38 r0 :
14 Flags: nzCv IRQs on FIQs on Mode SVC_32 Segment user
15 Control: c000717f Table: 33aDAC:
16 Process cat (pid: 767, stack limit = 0xc38d8258)
17 Stack: (0xc38d9f54 to 0xc38da000)
18 9f40:c3c105a0 c3c10580
19 9f60: c38d9fc38d9fa4 c38d9f78 c0088f88 c0088bb00000
20 9f80:2023 bef07cc002c0ec38d9fa8
21 9fa0: c002bf40 c0088f4cbef07cbef07c000000
22 9fc0:bef07c
23 9fe0:bef07c6cc 401adab
24 Backtrace: invalid frame pointer 0xffffffff
25 Code: ebffff86 ee1a07000 da(e594500c)
26 Segmentation fault
不過這次驚訝卻令人大為不解。OOP竟然說出錯的地方在vfs_read(要知道它可是大拿們千錘百煉的內(nèi)核代碼),這怎么可能?哈哈,萬能的內(nèi)核也不能追蹤函數(shù)調(diào)用棧了,這是為什么?其實問題出在faulty_read的43行,它導致入棧的r4、r5、r6、fp全部變?yōu)榱?xffffffff,ip、lr的值未變,這樣一來faulty_read函數(shù)能夠成功返回到它的調(diào)用者——vfs_read。但是可憐的vfs_read(忠實的APTCS規(guī)則遵守者)并不知道它的r4、r5、r6已經(jīng)被萬惡的faulty_read改變,這樣下去vfs_read命運就可想而知了——必死無疑!雖然內(nèi)核很有能力,但缺少了正確的fp的幫助,它也無法追蹤函數(shù)調(diào)用棧。
36 ssize_t faulty_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos)
38 {
int ret;
char stack_buf;
41
memset(stack_buf, 0xff, 20);
if (count > 4)
count = 4;
ret = copy_to_user(buf, stack_buf, count);
if (!ret)
return count;
return ret;
50 }
:
0: e1a0c00dmov ip, sp
4: e92ddstmdb sp!, {r4, r5, r6, fp, ip, lr, pc}
8: e24cbsub fp, ip, #; 0×4
c: e24ddsub sp, sp, #; 0×4,這里為stack_buf在棧上分配1個字的空間,局部變量ret使用寄存器存儲,因此就不在棧上分配空間了
10: e24b501csub r5, fp, #; 0x1c
14: e1amov r4, r1
18: e1amov r6, r2
1c: e3a010ffmov r1, #; 0xff
20: e3amov r2, #20 ; 0×14
24: e1amov r0, r5
28: ebfffffebl//這里在調(diào)用memset
78: e89daldmia sp, {r3, r4, r5, r6, fp, sp, pc}
這次OOP,深刻地認識到:
內(nèi)核能力超強,但它不是,也不可能是萬能的。所以即使你能力再強,也要和你的team member搞好關系,否則在關鍵時候你會倒霉的;
出錯的是faulty_read,vfs_read卻做了替罪羊。所以人不要被表面現(xiàn)象所迷惑,要深入看本質(zhì);
內(nèi)核本來超級健壯,可是你寫的驅(qū)動是內(nèi)核的組成部分,由于它出錯,結(jié)果整體。所以當你加入一個團隊的時候一定要告誡自己,雖然你的角色也許并不重要,但你的疏忽大意將足以令整個非常牛X的團隊。反過來說,當你是team leader的時候,在選團隊成員的時候一定要慎重、慎重、再慎重,即使他只是一個小角色。
關于linux scull的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。
香港服務器選創(chuàng)新互聯(lián),香港虛擬主機被稱為香港虛擬空間/香港網(wǎng)站空間,或者簡稱香港主機/香港空間。香港虛擬主機特點是免備案空間開通就用, 創(chuàng)新互聯(lián)香港主機精選cn2+bgp線路訪問快、穩(wěn)定!
本文名稱:LinuxScull:強大的內(nèi)核可擴展性和自適應性(linuxscull)
新聞來源:http://m.5511xx.com/article/djoohep.html


咨詢
建站咨詢
