久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Linux下的C編程入門之“線程”控制與“線程”通信編程

 楚暮四 2010-07-24

1.Linux“線程”

筆者曾經(jīng)在《基于嵌入式操作系統(tǒng)VxWorks的多任務并發(fā)程序設計》(《軟件報》2006年第5~12期)中詳細敘述了進程和線程的區(qū)別,并曾經(jīng)說明Linux是一種“多進程單線程”的操作系統(tǒng),。Linux本身只有進程的概念,,而其所謂的“線程”本質(zhì)上在內(nèi)核里仍然是進程。大家知道,,進程是資源分配的單位,同一進程中的多個線程共享該進程的資源(如作為共享內(nèi)存的全局變量),。Linux中所謂的“線程”只是在被創(chuàng)建的時候“克隆”(clone)了父進程的資源,,因此,,clone出來的進程表現(xiàn)為“線程”,這一點一定要弄清楚,。 Linux內(nèi)核只提供了輕量進程的支持,,未實現(xiàn)線程模型,但Linux盡最大努力優(yōu)化了進程的調(diào)度開銷,,這在一定程度上彌補無線程的缺陷,。Linux用一個核心進程(輕量進程)對應一個線程,將線程調(diào)度等同于進程調(diào)度,,交給核心完成,。

 

目前Linux中最流行的線程機制為LinuxThreads,所采用的就是線程-進程“一對一”模型,,調(diào)度交給核心,,而在用戶級實現(xiàn)一個包括信號處理在內(nèi)的線程管理機制。LinuxThreads由Xavier Leroy ([email protected])負責開發(fā)完成,,并已綁定在GLIBC中發(fā)行,,它實現(xiàn)了一種BiCapitalized面向Linux的Posix 1003.1c “pthread”標準接口。Linuxthread可以支持Intel,、Alpha,、MIPS等平臺上的多處理器系統(tǒng)。
按照POSIX 1003.1c 標準編寫的程序與Linuxthread 庫相鏈接即可支持Linux平臺上的多線程,,在程序中需包含頭文件pthread. h,,在編譯鏈接時使用命令:
gcc -D -REENTRANT -lpthread xxx. c
其中-REENTRANT宏使得相關(guān)庫函數(shù)(如stdio.h、errno.h中函數(shù)) 是可重入的,、線程安全的(thread-safe),,-lpthread則意味著鏈接庫目錄下的libpthread.a或libpthread.so文件。使用Linuxthread庫需要2.0以上版本的Linux內(nèi)核及相應版本的C庫(libc 5.2.18,、libc 5.4.12,、libc 6)。

2.“線程”控制

線程創(chuàng)建
進程被創(chuàng)建時,,系統(tǒng)會為其創(chuàng)建一個主線程,,而要在進程中創(chuàng)建新的線程,則可以調(diào)用pthread_create:
pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
  (start_routine)(void*), void *arg);
start_routine為新線程的入口函數(shù),,arg為傳遞給start_routine的參數(shù),。
每個線程都有自己的線程ID,以便在進程內(nèi)區(qū)分,。線程ID在pthread_create調(diào)用時回返給創(chuàng)建線程的調(diào)用者,;一個線程也可以在創(chuàng)建后使用pthread_self()調(diào)用獲取自己的線程ID:
pthread_self (void) ;
線程退出
線程的退出方式有三:
(1)執(zhí)行完成后隱式退出;
(2)由線程本身顯示調(diào)用pthread_exit 函數(shù)退出,;
pthread_exit (void * retval) ;
(3)被其他線程用pthread_cance函數(shù)終止:
pthread_cance (pthread_t thread) ;
在某線程中調(diào)用此函數(shù),,可以終止由參數(shù)thread 指定的線程,。
如果一個線程要等待另一個線程的終止,可以使用pthread_join函數(shù),,該函數(shù)的作用是調(diào)用pthread_join的線程將被掛起直到線程ID為參數(shù)thread的線程終止:
pthread_join (pthread_t thread, void** threadreturn);

3.線程通信

