這個主要針對程序線程的api和概念來講的,了解了後邊碰到線程同步以及程序通信從原理上就會有個認識
(一)控制原語
程序原語 | 線程原語 | 描述 |
fork | pthread_create | 建立。從建立上可以看出兩者的差別,strace指令跟蹤到前者調用clone,後者clone&mmap2 |
exit | pthread_exit | 退出 |
waitpid | pthread_join | 等待,并得到退出狀态 |
atexit | pthread_cleanup_push | 注冊退出時候調用函數 |
getpid | pthread_self | 擷取控制流id |
abort | pthread_cancel | 請求非正常退出 |
pthread_detach | 線程進入分離狀态,然後自動進行資源釋放,不需pthread_join處理。 |
關于fork 和 pthread_create這裡貼的連接配接可以參考一下。
http://www.fuzhijie.me/?p=235
關于pthread_join & pthread_detach剛開始看書上說明以及man page有點吃力,寫了個測試就一目了然了。
/*
*線程終止測試
*pthread_exit(),pthread_join().
*分離态pthread_detach()
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* thread_handle(void* arg)
{
// pthread_detach(pthread_self()); //自己能使自己處理分離狀态,之前寫錯了。現在修正
// sleep(4);
printf("from thread_handle\n");
return ;
// pthread_exit();
}
int main(int argc,char* argv[])
{
pthread_t tid;
int result;
void* retvar;
if( (result = pthread_create(&tid,NULL,thread_handle,NULL)) != 0)
perror("pthread create error\n");
if( (result = pthread_detach(tid)) != 0)
printf("pthread detach error\n"); \\線程中使用error_no牽扯到同步與私有化問題,之前用perror也是不當的,這裡給出修正
// sleep(2);
if( (result = pthread_join(tid,&retvar)) != 0)
printf("pthread join error\n");
printf("main exit ,and thread return %d\n",(int)result);
exit(0);
}
detach之後的輸出
pthread join error
main exit,and thread return xxxx //這裡thread沒有執行
如果sleep(2)
pthread join error
from thread handle
main exit,and thread return xxxx
(二) 系統實作淺析
系統環境
$cat /proc/version
Linux version 3.0.1 ([email protected]) (gcc version 4.4.5 (Debian 4.4.5-8) ) #1 SMP Fri Aug 12 11:50:03 CST 2011
這裡我建立1000個線程和1000個程序進行跟蹤截取部分。
$strace -c ./my_thread
130ms
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
97.99 0.001170 1 1011 618 mmap2
2.01 0.000024 0 382 clone
$strace -c ./my_proc
63ms
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000166 0 1000 clone
線程函數在編譯的時候,需要-lpthread ,也就是說系統核心沒有實作線程。
在trace 函數fork 與 pthread_create的時候,兩者都是通過clone實作.fork調用的clone,pthread_create在mmap2傳回錯誤的時候調用clone.而在網上搜到資料裡fork和vfork調用的是do_fork,但是我通過trace沒有跟蹤到這個函數,問了個了解核心實作的同學說do_fork調用clone..好吧,不管怎麼樣都不影響我們對他的了解。
線程和程序在核心的系統調用的相似性上表明兩者在linux下的差別,程序由系統核心實作,線程在系統調用之餘其建立、銷毀、同步由線程庫pthread做了大量的工作。
具體的clone函數的參數的說明能更了解一下兩者的概念,這裡我就不繼續往下深挖了。
這個文章讨論的還很有意義,http://topic.csdn.net/u/20100514/23/a71bad9c-8c84-4e9c-aa7f-c961af943a7c.html
如果了解了線程和程序的記憶體布局圖,對兩者的認識可能更清晰一點。(程序筆記那一節我記錄了程序的記憶體布局圖)
這個圖出自http://www.kaoyan.com/kaoyan/18/330074/index_6.html,因為他是概念性的介紹,可能各個系統的實作不太一樣。但是大體應該也差不多,一個程序内的
多線程共享代碼段、資料段(初始化&未初始化),而其堆棧段是不同的(也就是控制流)。
(三) 保留位
windows的程序與線程的關系(雖然之前做windows的開發比較多一些但是還真沒有好好了解這一塊,汗顔)
牽扯到信号、分離&僵屍、資源清理的一下疑問,以後補充
之前接觸多線程實作都是windows下,對linux的線程與程序的認識局限在linux的程序是輕量級程序,在linux下多用多程序進行程式設計。而現在我的了解是linux下的程序實作确實是比windows快很多,但是其線程實作又比程序實作快很多兩者實作我們也略有介紹。是以同步需要比較少 的情況下,不管是windows還是linux采用多線程還是比較好一些。對一下概念做點代碼測試能使了解更立體一點:)概念上資源排程的基本單元是程序,控制排程的基本單元是線程,通過本次的代碼測試對概念和實作有了新認識