2011-06-25 34 views
3

我已經運行了一個場景,其中兩個處理器之間通過調用clone()與CLONE_VM創建的多個glibc/syscalls調用最終會導致我的程序崩潰。如何在Linux上使用CLONE_VM與CLONE_SETTLS

基於我的理解,如果我打算使用CLONE_VM t,那麼我還必須指定CLONE_SETTLS。

任何人都可以舉例說明如何爲我的新克隆準備TLS存儲,以及如何使用CLONE_SETTLS實際執行clone()調用?

+0

'CLONE_VM'不需要'CLONE_SETTLS'。 'vfork()'在沒有'CLONE_SETTLS'的情況下使用'CLONE_VM'。 – ninjalj

+1

vfork依賴於其他進程不修改任何數據,理論上它應該立即調用exec。 - 在這種情況下,兩個進程都將修改數據並創建glibc/syscalls。一切正常,直到他們同時進行一些需要TLS正確操作的調用。 – Jufe

回答

1

用一粒鹽做下面的事情,因爲我只看過這個「編譯過程中」(這裏沒有wooden swords)。

Glibc/NPTL使用TLS存儲大量的線程狀態。 TLS指向線程struct pthread pdpd可能表示pthread描述符),分配在allocate_stack()的線程本地堆棧中,從__pthread_create_2_1()調用。

在x86上,中struct pthread第一件void *tcb,這應指向struct user_desc(其條目數量可能會架構之間各不相同,也可能內核版本之間,我的系統上的glibc使用6內部TLS)。這個tcb作爲參數傳遞給do_clone()

如果你仔細看看這些函數,你會發現glibc存儲了很多關於TLS的信息:關於線程本地堆棧的信息,這個程序是否有多個線程,強大的互斥列表,線程啓動例程和參數,pthread屬性標誌,調度策略,...

總之,如果你能脫離一個真正的pthread線程,它會簡單得多。

0

另一種方法是首先撥打clone,然後撥打pthread_create。 這樣你就可以使用線程庫來獲取正確的TLS(位於線程堆棧中)。

示例代碼:

int tmp_run(void *arg) { 
    void *ret; 
    pthread_t thread; 
    // now call the wanted function 
    pthread_create(&thread, NULL, run, arg); 
    pthread_join(thread, &ret); 
    return (long) ret; 
} 

int main(...) { 
    ... 
    int clone_pid = clone (tmp_run, stack, flags arg); 
    ... 
} 

pthread_create如果屬性是需要在螺紋上更多的控制(例如,棧位置)。