1. 程式人生 > >3---Linux核心及核心程式設計

3---Linux核心及核心程式設計

什麼是作業系統?

指在系統中負責完成最基本功能和系統管理的部分,

作業系統有哪些組成部分?

  • 核心------作業系統的內在核心
  • 裝置驅動程式
  • 啟動載入程式
  • 命令列shell
  • 其他種類的使用者介面----作業系統的外在表象
  • 基本的檔案管理工具和系統工具

Linux核心的組成

Linux核心原始碼目錄結構是什麼,各目錄有什麼含義?

  • arch:包含和硬體體系結構相關的程式碼,每種平臺佔一個相應的目錄,如i386、ARM、PowerPC、MIPS等
  • block:塊裝置驅動程式I/O 排程。
  • crypto:常用加密和雜湊演算法(如AES、SHA等),還有一些壓縮和CRC校驗演算法。
  • Documentation:核心各部分的通用解釋和註釋。
  • drivers:裝置驅動程式,每個不同的驅動佔用一個子目錄,如char、block、net、mtd、i2c等。
  • fs:支援的各種檔案系統,如EXT、FAT、NTFS、JFFS2 等。
  • include:標頭檔案,與系統相關的標頭檔案被放置在include/linux 子目錄下。
  • init:核心初始化程式碼
  • ipc:程序間通訊的程式碼。
  • kernel:核心的最核心部分,包括程序排程、定時器等,而和平臺相關的一部分程式碼放在arch/*/kernel目錄下。
  • lib:庫檔案程式碼。
  • mm:記憶體管理程式碼,和平臺相關的一部分程式碼放在arch/*/mm目錄下。
  • net:網路相關程式碼,實現了各種常見的網路協議。
  • scripts:包含用於配置核心的指令碼檔案。
  • security:主要包含SELinux 模組。
  • sound:ALSA、OSS音訊裝置的驅動核心程式碼和常用裝置驅動。
  • usr:實現了用於打包和壓縮的cpio等

Linux核心的有哪些組成部分?

程序排程(SCHED)、記憶體管理(MM)、虛擬檔案系統(VFS)、網路介面(NET)和程序間通訊(IPC)

Linux核心的的組成部分之間有什麼關係?

  • 程序排程與記憶體管理之間互相依賴。在多道程式環境下,必須為程式建立程序,而建立程序的第一件事情就是將程式和資料裝入記憶體。
  • 程序間通訊子系統要依賴記憶體管理支援共享記憶體通訊機制,這種機制允許兩個程序除了擁有自己的私有空間,還可以存取共同的記憶體區域。
  • 虛擬檔案系統利用網路介面支援網路檔案系統(NFS),也利用記憶體管理支援RAMDISK 裝置。
  • 記憶體管理利用虛擬檔案系統支援交換,依賴於程序排程完成交換程序(swapd)定期由排程程式排程。當一個程序存取的記憶體對映被換出時,記憶體管理向檔案系統發出請求,同時,掛起當前正在執行的程序。

 

程序排程有什麼作用?

排程控制系統中的多個程序對CPU 的訪問,使得多個程序能在CPU 中微觀序列,巨集觀並行地執行。

程序排程為什麼很重要?

程序排程處於系統的中心位置,核心中其他的子系統都依賴它,因為每個子系統都需要掛起或恢復程序

程序如何在幾個狀態間切換?

在裝置驅動程式設計中,當請求的資源不能得到滿足時會怎樣?

驅動一般會排程其他程序執行,其對應的程序進入睡眠狀態,直到它請求的資源被釋放,才會被喚醒而進入就緒狀態。

裝置驅動中,如果需要幾個併發執行的任務要怎麼做?

呼叫函式int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);啟動核心執行緒。

記憶體管理的主要作用是什麼?

控制多個程序安全地共享主記憶體區域。當CPU提供記憶體管理單元(MMU)時,Linux 記憶體管理完成為每個程序進行虛擬記憶體到實體記憶體的轉換。

程序的地址空間時怎樣劃分的?

Linux 的每個程序享有4GB的記憶體空間,0~3GB屬於使用者空間,3~4GB屬於核心空間

虛擬檔案系統有什麼作用?

Linux 虛擬檔案系統(VFS)隱藏各種了硬體的具體細節,為所有裝置提供了統一的介面。而且,它獨立於各個具體的檔案系統,是對各種檔案系統的一個抽象

虛擬檔案系統如何描述檔案相關資訊?

使用超級塊super block存放檔案系統相關資訊,使用索引節點inode存放檔案的物理資訊,使用目錄項dentry存放檔案的邏輯資訊。

網路介面有什麼作用?

提供了對各種網路標準的存取和各種網路硬體的支援。

網路介面包括那兩個部分?

