pthread執行緒建立過程(未完)
阿新 • • 發佈:2019-01-27
1. 當我們使用pthread_create來建立執行緒的時候, 實際上呼叫的是__pthread_create_2_1
versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1);
2. 而__pthread_create_2_1裡面呢,
根據傳入的pthread_attr_t 來分配stack,這個stack可以被thread使用
其呼叫函式allocate_stack來分配, 這個函式又呼叫mmap來得到記憶體
mem = mmap (NULL, size, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
然後呼叫函式create_thread() 函式來建立執行緒
3. 而create_thread實際上呼叫sys_clone來建立,
而clone的flag呢, 在這裡指定。
clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
| CLONE_SETTLS | CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID | CLONE_SYSVSE
呼叫do_clone的引數為
int res = do_clone (pd, attr, clone_flags, start_thread, STACK_VARIABLES_ARGS, 1);
而STACK_VARIABLES_PARMS 被定義為void *stackaddr, size_t stacksize
注意: 這裡start_thread實際上是執行緒返回後執行的函式。其定義在nptl/pthread_create.c中
4. do_clone裡面則是呼叫glibc-2.14/sysdeps/unix/sysv/linux/i386/clone.S 來建立執行緒 5. clone.s 又通過系統呼叫sys_clone來建立核心執行緒 6. sys_clone呢, 呼叫do_fork來建立執行緒 7. sys_clone 和 kernel_thread的函式區別呢, 在於 sys_clone呼叫的時候, 從使用者態傳入棧的起始地址和棧的大小,把這兩個引數傳給了do_fork 而kernel_thread函式, 呼叫do_fork的時候, 這兩個引數都是0 同時呢, sys_clone還傳入了地址用換存放parent_tid 和child_tid 8. 現在再關注下 clone的時候,傳入的clone_flag 1. 這裡CLONE_VM非常重要, 在kernel_thread 這個flag也是指定的, 而kernel_thread所有的執行緒都是使用同一個頁表。 而這裡, 意味著所有的執行緒也是使用同一個頁表。 2. 而CLONE_FILES, 則只是增加了parent task_struck->files_struct的ref count。 對比程序的fork, 則是把file_struct 複製了一份。 3. CLONE_SETTLS 則為執行緒建立新的TLS
4. do_clone裡面則是呼叫glibc-2.14/sysdeps/unix/sysv/linux/i386/clone.S 來建立執行緒 5. clone.s 又通過系統呼叫sys_clone來建立核心執行緒 6. sys_clone呢, 呼叫do_fork來建立執行緒 7. sys_clone 和 kernel_thread的函式區別呢, 在於 sys_clone呼叫的時候, 從使用者態傳入棧的起始地址和棧的大小,把這兩個引數傳給了do_fork 而kernel_thread函式, 呼叫do_fork的時候, 這兩個引數都是0 同時呢, sys_clone還傳入了地址用換存放parent_tid 和child_tid 8. 現在再關注下 clone的時候,傳入的clone_flag 1. 這裡CLONE_VM非常重要, 在kernel_thread 這個flag也是指定的, 而kernel_thread所有的執行緒都是使用同一個頁表。 而這裡, 意味著所有的執行緒也是使用同一個頁表。 2. 而CLONE_FILES, 則只是增加了parent task_struck->files_struct的ref count。 對比程序的fork, 則是把file_struct 複製了一份。 3. CLONE_SETTLS 則為執行緒建立新的TLS