linux c學習筆記----線程創建與終止


進程原語 線程原語 描述
fork pthread_create 創建新的控制流
exit pthread_exit 從現有的控制流中退出
waitpid pthread_join 從控制流中得到退出狀態
atexit pthread_cancel_push 注冊在退出控制流時調用的函數
getpid pthread_self 獲取控制流的ID
abort pthread_cancel 請深圳市控制流的非正常退出

 

 

pthread_create

int pthread_create(pthread_t *thread, pthread_addr_t *arr,void* (*start_routine)(void *), void *arg);

  •  thread    :用於返回創建的線程的ID
  • arr         : 用於指定的被創建的線程的屬性,上面的函數中使用NULL,表示使用默認的屬性
  • start_routine      : 這是一個函數指針,指向線程被創建后要調用的函數
  • arg        : 用於給線程傳遞參數,在本例中沒有傳遞參數,所以使用了NULL
 
線程創建時並不能保證哪個線程會先運行:是新創建的線程還是調用線程。新創建的線程可以訪問進程的地址空間,
並且繼承調用線程的浮點環境和信號屏蔽字,但是該線程的未決信號集被消除。
 
單個線程可以通過三種方式退出,在不終止整個進程的情況下停止它的控制流。
(1)線程只是從啟動全程中返回,返回值是線程的退出碼。
(2)線程可以被同一進程中的其他線程取消
(3)線程調用pthread_exit
 
 
void pthread_exit(void *rval_ptr)
rval_ptr是一個無類型指針,與傳給啟動例程的單個參數類似。進程中的其他線程可以通過調用pthread_join函數訪問到這個指針。
 
int pthread_join(pthread_t thread,void **rval_ptr);
成功返回0,失敗返回錯誤編號
調用線程將一直阻塞,直到指定的線程調用pthread_exit,從啟動例程中返回或者被取消。
如果線程只是從它的啟動例程返回,rval_ptr將包含返回碼。如果線程被取消,由rval_ptr指定的內存單元被置為PTHREAH_CANCELED.
可以通過調用pthread_join自動把線程置於分離狀態,這樣資源就可以恢復。如果線程已經處於分離狀態,pthread_join調用就會失敗,返回EINVAL.
如果對線程的返回值並不感興趣,可以把rval_ptr置為NULL。在這種情況下,調用pthread_join函數將等待指定的線程停止,但並不獲取線程的終止狀態。
 
在 調用線程的棧上分配了該結構,那么其他的線程在使用這個結構進內存可能已經改變了。又如,線程在自己的棧上分配了一個結構然后把指向這個結構的指針傳給 pthread_exit,那么當調用pthread_join的線程試圖使用該結構時,這個棧有可能已經被撤消,這塊內存也已另作他用。
例如:#include <stdlib.h>
 1 #include <stdio.h>  
 2 #include <pthread.h>  
 3   
 4 struct foo {  
 5     int a, b, c, d;  
 6 };  
 7   
 8 void printfoo(const char *s, const struct foo *fp)  
 9 {  
10     printf("%s",s);  
11     printf("  structure at 0x%x\n", (unsigned)fp);  
12     printf("  foo.a = %d\n", fp->a);  
13     printf("  foo.b = %d\n", fp->b);  
14     printf("  foo.c = %d\n", fp->c);  
15     printf("  foo.d = %d\n", fp->d);  
16 }  
17   
18 void *thr_fn1(void *arg)  
19 {  
20     struct foo  foo = {1, 2, 3, 4};  
21   
22     printfoo("thread 1:\n", &foo);  
23     pthread_exit((void *)&foo);  
24 }  
25   
26 void *thr_fn2(void *arg)  
27 {  
28     struct foo  fao = { 2,2, 3, 4};  
29     printf("thread 2: ID is %d\n", (unsigned int)pthread_self());  
30     pthread_exit((void *)0);  
31 }  
32   
33 int main(void)  
34 {  
35     int         err;  
36     pthread_t   tid1, tid2;  
37     struct foo  *fp;  
38   
39     err = pthread_create(&tid1, NULL, thr_fn1, NULL);  
40     if (err != 0)  
41         printf("can't create thread 1: %d\n", strerror(err));  
42     err = pthread_join(tid1, (void *)&fp);  
43     if (err != 0)  
44         printf("can't join with thread 1: %d\n", strerror(err));  
45     sleep(1);  
46     printf("parent starting second thread\n");  
47     err = pthread_create(&tid2, NULL, thr_fn2, NULL);  
48     if (err != 0)  
49         printf("can't create thread 2: %d\n", strerror(err));  
50     sleep(1);  
51     printfoo("parent:\n", fp);  
52     exit(0);  
53 }  
 
void pthread_cleanup_push(void (*rtn)(void *),void *arg);
void pthread_cleanup_pop(int execute);
當線程執行以下動作時調用清理函數,調用參數為arg,清理函數rtn的調用順序是由pthread_cleanup_push函數來安排的。
1.調用pthread_exit時。2.響應取消請求時。3.用非零execute參數調用pthread_cleanup_pop時。
如果execute參數置為0,清理函數將不被調用。無論哪種情況,pthread_cleanup_pop都將刪除上次pthread_clean_push調用建立的清理處理程序。
實例:
 1 #include <stdlib.h>  
 2 #include <stdio.h>  
 3 #include <pthread.h>  
 4   
 5 void cleanup(void *arg)  
 6 {  
 7     printf("cleanup: %s\n", (char *)arg);  
 8 }  
 9   
10 void *thr_fn1(void *arg)  
11 {  
12     printf("thread 1 start\n");  
13     pthread_cleanup_push(cleanup, "thread 1 first handler");  
14     pthread_cleanup_push(cleanup, "thread 1 second handler");  
15     printf("thread 1 push complete\n");  
16     if (arg)  
17         return((void *)1);  
18         // pthread_exit((void *)2);  
19           
20     pthread_cleanup_pop(0);  
21     pthread_cleanup_pop(0);  
22     // return((void *)1);  
23     pthread_exit((void *)2);  
24   
25 }  
26   
27 void *thr_fn2(void *arg)  
28 {  
29     printf("thread 2 start\n");  
30     pthread_cleanup_push(cleanup, "thread 2 first handler");  
31     pthread_cleanup_push(cleanup, "thread 2 second handler");  
32     printf("thread 2 push complete\n");  
33     if (arg)  
34         pthread_exit((void *)2);  
35     pthread_cleanup_pop(0);  
36     pthread_cleanup_pop(0);  
37     pthread_exit((void *)2);  
38 }  
39   
40 int main(void)  
41 {  
42     int         err;  
43     pthread_t   tid1, tid2;  
44     void        *tret;  
45   
46     err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);  
47     if (err != 0)  
48         printf("can't create thread 1: %c\n", strerror(err));  
49     err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);  
50     if (err != 0)  
51         printf("can't create thread 2: %c\n", strerror(err));  
52     err = pthread_join(tid1, &tret);  
53     if (err != 0)  
54         printf("can't join with thread 1: %c\n", strerror(err));  
55     printf("thread 1 exit code %d\n", (int)tret);  
56     err = pthread_join(tid2, &tret);  
57     if (err != 0)  
58         printf("can't join with thread 2: %c\n", strerror(err));  
59     printf("thread 2 exit code %d\n", (int)tret);  
60     exit(0);  
61 }  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM