linux核心pid雜湊表

2021-07-30 07:27:08 字數 2013 閱讀 4859

首先看一下kernel中的雜湊表的資料結構,雜湊表頭:

cpp**

struct hlist_head ;  

煉表頭是hlist_head,注意這是乙個雙向鍊錶但不迴圈。first欄位指向第乙個節點。

雜湊表節點:

cpp**

struct hlist_node ;  

這裡的next指向下乙個節點,pprev欄位存放了上乙個next欄位的位址。即*(second->pprev) = = first->next。

核心中經常需要通過程序的pid來獲得程序描述符task_struct,順序掃瞄程序鍊錶並檢查程序描述符的pid欄位是可行但相當低效的。為了加速查詢引入4個雜湊表,因為程序包含了表示不同型別的pid的字段,而且每個字段需要它自己的雜湊表。

4個雜湊表和程序描述符中的相關字段:

hash表的型別 欄位名 說明

pidtype_pid pid 程序的pid

pidtype_tgid tgid 執行緒組領頭程序的pid

pidtype_pgid pgrp 程序組領頭程序的pid

pidtype_sid session 會話領頭程序的pid

核心初始化期間為4個雜湊表分配空間,並把它們的位址存入pid_hash陣列。在start_kernel函式中呼叫了pidhash_init:

cpp**

void __init pidhash_init(void)  

}  pidhash_shift是表索引的長度,注意這裡有個printk,我系統啟動的列印資訊有這麼一行:

cpp**

[    0.000000] pid hash table entries: 4096 (order: 12, 16384 bytes)  

說明我系統的pidhash_shift為12,這個值依賴於系統ram的大小。例如:乙個擁有512mb的ram,每個雜湊表擁有4個頁框,可以擁有2048個表項。pidhash_init函式中使用alloc_bootmem分配器為雜湊表分配記憶體(這是alloc_page,slab還未初始化),pid_hash的第一維是雜湊表,第二維是每個雜湊表中的雜湊位址。每個位址會對應乙個鍊錶,所以這裡初始化煉表頭,如下圖:

pidtype_max就是雜湊表的個數,在pid.h中有乙個列舉:

cpp**

enum pid_type  

;  

cpp**

#define pid_hashfn(x)    hash_long((unsigned long)x, pidhash_shift)

在32位體系結構中hash_long等價於:

cpp**

unsigned long hash_long(unsigned long val, unsigned int bits)    

這裡我們使pidhash_shift為11,這樣表索引的範圍為0~2047,hash_long相當於(pid*0x9e370001)>>21。pid從0~32767會產生衝突,這裡解決衝突的方法就是使用鍊錶。如上圖,pid號為199的和pid為29384的程序產生了衝突,被鏈在同乙個雜湊位址的鍊錶上。

(199*0x9e370001)>>21 = 199,(29384*0x9e370001)>>21 = 199。

下面來看一下task_struct的pid欄位,在task_struct中有:

cpp**

struct pid pids[pidtype_max];  

cpp**

struct pid  

;  

nr是程序的pid,pid_chain是將發生衝突的pid鏈在這個pid_chain鍊錶上,pid_list欄位是同乙個執行緒組,會話組或程序組的鏈結在pid_list鍊錶上,如下圖:

這個圖里,pid為246的和pid為4351的pid發成衝突,所以鏈結在pid_chain鍊錶上。同乙個執行緒組的pid為4351的三個程序鏈結到pid_list上。

**

Linux程序PID雜湊表

linux 系統中每個程序由乙個程序id標識,在核心中對應乙個task struct結構的程序描述符,系統中所有程序的task struct通過鍊錶鏈結在一起,在核心中,經常需要通過程序id來獲取程序描述符,最簡單的方法可以通過遍歷task struct鍊錶並對比id的值來獲取,但這樣效率太低,尤其...

Linux Linux程序PID雜湊表

linux系統中每個程序由乙個程序id標識,在核心中對應乙個task struct結構的程序描述符,系統中所有程序的task struct通過鍊錶鏈結在一起,在核心中,經常需要通過程序id來獲取程序描述符,最簡單的方法可以通過遍歷task struct鍊錶並對比id的值來獲取,但這樣效率太低,尤其當...

linux 核心雜湊鍊錶

struct hlist node struct hlist head struct hlist node 雜湊表我們一般用鏈結位址法來解決雜湊衝突。一般我們想單鏈表即可解決問題,為什麼核心要引入乙個 pre呢?了解下構造圖 可以看出 hlist head和hlist node 不是乙個型別。這樣要...