網路協議和網路裝置驅動程式

網路協議有什麼作用?

負責實現每一種可能的網路傳輸協議

網路裝置驅動程式有什麼作用?

負責與硬體裝置進行通訊,每一種可能的硬體裝置都有相應的裝置驅動程式。

程序通訊有什麼作用?

協助多個程序、多資源的互斥訪問、程序間的同步和訊息傳遞

有哪些程序通訊機制?

訊號量、共享記憶體、管道、訊息佇列、Socket通訊、Binder通訊

ARM處理器有幾種工作模式?

  • 使用者模式(usr):大多數的應用程式執行在使用者模式下,當處理器執行在使用者模式下時,某些被保護的系統資源是不能被訪問的。
  • 快速中斷模式(fiq):用於高速資料傳輸或通道處理。
  • 外部中斷模式(irq):用於通用的中斷處理。
  • 管理模式(svc):作業系統使用的保護模式。
  • 資料訪問終止模式(abt):當資料或指令預取終止時進入該模式,可用於虛擬儲存及儲存保護。
  • 系統模式(sys):執行具有特權的作業系統任務。
  • 未定義指令中止模式(und):當未定義的指令執行時進入該模式,可用於支援硬體協處理器的軟體模擬。

為什麼要劃分核心空間和使用者空間?

核心可進行任何操作,而應用程式則被禁止對硬體的直接訪問和對記憶體的未授權訪問。劃分核心空間和使用者空間用來區分程式執行的這兩種不同狀態,它們使用不同的地址空間。

如何實現從使用者空間到核心空間的控制轉移?

只能通過系統呼叫和硬體中斷完成

Linux核心的編譯及載入

核心的配置系統由哪既部分組成?

  • Makefile:分佈在Linux 核心原始碼中的Makefile,定義Linux 核心的編譯規則。
  • 配置檔案(Kconfig):給使用者提供配置選擇的功能。
  • 配置工具:包括配置命令直譯器(對配置指令碼中使用的配置命令進行解釋)和配置使用者介面(提供字元介面和圖形介面)。這些配置工具都是使用指令碼語言編寫的,如Tcl/TK、Perl等。

使用make config、make menuconfig等命令後生成一個.config配置檔案,有什麼作用?

記錄哪些部分被編譯入核心、哪些部分被編譯為核心模組。

在Linux 核心中增加程式需要完成哪些工作?

  • 將編寫的原始碼複製到Linux 核心原始碼的相應目錄。
  • 在目錄的Kconfig檔案中增加新原始碼對應專案的編譯配置選項。
  • 在目錄的 Makefile檔案中增加對新原始碼的編譯條目。

為S3C2410 的LED 編寫了驅動,原始碼為s3c2410-led.c,為使核心能支援對該模組的編譯配置,需要完成哪些工作?

  • 將編寫的s3c2410-led.c原始碼複製到linux-2.6.15.5\drivers\char 目錄。
  • 在目錄的Kconfig檔案中增加LED 的編譯配置選項,如下所示:
config S3C2410_LED
bool "S3C2410 LED Driver"
depends on ARCH_S3C2410
help
LED driver for the Samsung S3C2410.
  •  在目錄的 Makefile檔案中增加對s3c2410-led.c原始碼的編譯,obj-$(CONFIG_S3C2410_LED) += s3c2410-led.o

kbuild Makefile的語法中目標定義有什麼作用?

目標定義,用來定義哪些內容要作為模組編譯,哪些要編譯並連線進核心

kbuild Makefile的語法中如何進行目標定義?

  1. 例如:obj-y += foo.o
  2. 根據.config 檔案的CONFIG_變數來決定檔案的編譯方式,如下所示:
 obj-$(CONFIG_ISDN) += isdn.o
 obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

什麼是多檔案模組的定義?

如果一個模組由多個檔案組成,這時候應採用模組名加-objs字尾或者-y字尾的形式來定義模組的組成檔案。

如何進行多檔案模組的定義?

///1---如-y形式
obj-$(CONFIG_EXT2_FS) += ext2.o
ext2-y := balloc.o bitmap.o
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

///2---如-objs的形式:
obj-$(CONFIG_ISDN) += isdn.o
isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

什麼是目錄層次的迭代?

形如obj-$(CONFIG_EXT2_FS) += ext2/的定義,如果CONFIG_EXT2_FS值為y或m時,kbuild將會把ext2 目錄列入向下迭代的目標中,具體ext2 目錄下的檔案是要作為模組編譯還是鏈入核心由ext2 目錄下的Makefile檔案的內容決定。

核心配置指令碼檔案Kconfig的語法中“config”關鍵字有什麼作用?

“config”關鍵字定義新的配置選項,之後的幾行定義了該配置選項的屬性。

配置選項的屬性有哪些?

型別、資料範圍、輸入提示、依賴關係(及反向依賴關係)、幫助資訊和預設值等

配置選項的型別有哪些?

配置選項都必須指定型別,型別包括bool、tristate、string、hex 和int。

如何指定配置選項的型別?

///方法1---:
bool "Networking support"
///方法2----:
bool
prompt "Networking support"

如何定義資料範圍?

range <symbol> <symbol> [if <expr>]

資料範圍symbol的值如何指定?

symbol 分為兩類,一類是由選單入口定義配置選項定義的非常數symbol,另一類是作為expr 組成部分的常數symbol。為int 和hex 型別的選項設可以接受的輸入值範圍,使用者只能輸入大於等於第一個symbol,小於等於第二個symbol 的值。

如何定義輸入提示?
prompt <prompt> [if <expr>]

如何定義依賴關係?

///方法1---
bool "foo" if BAR
default y if BAR
///方法2---
depends on BAR
bool "foo"
default y

depends 能限定一個symbol 的上限,即如果A依賴於B,B的配置如何影響A?

在B被配置為“Y”的情況下,A可以為“Y”、“M”和“N”;在B被配置為“M”的情況下,A可以被配置為“M”或“N”;B在被配置為“N”的情況下,A只能為“N”。

如何定義反向依賴關係?

    select <symbol> [if <expr>]

select能限定一個symbol的下限,若A反向依賴於B,B的配置如何影響A?

A的配置值會高於或等於B(正好與depends 相反)。如果symbol 反向依賴於多個物件,則它的下限是這些物件的最大值。

如何定義多個依賴關係?

多個依賴關係之間用“&&”間隔,

如何定義expr(表示式)?

 <expr> ::= <symbol>
            <symbol> '=' <symbol>
            <symbol> '!=' <symbol>
            '(' <expr> ')''!' <expr>
             <expr> '&&' <expr>
             <expr> '||' <expr>

如何定義幫助資訊?

help(或---help---)
開始
…
結束

如何定義配置選項的預設值?

default <expr> [if <expr>]

配置選項的預設值有什麼作用?

如果使用者不設定對應的選項,配置選項的值就是預設值。

任意多個預設值情況下,如何確定哪個配置選項的預設值是有效的?

存在任意多個預設值情況下,只有第一個被定義的值是可用的。

在選單樹結構中如何確定選單入口的位置?

  1. 所有處於“menu”和“endmenu”之間的選單入口都會成為“Network device support”的子選單。而且,所有子選單選項都會繼承父選單的依賴關係,比如,“Network device support”對“NET”的依賴被加到了配置選項NETDEVICES的依賴列表中。
  2. 如果選單選項在一定程度上依賴於前面的選項,它就能成為該選項的子選單。如果父選項為“N”,則子選項不可見;如果父選項為“Y”或“M”,則子選項可見。MODVERSIONS直接依賴MODULES,如果MODULES不為“N”,該選項才可見。
///方法1---
menu "Network device support"
      depends on NET
      config NETDEVICES
…
endmenu

///方法2---
config MODULES
bool "Enable loadable module support"
config MODVERSIONS
bool "Set version information on all module symbols"
depends on MODULES
comment "module support disabled"
depends on !MODULES

在X86 PC上從上電/復位到執行Linux 使用者空間,進入與Linux 相關程式碼之前,會經歷哪些階段?

  1. 當系統上電或復位時,CPU會將PC指標賦值為一個特定的地址0xFFFF0,並執行該地址處的指令。在PC 中,該地址位於BIOS 中,它儲存在主機板上的ROM 或Flash中。
  2.  BIOS執行時按照CMOS的設定定義的啟動裝置順序來搜尋處於活動狀態,並且可以引導的裝置。若從硬碟啟動,BIOS會將硬碟MBR(主引導記錄)中的內容載入到RAM。MBR 是一個512 位元組大小的扇區,位於磁碟上的第一個扇區中(0 道0柱面1 扇區)。當MBR被載入到RAM 中之後,BIOS就會將控制權交給MBR。
  3. 主引導載入程式查詢並載入次引導載入程式。它在分割槽表中查詢活動分割槽,當找到一個活動分割槽時,掃描分割槽表中的其他分割槽,以確保它們都不是活動的。當這個過程驗證完成之後,就將活動分割槽的引導記錄從這個裝置中讀入RAM中並執行它。
  4. 次引導載入程式載入Linux核心和可選的初始RAM 磁碟,將控制權交給Linux核心原始碼。
  5. 執行被載入的核心,並啟動使用者空間應用程式。

Linux下的C 程式設計

Linux中巨集定義、變數名、函式名命名習慣是什麼?

#define PI 3.1415926
int min_value, max_value;//單詞之間以_相連
void send_data(void);

如何定義零長陣列?

struct var_data
{
int len;
char data[0];
};

零長陣列有什麼作用?

char data[0]僅僅意味著程式中通過var_data 結構體例項的data[index]成員可以訪問len 之後的第index 個地址,它並沒有為data[]陣列分配記憶體,因此sizeof(structvar_data)=sizeof(int)。

如何利用零長陣列訪問資料?

struct var_data s;
...
for (i = 0; i < s.len; i++)
{
printf("%02x", s.data[i]);
}

如何使用case語法結構?

//case x…y這樣的語法,區間[x,y]的數都會滿足這個case的條件,
switch (ch)
{
case '0'... '9': c -= '0';
break;
case 'a'... 'f': c -= 'a' - 10;
break;
case 'A'... 'F': c -= 'A' - 10;
break;
}
//程式碼中的case '0'... '9'等價於標準C中的如下程式碼:
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':

什麼是語句表示式?

包含在括號中的複合語句看做是一個表示式,稱為語句表示式,它可以出現在任何允許表示式的地方

如何定義和使用語句表示式?

#define min_t(type,x,y) ({ type _ _x = (x); type _ _y = (y); _ _x < _ _y ? _ _x: _ _y; })
int ia, ib, mini;
float fa, fb, minf;
mini = min_t(int, ia, ib);
minf = min_t(float, fa, fb);

typeof 關鍵字有什麼作用?

typeof(x)語句可以獲得x 的型別

如何使用typeof 關鍵字?

通過程式碼行(void) (&_x == &_y)的作用是檢查_x 和_y的型別是否一致

#define min(x,y) ({ const typeof(x) _x = (x); const typeof(y) _y = (y); (void) (&_x == &_y); _x < _y ? _x : _y; })

如何定義可變引數的巨集?

arg 表示其餘的引數可以是零個或多個,這些引數以及引數之間的逗號構成 arg 的值,在巨集擴充套件時替換arg,使用“##”的原因是處理arg 不代表任何引數的情況,這時候,前面的逗號就變得多餘了。使用“##”之後,GNU C前處理器會丟棄前面的逗號。

#define pr_debug(fmt,arg...) printk(fmt,##arg)
//例如下列程式碼:
pr_debug("%s:%d",filename,line)
//會被擴充套件為:
printk("%s:%d", filename, line)

如何使用當前函式名?

_ _FUNCTION_ _儲存函式在原始碼中的名字,_ _PRETTY_FUNCTION_ _儲存帶語言特色的名字

void example()
{
printf("This is function:%s", _ _FUNCTION_ _);
}
//程式碼中的_ _FUNCTION_ _意味著字串“example”

什麼是特殊屬性宣告?

GNU C允許宣告函式、變數和型別的特殊屬性,以便進行手工的程式碼優化和定製程式碼檢查的方法。

如何進行特殊屬性宣告?

指定一個宣告的屬性,只需要在聲明後新增__attribute__(( ATTRIBUTE ))。其中ATTRIBUTE 為屬性說明,如果存在多個屬性,則以逗號分隔。

//noreturn
# define ATTRIB_NORET _ _attribute_ _((noreturn)) ....
asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;
//format
asmlinkage int printk(const char * fmt, ...) _ _attribute_ _ ((format(printf, 1, 2)));
//aligned,表示該結構型別的變數以4 位元組對界。
struct example_struct{
char a;
int b;
long c;
} _ _attribute_ _((aligned(4)));
//packed
struct example_struct{
char a;
int b;
long c _ _attribute_ _((packed));
};

有哪些特殊屬性?

  • noreturn 屬性作用於函式,表示該函式從不返回。這會讓編譯器優化程式碼,並消除不必要的警告資訊
  • format屬性也用於函式,表示該函式使用printf、scanf 或strftime 風格的引數,指定format屬性可以讓編譯器根據格式串檢查引數型別
  • unused屬性作用於函式和變數,表示該函式或變數可能不會被用到,這個屬性可以避免編譯器產生警告資訊。
  • aligned屬性用於變數、結構體或聯合體,指定變數、結構體或聯合體的對界方式,以位元組為單位,
  • packed屬性作用於變數和型別,用於變數或結構體成員時表示使用最小可能的對界,用於列舉、結構體或聯合體型別時表示該型別使用最小的記憶體

do{}while(0)有什麼作用?

保證巨集定義的使用者能無編譯錯誤地使用巨集,它不對其使用者做任何假設。

用於錯誤處理的goto使用時需要注意什麼?

需保證在錯誤處理時登出、資源釋放的順序與正常的註冊、釋放申請的順序相反。