linux源碼分析(一)


前置:這里使用的linux版本是4.8,x86體系。

其實linux的內核啟動的入口文件還是非常好找的,init/main.c。

static 和 extern

首先理解的是static和extern的區別:

static int kernel_init(void *);

extern void init_IRQ(void);
extern void fork_init(void);
extern void radix_tree_init(void);

這個代碼說的是kernel_init函數的定義在這個文件中,extern說明init_IRQ函數的定義在其他文件中。
這三個extern分別是對中斷的初始化,對fork功能的初始化,對基數樹的初始化。不過具體不知道為什么有的函數以init_xxx為風格,有的又以xxx_init的風格來做。

main的第一行看到了這么個語句

#define DEBUG

感覺有點奇怪,原來還有#define <宏名> 而沒有定義具體的值。其實這個可以當作已經有定義,且定義了空串來理解。
http://bbs.csdn.net/topics/390960776?page=1

繼續往下面看,還會看到

bool early_boot_irqs_disabled __read_mostly;

這里最后的__read_mostly 是一個宏,它標記了前面這個變量是很經常被讀取的。那么做了標記有什么用呢?

如果在有緩存的平台上,它就能把這個變量存放到cache中,以保證后續讀取的速度。這個宏定義在 arch/arm/include/asm/cache.h

#define __read_mostly __attribute__((__section__(".data..read_mostly")))

這里的意思是將這個數據結構鏈接進data.read_mostly段。

EXPORT_SYMBOL

EXPORT_SYMBOL(system_state);

這個是和extern一起使用的,表示system_state這個方法在這個模塊中定義了,提供給其他模塊使用。

在其他模塊中,只需要使用extern 就可以使用這個方法。

這里就涉及到模塊的概念。

模塊是linux內核對外提供的一個插件機制,由於linux是單內核,這個單內核是相對微內核來說的。所以linux很大可能會非常龐大,這個模塊機制就是對單內核的一種補充,把一些功能放給內核模塊開發。比如像上面的那個代碼,就是對內核提供了system_state的函數接口。

__initdata

下面代碼:

char __initdata boot_command_line[COMMAND_LINE_SIZE];

這里的__initdata也是一個宏,定義在include/linux/init.h

#define __init        __section(.init.text) __cold notrace
#define __initdata    __section(.init.data)
#define __initconst    __constsection(.init.rodata)
#define __exitdata    __section(.exit.data)
#define __exit_call    __used __section(.exitcall.exit)

同上面__read_mostly一樣,是用來把這個變量綁定在某個區里面。

http://blog.csdn.net/beatbean/article/details/8448623

這個圖就說明了什么是__section。它的功能有點像是全局變量,只是這個全局變量是對匯編這個層次的表達,某個變量,我固定在某個內存段里面。這么做其實還有一個好處,段也是一種分類,比如這個段存儲的是init函數的變量,那么等初始化結束之后,我把這個段的內存直接釋放。里面的變量也一次性消除了。

EXPORT_SYMBOL_GPL

下面看到一個很奇怪的方法

EXPORT_SYMBOL_GPL(static_key_initialized);

這個和之前的EXPORT_SYMBOL不一樣,多了一個GPL后綴。

由於模塊很有可能是第三方(非linux內核組成員)開發的。那么有人希望自己開發的模塊是閉源的。它就會在自己開發的模塊里面使用

MODULE_LICENSE("Proprietary")

來標記這個模塊是閉源的。相對的,如果你的模塊遵循GPL這個開源許可證規則,那么則增加下面的:

MODULE_LICENSE("GPL");

好了,linux對這兩種許可證行為的模塊開放的接口並不相同,本節的這個函數就是說明這個方法只對GPL的模塊開放。

http://www.ruanyifeng.com/blog/2010/02/why_gpl_is_a_better_choice.html

__setup 和 early_param

unsigned int reset_devices;
EXPORT_SYMBOL(reset_devices);

static int __init set_reset_devices(char *str)
{
reset_devices = 1;
return 1;
}

__setup("reset_devices", set_reset_devices);

這段代碼,首先需要理解__setup,這個函數就理解為:啟動時候如果有接收reset_devices參數,那么就調用set_reset_devices方法。而詳細看了下set_reset_devices方法,里面只是把reset_devices變量設置為1,但是呢,這個reset_devices變量又是一個給所有模塊使用的變量。

所以這段代碼能達到的功能是只要啟動參數有包含reset_device,通過設置reset_devices通知給所有模塊。

與__setup相對應的還有一個叫做early_param。這兩個宏函數的功能一樣,區別就在於early_param定義的參數比__setup更早。

http://www.linuxde.net/2013/02/12446.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM