標籤:
最近折騰CTS
android.security.cts
testCheckForDuplicateOutput項,單項測試很容易過,但是聯測就掛了。
源碼:http://xdecay.com/docs/android-sdk/cts/tests/tests/security/d0/db5/_cloned_secure_random_test_8java_source.php
測試的原理是:不停的建立和關閉進程,測試Pass的前提是出現兩個Pid相同的進程。。
迴圈過程如下:
a). 建立進程A, 記錄下A的Pid為pid-1; 然後立即Kill pid-1;
b). 建立進程B, 記錄下B的Pid為pid-2; 然後立即Kill pid-2;
……
直到再次出現記錄過的進程號。
因為Linux的PId數是有限的,
根據鴿巢原理(n個盒子裝n+1個球,必然出現一個盒子有兩個球的現象),假設PID的上線時pid_max, 那麼如果建立pid_max個進程(並不同時存在),那麼必然會再次出現以前出現過的進程號。
CTS 測試為了加快測試速率,調用了如下的函數(wastePids):
比如 第一次是pid-1, 多次迴圈之後還未出現同PID的進程號,比如這時出現了pid-5000,那麼就調用wastePids(1,5000)
/** * This is an attempt to get the PIDs to roll over faster. Threads use up * PIDs on Android and spawning a new thread is much faster than having * another service spawned as we are doing in this test. */ private static void wastePids(int firstPid, int previousPid) { int distance = (firstPid - previousPid + MAX_PID) % MAX_PID; // Don't waste PIDs if we're close to wrap-around to improve odds of // collision. if ((distance < PID_WASTING_SKIP_LOWER) || (MAX_PID - distance < PID_WASTING_SKIP_UPPER)) { return; } for (int i = 0; i < distance; i++) { Thread t = new Thread(); t.start(); } }
按注釋翻譯而言,應該是通過建立Thread ,將可分配的剩下的Pid佔用掉,讓Pid儘快迴圈複用。
問題來了:從傳統的thread學習而言,thread怎麼會佔用Pid,Linux書籍都會告訴我們,所有同一個進程下的thread共用一個Pid;更何況,JVM的線程跟Pthread的線程還不是一個東西,因此迷惑了。
查了linux核心的書籍,基本不怎麼講述thread, 這主要是pthread是一個庫,而不是Linux核心本身的一部分。
然後開始翻牆google。
找到3篇文章:
第一篇:http://www.cnblogs.com/princessd8251/articles/3914434.html
這篇文章,測試JVM能開闢的最大線程數: 發現線程數量在達到32279以後,不再增長。查了一下,32位Linux系統可建立的最大pid數是32678,這個數值可以通過/proc/sys/kernel/pid_max來做修改(修改方法同threads-max),但是在32系統下這個值只能改小,無法更大。
雖然實際線程數,可以通過修改核心來建立更多線程,但這表明,線程數跟Pid_max是有關的;
第二篇:http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/
這篇文章分析Linux 線程實現機制
雖然,線上程庫裡面,pthread的建立,使用的是多個線程share 同一個PID,然而,核心確有自己的機制:
Linux核心並不支援真正意義上的線程,LinuxThreads是用與普通進程具有同樣核心調度視圖的輕量級進程來實現線程支援的。這些輕量級進程擁有獨立的進程id,在進程調度、訊號處理、IO等方面享有與普通進程一樣的能力。
這句話就表明了,核心中,採用的是輕量級的進程來支撐線程的調度的,那麼必然會佔用Pid:
第三篇:http://blog.chinaunix.net/uid-27767798-id-3470592.html
講述了Pid的分配過程:alloc_pidmap:
static int alloc_pidmap(struct pid_namespace *pid_ns) { int i, offset, max_scan, pid, last = pid_ns->last_pid; //取出last_pid struct pidmap *map; pid = last + 1; //這裡last+1,取得備選pid//如果pid到了pidmax,那麼重頭開始尋找可用的pid,從RESERVED_PIDS開始,保留RESERVED_PIDS之前的pid號,預設300 if (pid >= pid_max) pid = RESERVED_PIDS; ……}
指明pid是從低往高分配,當超過pid_max,那麼重頭開始尋找可用的pid,從RESERVED_PIDS開始,保留RESERVED_PIDS之前的pid號,預設300
到這裡基本就明朗了。
至於Thread如何通過VM進入到核心 參看:http://www.eoeandroid.com/blog-21517-3026.html
從Cts測試testCheckForDuplicateOutput到linux kernel中Thread消耗PID