函數(shù)原型:
#include <pthread.h> int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);
返回值:若是成功建立線程返回0,否則返回錯誤的編號
形式參數(shù): pthread_t *restrict tidp 要創(chuàng)建的線程的線程id指針
const pthread_attr_t *restrict attr 創(chuàng)建線程時的線程屬性
void* (start_rtn)(void) 返回值是void類型的指針函數(shù) vodi
*restrict arg start_rtn的行參 例題1: 功能:測試建立一個新的線程 程序名稱: pthread_test.c
#include <pthread.h> #include <stdio.h> void *create(void *arg) ...{ printf("new thread created ..... "); } int main(int argc,char *argv[]) ...{ pthread_t tidp; int error;
error=pthread_create(&tidp,NULL,create,NULL); if(error!=0) ......{ printf("pthread_create is not created ... "); return -1; } printf("prthread_create is created... "); return 0; }
編譯方法:
#gcc -Wall -lpthread pthread_test.c
因為pthread的庫不是linux系統(tǒng)的庫,所以在進(jìn)行編
譯的時候要加上-lpthread,否則編譯不過,會出現(xiàn)下面錯誤
thread_test.c: 在函
數(shù) ‘create’ 中: thread_test.c:7: 警告: 在
有返回值的函數(shù)中,程序流程到達(dá)函數(shù)尾 /tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):對
‘pthread_create’未定義的引用 collect2: ld 返回 1
現(xiàn)在我們能建立了一個線程了,我們可以從函數(shù)的原型看到,在創(chuàng)建線程的時候,是可以在對
我們的函數(shù)進(jìn)行傳遞參數(shù),在pthread_create的第四個行參。我們看一下例題2~3. 例題2
功能:向新的線程傳遞整形值 程序名稱:pthread_int.c
#include <stdio.h> #include <pthread.h> #include <unistd.h> void *create(void *arg) ...{ int *num; num=(int *)arg; printf("create parameter is %d ",*num); return (void *)0; } int main(int argc ,char *argv[]) ...{ pthread_t tidp; int error; int test=4; int *attr=&test; error=pthread_create(&tidp,NULL,create,(void *)attr);
if(error!=0) ...{ printf("pthread_create is created is not created ... "); return -1; } sleep(1); printf("pthread_create is created is created ... "); return 0; }
編譯方法:
gcc -lpthread thread_int.c -Wall
執(zhí)行結(jié)果:
create parameter is 4 pthread_create is created is created ...
例題總結(jié):
可以看出來,我們在main函數(shù)中傳遞的整行指針,傳遞到我們新建的線程函數(shù)中。
在上面的例子可以看出來我們向新的線程傳入了另一個線程的int數(shù)據(jù),線程之間還可以傳遞字符串或是更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
例題3:
程序功能:向新建的線程傳遞字符串 程序名稱:thread_char.c
#include <pthread.h> #include <stdio.h> #include <unistd.h> void *create(void *arg) ...{ char *name; name=(char *)arg; printf("arg is %s
",name); return (void *)0; } int main(int argc,char *argv[]) ...{ char *a="wang"; int error; pthread_t tidp;
error=pthread_create(&tidp,NULL,create,(void *)a);
if(error!=0) ...{ printf("pthread is not created
"); return -1; } sleep(1); printf("pthread is created...
"); return 0; }
編譯方法:
gcc -Wall thread_char.c -lpthread
執(zhí)行結(jié)果:
arg is wang pthread is created...
例題總結(jié):
可以看出來main函數(shù)中的字符串傳入了新建里的線程中。
例題4
程序名稱:thread_struct.c
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> /**//*malloc()*/ struct test ...{ int a; char *s; };
void *create(void *arg) ...{ struct test *temp; temp=(struct test *)arg; printf("test->a ==%d
",temp->a); printf("test->s ==%s
",temp->s); return (void *)0; } int main(int argc,char *argv[]) ...{ pthread_t tidp; int error; struct test *b; b=(struct test *)malloc(sizeof(struct test)); b->a=4; b->s="wang";
error=pthread_create(&tidp,NULL,create,(void *)b);
if(error!=0) ...{ printf("phread is not created...
"); return -1; } sleep(1); printf("pthread is created...
"); return 0; }
編譯方法:
gcc -Wall -lpthread thread_struct.c
執(zhí)行結(jié)果:
test->a ==4 test->s ==wang pthread is created...
線程包含了標(biāo)識進(jìn)程內(nèi)執(zhí)行環(huán)境必須的信息。他集成了進(jìn)程中的所有信息都是對線程進(jìn)行共享
的,包括文本程序、程序的全局內(nèi)存和堆內(nèi)存、棧以及文件描述符。
例題5
程序目的:驗證新建立的線程可以共享進(jìn)程中的數(shù)據(jù) 程序名稱:thread_share.c
#include <stdio.h> #include <pthread.h> #include <unistd.h> static int a=4; void *create(void *arg) ...{ printf("new pthread ...
"); printf("a==%d ",a); return (void *)0; } int main(int argc,char *argv[]) ...{ pthread_t tidp; int error; a=5;
error=pthread_create(&tidp,NULL,create,NULL);
if(error!=0) ...{ printf("new thread is not create ...
"); return -1; } sleep(1); printf("new thread is created ...
"); return 0; }
編譯方法:
gcc -Wall -lpthread thread_share.c
執(zhí)行結(jié)果:
new pthread ... a==5 new thread is created ...
例題總結(jié):可以看出來,我們在主線程更改了我們的全局變量a的值的時候,我們新建立的線程則打印出來了改變的值,可以看出可以訪問線程所在進(jìn)程中的數(shù)據(jù)信
息。
如果進(jìn)程中任何一個線程中調(diào)用exit,_Exit,或者是_exit,那么整個進(jìn)程就
會終止,與此類似,如果信號的默認(rèn)的動作是終止進(jìn)程,那么,把該信號發(fā)送到線程會終止進(jìn)程。 線程的正常退出的方式:
(1) 線程只是從啟動例程中返回,返回值是線程中的退出碼 (2) 線程可以被另一個進(jìn)程進(jìn)行終止 (3)
線程自己調(diào)用pthread_exit函數(shù) 兩個重要的函數(shù)原型:
#include <pthread.h> void pthread_exit(void *rval_ptr); /*rval_ptr 線程退出返回
的指針*/
int pthread_join(pthread_t thread,void **rval_ptr);
/*成功結(jié)束進(jìn)程為0,否則為錯誤編碼*/
例題6 程序目的:線程正常退出,接受線程退出的返回碼
程序名稱:exit_return.c
#include <stdio.h> #include <pthread.h> #include <unistd.h> void *create(void *arg) ...{ printf("new thread is created ...
"); return (void *)2; } int main(int argc,char *argv[]) ...{ pthread_t tid; int error; void *temp;
error=pthread_create(&tid,NULL,create,NULL);
if(error!=0) ...{ printf("thread is not created ...
"); return -1; } error=pthread_join(tid,&temp);
if(error!=0) ...{ printf("thread is not exit ...
"); return -2; } printf("thread is exit code %d
",(int )temp); sleep(1); printf("thread is created...
"); return 0; }
編譯方法:
gcc -Wall exit_return.c -lpthread
執(zhí)行結(jié)果:
new thread is created ... thread is exit code 2 thread is created...
線程退出不僅僅可以返回線程的int數(shù)值,還可以返回一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu) 例題7
程序目的:線程結(jié)束返回一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu) 程序名稱:exit_thread.c
#include <stdio.h> #include <pthread.h> #include <unistd.h> struct test ...{ int a; char *b; };
struct test temp= ...{ .a =4, .b ="wang" };
void *create(void *arg) ...{ printf("new thread ...
"); return (void *)&temp; }
int main(int argc,char *argv[]) ...{ int error; pthread_t tid; struct test *c;
error=pthread_create(&tid,NULL,create,NULL); if(error!=0) ...{ printf("new thread is not created ...
"); return -1; } printf("main ...
");
error=pthread_join(tid,(void *)&c);
if(error!=0) ...{ printf("new thread is not exit ...
"); return -2; } printf("c->a ==%d
",c->a); printf("c->b ==%s
",c->b); sleep(1); return 0; }
編譯方法:
gcc -Wall -lpthread exit_struct.c
執(zhí)行結(jié)果:
main ... new thread ... c->a ==4 c->b ==wang
例題總結(jié):一定要記得返回的數(shù)據(jù)結(jié)構(gòu)要是在這個數(shù)據(jù)要返回的結(jié)構(gòu)沒有釋放的時候應(yīng)用,如果數(shù)據(jù)結(jié)構(gòu)已經(jīng)發(fā)生變化,那返回的就不會是我們所需要的,而是藏數(shù)
據(jù)阿。
函數(shù)原型:
#include <pthread.h> pthread_t pthread_self(void);
例題8 程序目的:實(shí)現(xiàn)在新建立的線程中打印該線程的id和進(jìn)程id 程序名稱:thread_self.c
編譯方法:
gcc -Wall -lpthread thread_self.c
執(zhí)行結(jié)果:
Main thread is starting ... main pid is 6860 new thread .... thread_tid==3084954544 thread pid is 6860
4、 線程的處理程序
函數(shù)原型:
#include <pthread.h> void pthread_cleanup_push(void (*rtn)(void *),void *arg); 函數(shù)rtn是清理函數(shù),arg是調(diào)用參數(shù) void pthread_cleanup_pop(int execute);
在前面講過線程的終止方式,是正常終止還是非正常終止,都會存在一個資源釋放的問題,在posix中提供了一組,就是我們上面看的函數(shù)進(jìn)行線程退出的處理
函數(shù),有些像在進(jìn)程中的atexit函數(shù)。釋放的方式是指pthread_cleanup_push的調(diào)用點(diǎn)到pthread_cleanup_pop之
間程序段進(jìn)行終止。
pthread_cleanup_push()/pthread_cleanup_pop采用先入后出的方式的棧的管理方式,void
*rtn(void
*),在執(zhí)行pthread_cleanup_push()時壓入函數(shù)棧,多次執(zhí)行pthread_cleanup_push()形成一個函數(shù)鏈,在執(zhí)行
這個函數(shù)鏈的時候會以反方向彈出,即先入后出。execute參數(shù)表識,是否執(zhí)行彈出清理函數(shù),當(dāng)execute=0時不進(jìn)行彈出清理函數(shù),非零的時候彈
出處理函數(shù)。
例題9
程序目的:實(shí)現(xiàn)在正常結(jié)束線程的時候,進(jìn)行函數(shù)處理
程序名稱:thread_clean.c
編譯方法:
執(zhí)行結(jié)果:
thread 1 start thread 1 push complete thread 1 exit code 1 thread 2 start thread 2 push complete cleanup :thread 2 second handler cleanup :thread 2 first handler thread 2 exit code 2
gcc -Wall -lpthread thread_clean.c
#include <stdio.h> #include <pthread.h> #include <unistd.h> void *clean(void *arg) ...{ printf("cleanup :%s ",(char *)arg); return (void *)0; } void *thr_fn1(void *arg) ...{ printf("thread 1 start "); pthread_cleanup_push(clean,"thread 1 first handler"); pthread_cleanup_push(clean,"thread 1 second hadler"); printf("thread 1 push complete "); if(arg) ...{ return((void *)1); } pthread_cleanup_pop(0); pthread_cleanup_pop(0); return (void *)1; } void *thr_fn2(void *arg) ...{ printf("thread 2 start "); pthread_cleanup_push(clean,"thread 2 first handler"); pthread_cleanup_push(clean,"thread 2 second handler"); printf("thread 2 push complete "); if(arg) ...{ pthread_exit((void *)2); } pthread_cleanup_pop(0); pthread_cleanup_pop(0); pthread_exit((void *)2); } int main(void) ...{ int err; pthread_t tid1,tid2; void *tret; err=pthread_create(&tid1,NULL,thr_fn1,(void *)1); if(err!=0) ...{ printf("error .... "); return -1; } err=pthread_create(&tid2,NULL,thr_fn2,(void *)1); if(err!=0) ...{ printf("error .... "); return -1; } err=pthread_join(tid1,&tret); if(err!=0) ...{ printf("error .... "); return -1; } printf("thread 1 exit code %d ",(int)tret); err=pthread_join(tid2,&tret); if(err!=0) ...{ printf("error .... "); return -1; }
gcc -Wall -lpthread thread_clean.c
printf("thread 2 exit code %d ",(int)tret); exit(0); }
|