alloc pidmap 函式註解

2022-05-17 09:14:15 字數 3669 閱讀 6933

在建立程序的時候會呼叫到alloc_pidmap來分配乙個空閒的pid。

函式入參是pid_namespace結構體,介紹下該結構體的兩個成員:

int last_pid 上乙個程序所使用的pid;

struct pidmap pidmap[pidmap_entries] pid點陣圖陣列,pidmap有兩個成員:nr_free,用來表徵當前點陣圖中的空閒pid個數;page指標,儲存一頁大小的記憶體的虛擬位址,也就是pid點陣圖,一頁有32768位,每一位代表乙個pid,置1表示該位表徵的pid已被使用。

來看具體的實現流程:

1     pid = last + 1;2

if (pid >=pid_max)

3 pid =reserved_pids;45

/*32位體系結構上,pid點陣圖是乙個物理頁,但是pid的值可以超過一頁含有的位數32768,

6獲取新程序pid在頁內偏移7*/

8 offset = pid &bits_per_page_mask;9/*

pid/bits_per_page 表徵處於哪一頁,每個頁都有乙個與之對應的pidmap結構體

*/10 map = &pid_ns->pidmap[pid/bits_per_page];

首先是last pid加1作為新程序的pid,如果pid大於等於pid_max,就把pid置為reserved_pids(300),從reserved_pids開始查詢空閒pid,然後獲取頁內偏移和該pid所對應的pidmap結構體,假設pid_max為65536,那麼pidmap[0]表徵pid 0~32767,pidmap[1]表徵pid 32768~65535。

1 max_scan = div_round_up(pid_max, bits_per_page) - !offset;

接下來會通過乙個for迴圈來遍歷位圖,max_scan表明遍歷次數,如果offset為0,即從0開始查詢空閒pid,max_scan為0,那麼只需要遍歷一次;如果offset不為0,max_scan為1,需要遍歷二次。

1

/*max_scan表徵的查詢次數只適用於從offset開始查詢位圖沒有找到空閒pid的情況,

2因為一旦查詢到了就直接返回pid了,不會再開始下一次查詢;34

主要是擔心offset如果不為0,即使從offset開始直到點陣圖末沒有查詢到空閒pid,但

5是offset之前的點陣圖中仍然可能有空閒的pid,於是將offset置為reserved_pids,重

6新從最初的點陣圖開始查詢,或者置offset為0,從下一張開始查詢78

如果offset為0,max_scan就為1,從頭開始查詢,如果沒有找到合適的pid,就說明的確

9是沒有空閒的pid,就不必再繼續遍歷,max_scan為0即可

10*/

11for (i = 0; i <= max_scan; ++i)

1229 spin_unlock_irq(&pidmap_lock);

30/*

如果map->page是null,page賦值為null,接下來free(null);

31如果map->page不是null,就不要再分配新頁,把新分配的頁free掉

32*/

33kfree(page);

34if (unlikely(!map->page))

35break;36

}37/*如果該位圖內還有未分配的pid

*/38

if (likely(atomic_read(&map->nr_free)))

3954

/*如果offset指定的位已被占用,就從offset開始在map->page中找到

5556

為0的位,offset如果大於bits_per_page說明已經不屬於該pidmap了

57*/

58 offset =find_next_offset(map, offset);

59/*

根據offset得到實際pid值

*/60 pid =mk_pid(pid_ns, map, offset);

6162 } while (offset < bits_per_page && pid 6465

/*66

在以上的**中,比較理想的情況是找到了合適的pid,然後return,但是還有一

67些其他的情況,比如從某個offset開始直到該頁結束的位都被用光了,那麼根據

68find_next_offset查詢到的offset就會超過bits_per_page,此時假如還有多餘的

6970

最後一張位圖,就將map設為pidmap[0],從第一張位圖開始繼續查詢,只不過要從

71offset 300開始查詢,前提是max_scan為1,那麼max_scan是否有可能不為1呢?

7273

如果最初查詢空閒pid時獲得的offset為0,只有一種情況,就是在核心啟動過程中

74剛剛開始建立程序,即從offset為0開始查詢空閒pid是肯定能查詢到的,因而如果

75查詢不到pid,最初的offset肯定不為0,即max_scan肯定為1,肯定還可以再執行一

76個for迴圈查詢一次

77*/

78if (map < &pid_ns->pidmap[(pid_max-1)/bits_per_page])

7983

else

8490 pid =mk_pid(pid_ns, map, offset);

91 }

為pid點陣圖分配一頁大小的記憶體;通過nr_free判斷將要查詢的pidmap中是否還有空閒的pid,開始乙個do...while迴圈來遍歷該位圖查詢pid,呼叫test_and_set_bit判斷offset所指定的點陣圖中的位是否為0(test_and_set_bit返回0),如果是表明該位表徵的pid空閒,即已經找到了空閒pid,nr_free減1,將該pid設定了last_pid之後返回。

如果offset指定的pid已被占用,就呼叫find_next_offset從offset開始找到第乙個為0的位,返回值是該位距離點陣圖首位址的偏移,如果找到的空閒位的位置沒有超過bits_per_page,表示仍屬於該pidmap並且由空閒位得到的pid沒有超過pid_max,那麼該位就是所要找的pid,返回。

存在三種情況會跳出該do...while迴圈:

1. offset > bits_per_page ,pid < pid_max

查詢到的空閒位不屬於該pidmap,但是沒有超過pid_max,說明當前點陣圖的pid已全部被占用,那麼就從下乙個點陣圖的偏移0處開始繼續查詢;

2. offset < bits_per_page ,pid > pid_max

查詢到的空閒位屬於該pidmap,但是超過pid_max,就從第乙個pidmap[0]的reserved_pids開始查詢,發生在pid_max不是bits_per_page的整數倍的情況;

3. offset > bits_per_page ,pid > pid_max

查詢到的空閒位屬於該pidmap,但是超過pid_max,就從第乙個pidmap[0]的reserved_pids開始查詢,發生在pid_max是bits_per_page的整數倍的情況;

(其他的可以看函式注釋)   

Python 函式註解

start 當我們定義函式的時候,引數是不需要指定型別的,如果你要呼叫別人寫的函式,而該函式又沒有文件說明,你如何知道要傳遞什麼型別的引數呢?也需只能看源 了。好在 python 還提供了一種機制,可以在定義函式的同時指定引數型別,稱之為函式註解。def f name str,age int 18 ...

函式引數註解

python是動態語言,變數隨時可以被賦值,且能賦值為不同的另外型別 python不是靜態編譯型語言,變數型別是在執行期決定的 動態語言很靈活,但是這種特性也是弊端 def add x,y return x y print add 4,5 9 print add hello word hellowo...

python oops Python函式註解

以下內容基於python 3x 涉及的知識前提 建議理解python裝飾器後學習此內容 函式註解概述 函式註解可以針對函式的引數 返回值新增元資料,其為註解。python是動態語言,變數賦值時不會強制宣告型別,且能隨時重新賦值。無法像靜態編譯型語言一樣,在編譯時發現基本問題。函式的引數要求,沒有詳細...