前面12節(jié)的課程,主要針對 Linux 內(nèi)核中 GNU C 擴(kuò)展的一些常用 C 語言語法進(jìn)行了分析。GNU C 的這些擴(kuò)展語法,主要用來完善 C 語言標(biāo)準(zhǔn)和編譯優(yōu)化。而通過 C 標(biāo)準(zhǔn)的發(fā)展過程我們又發(fā)現(xiàn),對于一些編譯器擴(kuò)展的一些特性,或者其它編程語言(如:C++)中的好的特性和語法,C 標(biāo)準(zhǔn)也會適時地吸收進(jìn)來,作為新的 C 語言標(biāo)準(zhǔn)。
專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)內(nèi)黃免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了上千余家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
在 GNU C 的這些擴(kuò)展語法中,attribute和宏定義是兩大特色。在嵌入式底層系統(tǒng)中,尤其是 Linux 內(nèi)核和 U-boot 中,大量使用 GNU C 擴(kuò)展的 attribute屬性去輔助一些底層機(jī)制的實(shí)現(xiàn),或者實(shí)現(xiàn)一些編譯上的優(yōu)化。在宏定義方面,通過語句表達(dá)式、可變參數(shù)宏等特性,我們可以定義一個功能復(fù)雜、安全可靠的高質(zhì)量宏。
本教程所講的一些特性,都是在實(shí)際工作或閱讀 Linux 內(nèi)核驅(qū)動源碼時經(jīng)常遇見的一些特性,掌握了這些擴(kuò)展特性的使用,以后再遇到類似的“奇葩 C 語言”程序,就知道怎么去分析了。除此之外,GNU C 還有一些其它擴(kuò)展特性,由于他們在內(nèi)核中用得不是很多,或者說僅僅是做一些編譯上的優(yōu)化,即使不知道也不會影響我們理解代碼,限于篇幅關(guān)系,所以就暫時不講了,比如下面這些特性。
大家以后遇到類似的擴(kuò)展,可以到下面這幾個網(wǎng)站上去看看。
下面是幾道 C 語言練習(xí)題,大家可以做一做??纯磳W(xué)完本教程后,有沒有真正的掌握。有什么疑問,可以通過讀者圈,或加入QQ群(475504428)與我討論。
1.下面的程序,在不同編譯環(huán)境下,比如分別在 C-Free、VC++6.0、TurboC 環(huán)境下編譯運(yùn)行,結(jié)果是否相等,為什么?
#include
int main(void)
{
printf("size: %d\n", sizeof(int);
return 0;
}
2.定義一個宏,求兩個數(shù)的最小值。
3.將下面的程序編譯為可以在 ARM 平臺上運(yùn)行的可執(zhí)行文件 a.out,并對其進(jìn)行反匯編,查看變量 global_val 的地址。
int global_val = 10;
int uninit_val;
int main(void)
{
int local_val = 20;
return 0;
}
在一個工程項(xiàng)目中,有兩個源文件如下,分析下面程序的運(yùn)行結(jié)果。
//func.c
int a = 10;
int b;
int c attribute((weak)) = 30;
//main.c
int a;
int b = 20;
int c = 40;
int main(void)
{
printf("a: %d\n",a);
printf("b: %d\n",b);
printf("c: %d\n",c);
return 0;
}
5.定義一個變參函數(shù),實(shí)現(xiàn)等級打印控制:ERROR、DEBUG、INFO。用這三個宏分別代表等級打印,比如定義 ERROR 時,只打印錯誤的信息;定義 DEBUG 時,打印錯誤和調(diào)試信息;定義 INFO 時,所有的打印信息都打印出來。
6.定義一個變參宏,實(shí)現(xiàn)等級打印控制:ERROR、DEBUG、INFO。用這三個宏分別代表等級打印,比如定義 ERROR 宏時,只打印錯誤的信息;定義 DEBUG 時,打印錯誤和調(diào)試信息;定義 INFO 時,所有的打印信息都打印出來。
7.下面是 Linux 內(nèi)核(Linux4.4.0)中的一些宏定義,請分析它們實(shí)現(xiàn)的功能。
#define pr_emerg(fmt, ...) \
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define pr_alert(fmt, ...) \
printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_crit(fmt, ...) \
printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...) \
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...) \
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warn pr_warning
#define pr_notice(fmt, ...) \
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...) \
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
8.在 Linux 內(nèi)核啟動過程中,啟動 log 的最后往往會有這么一行信息。
Freeing unused kernel memory: 468K
請用本課程中的 section 屬性聲明,分析這段 log 背后的內(nèi)核初始化及內(nèi)存釋放過程。
9.在嵌入式 Linux 驅(qū)動開發(fā)中,驅(qū)動模塊是沒有 main() 入口函數(shù)的,請用本課程學(xué)過的知識分析:驅(qū)動是如何運(yùn)行和初始化的。
10.驅(qū)動分析:在 linux4.4 源碼 linux-4.4/arch/arm/mach-footbridge/ebsa285.c 中,分析下面代碼的含義及 container_of 宏的作用。
MACHINE_START(EBSA285, "EBSA285")
/* Maintainer: Russell King */
.atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.map_io = footbridge_map_io,
.init_early = footbridge_sched_clock,
.init_irq = footbridge_init_irq,
.init_time = footbridge_timer_init,
.restart = footbridge_restart,
MACHINE_END
static void ebsa285_led_set(struct \
led_classdev *cdev, enum led_brightness b)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
if (b == LED_OFF)
hw_led_state |= led->mask;
else
hw_led_state &= ~led->mask;
writeb(hw_led_state, xbus);
}
static enum led_brightness \
ebsa285_led_get(struct led_classdev *cdev)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
return hw_led_state & led->mask ? LED_OFF : LED_FULL;
}
通過本課程的學(xué)習(xí),再加上本節(jié)10個習(xí)題的練習(xí),相信大家的 C 語言功底肯定又加深了一層!有了這些知識儲備基礎(chǔ),基本上就掃除了 Linux 內(nèi)核的閱讀障礙。相信大家在以后的工作、學(xué)習(xí)中一定會日益精進(jìn),不斷突破!
最后祝大家工作順利、學(xué)習(xí)愉快!
另外,大家如果想系統(tǒng)學(xué)習(xí) Linux 內(nèi)核中的某塊知識,或者說有哪些知識掌握得不是很好,想進(jìn)階學(xué)習(xí),但限于工作、學(xué)習(xí)繁忙,時間精力有限,無法系統(tǒng)地去學(xué)習(xí),也可以跟我聯(lián)系交流
本教程根據(jù) C語言嵌入式Linux高級編程視頻教程 第05期 改編,電子版書籍可加入QQ群:475504428 下載,更多嵌入式視頻教程,可關(guān)注:
微信公眾號:宅學(xué)部落(armlinuxfun)
51CTO學(xué)院-王利濤老師:http://edu.51cto.com/sd/d344f