線程互斥
互斥意味著“排它”,,即兩個線程不能同時進入被互斥保護的代碼。Linux下可以通過pthread_mutex_t 定義互斥體機制完成多線程的互斥操作,,該機制的作用是對某個需要互斥的部分,,在進入時先得到互斥體,如果沒有得到互斥體,,表明互斥部分被其它線程擁有,,此時欲獲取互斥體的線程阻塞,直到擁有該互斥體的線程完成互斥部分的操作為止,。
下面的代碼實現(xiàn)了對共享全局變量x 用互斥體mutex 進行保護的目的:
int x; // 進程中的全局變量
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL); //按缺省的屬性初始化互斥體變量mutex
pthread_mutex_lock(&mutex); // 給互斥體變量加鎖
… //對變量x 的操作
phtread_mutex_unlock(&mutex); // 給互斥體變量解除鎖
線程同步
同步就是線程等待某個事件的發(fā)生。只有當?shù)却氖录l(fā)生線程才繼續(xù)執(zhí)行,,否則線程掛起并放棄處理器,。當多個線程協(xié)作時,相互作用的任務必須在一定的條件下同步,。
Linux下的C語言編程有多種線程同步機制,,最典型的是條件變量(condition variable)。pthread_cond_init用來創(chuàng)建一個條件變量,,其函數(shù)原型為:
pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);
pthread_cond_wait和pthread_cond_timedwait用來等待條件變量被設置,,值得注意的是這兩個等待調(diào)用需要一個已經(jīng)上鎖的互斥體mutex,這是為了防止在真正進入等待狀態(tài)之前別的線程有可能設置該條件變量而產(chǎn)生競爭,。pthread_cond_wait的函數(shù)原型為:
pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
pthread_cond_broadcast用于設置條件變量,,即使得事件發(fā)生,這樣等待該事件的線程將不再阻塞:
pthread_cond_broadcast (pthread_cond_t *cond) ;
pthread_cond_signal則用于解除某一個等待線程的阻塞狀態(tài):
pthread_cond_signal (pthread_cond_t *cond) ; 
pthread_cond_destroy 則用于釋放一個條件變量的資源,。
在頭文件semaphore.h 中定義的信號量則完成了互斥體和條件變量的封裝,,按照多線程程序設計中訪問控制機制,控制對資源的同步訪問,,提供程序設計人員更方便的調(diào)用接口,。
sem_init(sem_t *sem, int pshared, unsigned int val);
這個函數(shù)初始化一個信號量sem 的值為val,參數(shù)pshared 是共享屬性控制,,表明是否在進程間共享,。
sem_wait(sem_t *sem);
調(diào)用該函數(shù)時,若sem為無狀態(tài),,調(diào)用線程阻塞,,等待信號量sem值增加(post )成為有信號狀態(tài);若sem為有狀態(tài),,調(diào)用線程順序執(zhí)行,,但信號量的值減一,。
sem_post(sem_t *sem);
調(diào)用該函數(shù),信號量sem的值增加,,可以從無信號狀態(tài)變?yōu)橛行盘枲顟B(tài),。

4.實例

