1. 程式人生 > >Linux內核學習筆記

Linux內核學習筆記

寄存器 運行 初始 進程間通信 表示 世紀 com mage call()

2.2 內核源碼樹
arch 特定體系結構的源碼
block Crypto API
crypto 內核源碼文檔
drivers 設備驅動程序
firmware
fs VFS和各種文件系統
include 內核頭文件
init 內核引導和初始化
ipc 進程間通信代碼
kernel 像調度程序這樣的核心子系統
lib 通用內核函數
Makefile
Makefile.common
mm 內存管理子系統和VM
Module.symvers
net 網絡子系統
samples
scripts 編譯內核所用的腳本
security Linux安全模塊
sound 語音子系統
System.map
tools

usr 早期用戶空間代碼
virt

2.3 編譯內核
配置內核(不同的選項)
make config
make menuconfig
make xconfig
make gconfig
創建默認配置
make defconfig
make oldconfig
編譯
make
記錄編譯信息
make >../log.txt
互略編譯信息
make >/dev/null
衍生多個編譯作業
make -j?
如雙核處理器上,每個處理器衍生兩個作業
make -j4

安裝內核
把arch/i386/boot/bzImage拷貝到/boot
依照vmlinuz-version來命名
編輯/boot/grub/grub.conf文件,為新內核建立新的啟動項

使用LILO的系統則編輯/etc/lilo.conf,然後運行lilo

安裝模塊
make modules_install

2.4 內核開發的特點
1.沒有libc庫
大部分常用的C庫函數在內核中都已經得到了實現
2.GNU C
內聯函數
把對時間要求比較高而本身長度又比較短的函數定義成內聯函數
static inline void test(unsigned long tail_size)
內聯函數必須在使用前就定義好,一般在頭文件或者文件頭中定義內聯函數
內聯匯編
分支聲明(為了優化)
likely()
unlikely()
if(unlikely(foo){
/*****/
}

if (likely(foo)){

/****/
}

3.沒有內存保護機制
4.不要輕易在內核中使用浮點數
5.內核空間具有容積小而固定的棧
6.同步和並發
7.可移植性

三.進程管理
進程是處於執行期的程序以及它所包含的資源的總稱
3.1進程描述符及任務結構
內核把進程存放在任務隊列中
任務隊列是各雙向循環鏈表,鏈表中的每一項都是類型為task_struct,成為進程描述符的結構
定義在<linux/sched.h>文件中
進程描述符中包含一個具體進程的所有信息
task_struct在32位機器上有1.7k字節
其中包含的數據能完整的描述一個正在執行的程序
(打開的文件,進程的地址空間,掛起的信號,進程的狀態還有其他更多信息)
3.1.1分配進程描述符
通過slab分配器分配task_struct結構
3.1.2進程描述符的存放
內核通過一個唯一的進程標識值或PID類標識每個進程
PID最大默認值為32768(short int的最大值)
也可以修改/proc/sys/kernle/pid_max來提高上限
3.1.3進程狀態
進程描述符中的state域描述了進程的當前狀態,系統中每個進程都必須處於五種狀態中的一種
TASK_RUNNING(運行)
TASK_INTERRUPTIBLE(可中斷)
TASK_UNINTERRUPTIBLE(不可中斷)
TASK_ZOMBIE(僵死)
TASK_STOPPED(停止)

3.1.4 設置當前進程狀態
set_task_state(task,state);
/將任務task的狀態設置為state/
set_current_state(state) <=> set_stask_state(current,state)

3.1.5進程上下文
3.1.6進程家族樹
所有的進程都是PID為1的init進程的後臺
內核在系統啟動的最後階段啟動init進程
該進程讀取系統的初始化腳本並執行其他的相關程序

進程間的關系存放在進程描述符中
每個tack_struct都包含一個指向其父進程task_struct,叫做parent的指針
獲取其父進程的進程描述符:
struct task_struct my_parent = ourrent->parent;
訪問子進程:
struct task_struct
task;
struct list_head *list;

list_for_each(list,$current->children){
task = list_entry(list,sruct task_struct,sibling);
/* task 現在指向當前的某個子進程*/
}

struct task_struct task;
for (task =current;task != $init_task; task= task->parent)
/
task 現在指向init */

}

五.系統調用
5.1 API.POSIX.C
5.2 系統調用(系統調用號)
5.3 系統調用處理程序
int $0x80(十進制128) system_call()
第128號異常處理程序
系統調用號通過eax寄存器傳遞給內核
call *sys_call_table(,%eax,4)
系統調用表的表項是以32位類型存放的,所以內核需要將給定的系統調用號乘以4,然後查詢
參數傳遞:ebx,ecx,edx,esi和edi按照順序存放前五個參數
5.4 系統調用的實現
5.5 系統調用上下文
entry.s(系統調用表)

六.中斷和中斷處理程序
IRQ:中斷請求
ISR:中斷服務例程

6.3 註冊中斷處理程序
int request_irq(unsigned int irq,
irqreturn_t(handler)(int,void ,struct pt_regs ),
unsighed long irqflags,
const char
devname,
void *dev_id)

參數說明:
irq:要分配的中斷號
handler:指針,指向處理這個中斷的世紀中斷處理程序。
handler函數的原型是特定的,接受三個參數,並有一個類型為irqresutn_t的返回值。
irqflags:可以為0,也可以為下列標誌的位掩碼
SA_INTERRUPT:表示給定的中斷處理程序是一個快速中斷處理程序
SA_SAMPLE_RANDOM:
SA_SHIRQ:
devname:與中斷相關的ASCII文本表示法.
dev_id:

request_irq()成功執行會返回0.

Linux內核學習筆記