《Linux多线程编程的基本的函数.doc》由会员分享,可在线阅读,更多相关《Linux多线程编程的基本的函数.doc(14页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Linux多线程编程的基本的函数函数原型: #includeintpthread_create(pthread_t*restricttidp,constpthread_attr_t*restrictattr,void*(*start_rtn)(void),void*restrictarg); 返回值:若是成功建立线程返回0,否则返回错误的编号 形式参数: pthread_t *restrict tidp 要创建的线程的线程id指针 const pthread_attr_t *restrict attr 创建线程时的线程属性 void* (start_rtn)(void) 返回值是void类型的
2、指针函数 vodi *restrict arg start_rtn的行参 例题1: 功能:测试建立一个新的线程 程序名称: pthread_test.c #include#includevoid*create(void*arg).printf(newthreadcreated.);intmain(intargc,char*argv).pthread_ttidp;interror;error=pthread_create(&tidp,NULL,create,NULL);if(error!=0).printf(pthread_createisnotcreated.);return-1;printf
3、(prthread_createiscreated.);return0; 编译方法:#gcc-Wall-lpthreadpthread_test.c 因为pthread的库不是linux系统的库,所以在进行编译的时候要加上-lpthread,否则编译不过,会出现下面错误thread_test.c:在函数create中:thread_test.c:7:警告:在有返回值的函数中,程序流程到达函数尾/tmp/ccOBJmuD.o:Infunctionmain:thread_test.c:(.text+0x4f):对pthread_create未定义的引用collect2:ld返回1现在我们能建立了一
4、个线程了,我们可以从函数的原型看到,在创建线程的时候,是可以在对我们的函数进行传递参数,在pthread_create的第四个行参。我们看一下例题23. 例题2 功能:向新的线程传递整形值 程序名称:pthread_int.c #include#include#includevoid*create(void*arg).int*num;num=(int*)arg;printf(createparameteris%d,*num);return(void*)0;intmain(intargc,char*argv).pthread_ttidp;interror;inttest=4;int*attr=&
5、test;error=pthread_create(&tidp,NULL,create,(void*)attr);if(error!=0).printf(pthread_createiscreatedisnotcreated.);return-1;sleep(1);printf(pthread_createiscreatediscreated.);return0; 编译方法:gcc-lpthreadthread_int.c-Wall 执行结果:createparameteris4pthread_createiscreatediscreated. 例题总结: 可以看出来,我们在main函数中传递
6、的整行指针,传递到我们新建的线程函数中。 在上面的例子可以看出来我们向新的线程传入了另一个线程的int数据,线程之间还可以传递字符串或是更复杂的数据结构。 例题3: 程序功能:向新建的线程传递字符串 程序名称:thread_char.c #include#include#includevoid*create(void*arg).char*name;name=(char*)arg;printf(argis%s ,name);return(void*)0;intmain(intargc,char*argv).char*a=wang;interror;pthread_ttidp;error=pthr
7、ead_create(&tidp,NULL,create,(void*)a);if(error!=0).printf(pthreadisnotcreated );return-1;sleep(1);printf(pthreadiscreated. );return0; 编译方法:gcc-Wallthread_char.c-lpthread 执行结果:argiswangpthreadiscreated. 例题总结: 可以看出来main函数中的字符串传入了新建里的线程中。 例题4 程序名称:thread_struct.c #include#include#include#include/*/*ma
8、lloc()*/structtest.inta;char*s;void*create(void*arg).structtest*temp;temp=(structtest*)arg;printf(test-a=%d ,temp-a);printf(test-s=%s ,temp-s);return(void*)0;intmain(intargc,char*argv).pthread_ttidp;interror;structtest*b;b=(structtest*)malloc(sizeof(structtest);b-a=4;b-s=wang;error=pthread_create(&t
9、idp,NULL,create,(void*)b);if(error!=0).printf(phreadisnotcreated. );return-1;sleep(1);printf(pthreadiscreated. );return0; 编译方法:gcc-Wall-lpthreadthread_struct.c 执行结果:test-a=4test-s=wangpthreadiscreated.线程包含了标识进程内执行环境必须的信息。他集成了进程中的所有信息都是对线程进行共享的,包括文本程序、程序的全局内存和堆内存、栈以及文件描述符。 例题5 程序目的:验证新建立的线程可以共享进程中的数据
10、 程序名称:thread_share.c #include#include#includestaticinta=4;void*create(void*arg).printf(newpthread. );printf(a=%d ,a);return(void*)0;intmain(intargc,char*argv).pthread_ttidp;interror;a=5;error=pthread_create(&tidp,NULL,create,NULL);if(error!=0).printf(newthreadisnotcreate. );return-1;sleep(1);printf(
11、newthreadiscreated. );return0; 编译方法:gcc-Wall-lpthreadthread_share.c 执行结果:newpthread.a=5newthreadiscreated. 例题总结:可以看出来,我们在主线程更改了我们的全局变量a的值的时候,我们新建立的线程则打印出来了改变的值,可以看出可以访问线程所在进程中的数据信息。 如果进程中任何一个线程中调用exit,_Exit,或者是_exit,那么整个进程就会终止,与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。 线程的正常退出的方式: (1) 线程只是从启动例程中返回,返回值是
12、线程中的退出码 (2) 线程可以被另一个进程进行终止 (3) 线程自己调用pthread_exit函数 两个重要的函数原型: #includevoidpthread_exit(void*rval_ptr);/*rval_ptr 线程退出返回的指针*/intpthread_join(pthread_tthread,void*rval_ptr); /*成功结束进程为0,否则为错误编码*/ 例题6 程序目的:线程正常退出,接受线程退出的返回码 程序名称:exit_return.c #include#include#includevoid*create(void*arg).printf(newthre
13、adiscreated. );return(void*)2;intmain(intargc,char*argv).pthread_ttid;interror;void*temp;error=pthread_create(&tid,NULL,create,NULL);if(error!=0).printf(threadisnotcreated. );return-1;error=pthread_join(tid,&temp);if(error!=0).printf(threadisnotexit. );return-2;printf(threadisexitcode%d ,(int)temp);
14、sleep(1);printf(threadiscreated. );return0; 编译方法:gcc-Wallexit_return.c-lpthread 执行结果:newthreadiscreated.threadisexitcode2threadiscreated. 线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构 例题7 程序目的:线程结束返回一个复杂的数据结构 程序名称:exit_thread.c #include#include#includestructtest.inta;char*b;structtesttemp=.a=4,.b=wang;void*cre
15、ate(void*arg).printf(newthread. );return(void*)&temp;intmain(intargc,char*argv).interror;pthread_ttid;structtest*c;error=pthread_create(&tid,NULL,create,NULL);if(error!=0).printf(newthreadisnotcreated. );return-1;printf(main. );error=pthread_join(tid,(void*)&c);if(error!=0).printf(newthreadisnotexit
16、. );return-2;printf(c-a=%d ,c-a);printf(c-b=%s ,c-b);sleep(1);return0; 编译方法: gcc-Wall-lpthreadexit_struct.c 执行结果:main.newthread.c-a=4c-b=wang 例题总结:一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时候应用,如果数据结构已经发生变化,那返回的就不会是我们所需要的。函数原型: #includepthread_tpthread_self(void); 例题8 程序目的:实现在新建立的线程中打印该线程的id和进程id 程序名称:thread_se
17、lf.c #include#include#include/*/*getpid()*/void*create(void*arg).printf(newthread. );printf(thread_tid=%u ,(unsignedint)pthread_self();printf(threadpidis%d ,getpid();return(void*)0;intmain(intargc,char*argv).pthread_ttid;interror;printf(Mainthreadisstarting. );error=pthread_create(&tid,NULL,create,N
18、ULL);if(error!=0).printf(threadisnotcreated. );return-1;printf(mainpidis%d ,getpid();sleep(1);return0; 编译方法: gcc-Wall-lpthreadthread_self.c 执行结果:Mainthreadisstarting.mainpidis6860newthread.thread_tid=3084954544threadpidis6860 4、 线程的处理程序 函数原型: #includevoidpthread_cleanup_push(void(*rtn)(void*),void*a
19、rg); 函数rtn是清理函数,arg是调用参数voidpthread_cleanup_pop(intexecute); 在前面讲过线程的终止方式,是正常终止还是非正常终止,都会存在一个资源释放的问题,在posix中提供了一组,就是我们上面看的函数进行线程退出的处理函数,有些像在进程中的atexit函数。释放的方式是指pthread_cleanup_push的调用点到pthread_cleanup_pop之间程序段进行终止。pthread_cleanup_push()/pthread_cleanup_pop采用先入后出的方式的栈的管理方式,void *rtn(void *),在执行pthrea
20、d_cleanup_push()时压入函数栈,多次执行pthread_cleanup_push()形成一个函数链,在执行这个函数链的时候会以反方向弹出,即先入后出。execute参数表识,是否执行弹出清理函数,当execute=0时不进行弹出清理函数,非零的时候弹出处理函数。 例题9 程序目的:实现在正常结束线程的时候,进行函数处理 程序名称:thread_clean.c 编译方法: 执行结果: thread1startthread1pushcompletethread1exitcode1thread2startthread2pushcompletecleanup:thread2secondh
21、andlercleanup:thread2firsthandlerthread2exitcode2gcc-Wall-lpthreadthread_clean.c#include#include#includevoid*clean(void*arg).printf(cleanup:%s ,(char*)arg);return(void*)0;void*thr_fn1(void*arg).printf(thread1start );pthread_cleanup_push(clean,thread1firsthandler);pthread_cleanup_push(clean,thread1se
22、condhadler);printf(thread1pushcomplete );if(arg).return(void*)1);pthread_cleanup_pop(0);pthread_cleanup_pop(0);return(void*)1;void*thr_fn2(void*arg).printf(thread2start );pthread_cleanup_push(clean,thread2firsthandler);pthread_cleanup_push(clean,thread2secondhandler);printf(thread2pushcomplete );if(
23、arg).pthread_exit(void*)2);pthread_cleanup_pop(0);pthread_cleanup_pop(0);pthread_exit(void*)2);intmain(void).interr;pthread_ttid1,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(thread1exitcode%d ,(int)tret);err=pthread_join(tid2,&tret);if(err!=0).printf(error. );return-1; gcc-Wall-lpthreadthread_clean.cprintf(thread2exitcode%d ,(int)tret);exit(0);
限制150内