天天看點

APUE學習(五):線程與程序(API與概念部分)

這個主要針對程序線程的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

如果了解了線程和程序的記憶體布局圖,對兩者的認識可能更清晰一點。(程序筆記那一節我記錄了程序的記憶體布局圖)

APUE學習(五):線程與程式(API與概念部分)

這個圖出自http://www.kaoyan.com/kaoyan/18/330074/index_6.html,因為他是概念性的介紹,可能各個系統的實作不太一樣。但是大體應該也差不多,一個程序内的

多線程共享代碼段、資料段(初始化&未初始化),而其堆棧段是不同的(也就是控制流)。

(三) 保留位

windows的程序與線程的關系(雖然之前做windows的開發比較多一些但是還真沒有好好了解這一塊,汗顔)

牽扯到信号、分離&僵屍、資源清理的一下疑問,以後補充

之前接觸多線程實作都是windows下,對linux的線程與程序的認識局限在linux的程序是輕量級程序,在linux下多用多程序進行程式設計。而現在我的了解是linux下的程序實作确實是比windows快很多,但是其線程實作又比程序實作快很多兩者實作我們也略有介紹。是以同步需要比較少 的情況下,不管是windows還是linux采用多線程還是比較好一些。對一下概念做點代碼測試能使了解更立體一點:)概念上資源排程的基本單元是程序,控制排程的基本單元是線程,通過本次的代碼測試對概念和實作有了新認識

繼續閱讀