下面我們還是以著名的生產(chǎn)者/消費者問題為例來闡述Linux線程的控制和通信。一組生產(chǎn)者線程與一組消費者線程通過緩沖區(qū)發(fā)生聯(lián)系,。生產(chǎn)者線程將生產(chǎn)的產(chǎn)品送入緩沖區(qū),,消費者線程則從中取出產(chǎn)品。緩沖區(qū)有N 個,,是一個環(huán)形的緩沖池,。

  1. #include <stdio.h> 
  2. #include <pthread.h> 
  3. #define BUFFER_SIZE 16 // 緩沖區(qū)數(shù)量 
  4. struct prodcons 
  5.   // 緩沖區(qū)相關(guān)數(shù)據(jù)結(jié)構(gòu) 
  6.   int buffer[BUFFER_SIZE]; /* 實際數(shù)據(jù)存放的數(shù)組*/ 
  7.   pthread_mutex_t lock; /* 互斥體lock 用于對緩沖區(qū)的互斥操作 */ 
  8.   int readpos, writepos; /* 讀寫指針*/ 
  9.   pthread_cond_t notempty; /* 緩沖區(qū)非空的條件變量 */ 
  10.   pthread_cond_t notfull; /* 緩沖區(qū)未滿的條件變量 */ 
  11. }; 
  12. /* 初始化緩沖區(qū)結(jié)構(gòu) */ 
  13. void init(struct prodcons *b) 
  14.   pthread_mutex_init(&b->lock, NULL); 
  15.   pthread_cond_init(&b->notempty, NULL); 
  16.   pthread_cond_init(&b->notfull, NULL); 
  17.   b->readpos = 0; 
  18.   b->writepos = 0; 
  19. /* 將產(chǎn)品放入緩沖區(qū),這里是存入一個整數(shù)*/ 
  20. void put(struct prodcons *b, int data) 
  21.   pthread_mutex_lock(&b->lock); 
  22.   /* 等待緩沖區(qū)未滿*/ 
  23.   if ((b->writepos + 1) % BUFFER_SIZE == b->readpos) 
  24.   { 
  25.     pthread_cond_wait(&b->notfull, &b->lock); 
  26.   } 
  27.   /* 寫數(shù)據(jù),并移動指針 */ 
  28.   b->buffer[b->writepos] = data; 
  29.   b->writepos++; 
  30.   if (b->writepos >  = BUFFER_SIZE) 
  31.     b->writepos = 0; 
  32.   /* 設置緩沖區(qū)非空的條件變量*/ 
  33.   pthread_cond_signal(&b->notempty); 
  34.   pthread_mutex_unlock(&b->lock); 
  35.  
  36. /* 從緩沖區(qū)中取出整數(shù)*/ 
  37. int get(struct prodcons *b) 
  38.   int data; 
  39.   pthread_mutex_lock(&b->lock); 
  40.   /* 等待緩沖區(qū)非空*/ 
  41.   if (b->writepos == b->readpos) 
  42.   { 
  43.     pthread_cond_wait(&b->notempty, &b->lock); 
  44.   } 
  45.   /* 讀數(shù)據(jù),移動讀指針*/ 
  46.   data = b->buffer[b->readpos]; 
  47.   b->readpos++; 
  48.   if (b->readpos >  = BUFFER_SIZE) 
  49.     b->readpos = 0; 
  50.   /* 設置緩沖區(qū)未滿的條件變量*/ 
  51.   pthread_cond_signal(&b->notfull); 
  52.   pthread_mutex_unlock(&b->lock); 
  53.   return data; 
  54.  
  55. /* 測試:生產(chǎn)者線程將1 到10000 的整數(shù)送入緩沖區(qū),消費者線 
  56. 程從緩沖區(qū)中獲取整數(shù),兩者都打印信息*/ 
  57. #define OVER ( - 1) 
  58. struct prodcons buffer; 
  59. void *producer(void *data) 
  60.   int n; 
  61.   for (n = 0; n < 10000; n++) 
  62.   { 
  63.     printf("%d --->\n", n); 
  64.     put(&buffer, n); 
  65.   } put(&buffer, OVER); 
  66.   return NULL; 
  67.  
  68. void *consumer(void *data) 
  69.   int d; 
  70.   while (1) 
  71.   { 
  72.     d = get(&buffer); 
  73.     if (d == OVER) 
  74.       break
  75.     printf("--->%d \n", d); 
  76.   } 
  77.   return NULL; 
  78.  
  79. int main(void
  80.   pthread_t th_a, th_b; 
  81.   void *retval; 
  82.   init(&buffer); 
  83.   /* 創(chuàng)建生產(chǎn)者和消費者線程*/ 
  84.   pthread_create(&th_a, NULL, producer, 0); 
  85.   pthread_create(&th_b, NULL, consumer, 0); 
  86.   /* 等待兩個線程結(jié)束*/ 
  87.   pthread_join(th_a, &retval); 
  88.   pthread_join(th_b, &retval); 
  89.   return 0; 

5.WIN32、VxWorks,、Linux線程類比

目前為止,,筆者已經(jīng)創(chuàng)作了《基于嵌入式操作系統(tǒng)VxWorks的多任務并發(fā)程序設計》(《軟件報》2006年5~12期連載)、《深入淺出Win32多線程程序設計》(天極網(wǎng)技術(shù)專題)系列,,我們來找出這兩個系列文章與本文的共通點,。
看待技術(shù)問題要瞄準其本質(zhì),不管是Linux,、VxWorks還是WIN32,,其涉及到多線程的部分都是那些內(nèi)容,無非就是線程控制和線程通信,,它們的許多函數(shù)只是名稱不同,,其實質(zhì)含義是等價的,下面我們來列個三大操作系統(tǒng)共同點詳細表單:

事項

WIN32

VxWorks

Linux

線程創(chuàng)建

CreateThread

taskSpawn

pthread_create

線程終止

執(zhí)行完成后退出,;線程自身調(diào)用ExitThread 函數(shù)即終止自己,;被其他線程調(diào)用函數(shù)TerminateThread函數(shù)

執(zhí)行完成后退出;由線程本身調(diào)用exit退出,;被其他線程調(diào)用函數(shù)taskDelete終止

執(zhí)行完成后退出,;由線程本身調(diào)用pthread_exit退出;被其他線程調(diào)用函數(shù)pthread_cance終止

獲取線程ID

GetCurrentThreadId

taskIdSelf

pthread_self

創(chuàng)建互斥

CreateMutex

semMCreate

pthread_mutex_init

獲取互斥

WaitForSingleObject,、

WaitForMultipleObjects

semTake

pthread_mutex_lock

釋放互斥

ReleaseMutex

semGive

phtread_mutex_unlock

創(chuàng)建信號量

CreateSemaphore

semBCreate,、semCCreate

sem_init

等待信號量

WaitForSingleObject

semTake

sem_wait

釋放信號量

ReleaseSemaphore

semGive

sem_post


6.小結(jié)

本章講述了Linux下多線程的控制及線程間通信編程方法,給出了一個生產(chǎn)者/消費者的實例,,并將Linux的多線程與WIN32,、VxWorks多線程進行了類比,總結(jié)了一般規(guī)律,。鑒于多線程編程已成為開發(fā)并發(fā)應用程序的主流方法,,學好本章的意義也便不言自明。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多