【文档说明】操作系统-Linux环境下C语言编程课件.ppt,共(81)页,210.500 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44615.html
以下为本文档部分文字说明:
Linux环境下C语言编程2007年10月GCC简介C语言和LinuxLINUX中包含了很多软件开发工具。它们中的很多是用于C和C++应用程序开发的。C是一种能在UNIX的早期就被广泛使用的通用编程语言。它最早是由Bell实验室的
DennisRitchie为了UNIX的辅助开发而写的,从此C就成为世界上使用最广泛的计算机语言。C能在编程领域里得到如此广泛支持的原因有:(1)它是一种非常通用的语言,并且它的语法和函数库在不同的平台上都是统一的,对开发者非常有吸引力;(2)用C写的程序执行速度很快;(3)C是所有版本U
NIX上的系统语言;GNUC编译器-gccLINUX上可用的C编译器是GNUC编译器,它建立在自由软件基金会编程许可证的基础上,因此可以自由发布。LINUX上的GNUC编译器(gcc)是一个全功能的ANCIC兼容编译器,而一般UNIX(如SCOUNIX)用的编译器是CC。
文件后缀Gcc编译文件gcc指令的一般格式为:gcc[选项]要编译的文件[选项][目标文件]其中,目标文件可缺省,gcc默认生成可执行的文件为:编译文件.out如:gcc–ohellohello.cGCC编译流程预处理(Preprocessing)编译(Compiling)汇编
(Assembling)连接(Linking)hello.c#include<stdio.h>intmain(){printf("Hello!Thisisourworld!\n");return0;}预处理阶段在该阶段,编译器将上述代码中的stdio
.h编译进来,并且用户可以使用Gcc的选项“-E”进行查看,该选项的作用是让Gcc在预处理结束后停止编译过程。编译命令:gcc–Ehello.c–ohello.igcc进行了预处理,它把“stdio.
h”的内容插入到hello.i文件中。编译阶段在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。编译命
令:gcc–Shello.i–ohello.s汇编阶段汇编阶段是把编译阶段生成的“.s”文件转成目标文件,在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。编译命令:gcc–chello.s–ohel
lo.o链接阶段系统把”stdio.h”中的实现都在libc.so.6库文件中,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数“printf”了。编
译命令:gcchello.o–ohello运行程序[root@localhost]#./helloHello!Thisisourworld!Gcc常用编译选项Gdb调试器Gdb调试器是一款GNU开发组
织并发布的UNIX/Linux下的程序调试工具。虽然,它没有图形化的友好界面,但是它强大的功能也足以与微软的VC工具等媲美。能监视程序中变量的值能设置断点以使程序在指定的代码行上停止执行能一行行执行代码基本gdb命令命令描述file装入想要调试的可执行文件.ki
ll终止正在调试的程序.list列出产生执行文件的源代码的一部分.next执行一行源代码但不进入函数内部.step执行一行源代码而且进入函数内部.run执行当前被调试的程序quit终止gdbwatch使你能监视一个变量的值而不管它何时被改变.print显示表达式的值bre
ak在代码里设置断点,这将使程序执行到这里时被挂起.make能不退出gdb就可以重新产生可执行文件.shell能不离开gdb就执行UNIXshell命令.一个调试的例子-gdbtest.c#include<stdio.h>int
sum(intm);intmain(){inti,n=0;sum(50);for(i=1;i<=50;i++){n+=i;}printf("Thesumof1-50is%d\n",n);}intsum(intm){
inti,n=0;for(i=1;i<=m;i++)n+=i;printf("Thesumof1-mis%d\n",n);}编译程序使用Gcc对test.c进行编译,注意一定要加上选项“-g”,这样编译出的可执行代码中才包含调试信息,否则之后Gdb无法载入该可执行文件。gc
c-ggdbtest.c-ogdbtest用Gdb调试1开始调试:gdbgdbtest……(gdb)2查看文件命令:l列出带有行号的代码用Gdb调试(续)3设置断点设置断点是调试程序中是一个非常重要的手段,它可以使程序到一
定位置暂停它的运行。因此,程序员在该位置处可以方便地查看变量的值、堆栈情况等,从而找出代码的症结所在。在Gdb中设置断点非常简单,只需在“b”后加入对应的行号即可。如:(Gdb)b6Breakpoint1at0x804846d:filegdbtest.c
,line6.用Gdb调试(续)查看断点情况:键入“infob”来查看设置断点情况:(Gdb)infobNumTypeDispEnbAddressWhat1breakpointkeepy0x0804846dinmainattest.c:64运行代码:
Gdb默认从首行开始运行代码,可键入“r”(run)即可(若想从程序中指定行开始运行,可在r后面加上行号)。(Gdb)rStartingprogram:/root/workplace/Gdb/testReadingsymbolsfromsharedob
jectreadfromtargetmemory...done.LoadedsystemsuppliedDSOat0x5fb000Breakpoint1,main()attest.c:66sum(50);用Gdb调试(续)5查看变量值在Gdb中只需键入“p”+
变量值即可,如下所示:(Gdb)pn$1=0(Gdb)pi$2=134518440用Gdb调试(续)6单步运行单步运行可以使用命令“n”(next)或“s”(step),它们之间的区别在于:若有函数调用的时候,“s”会进入该函
数而“n”不会进入该函数。(Gdb)nThesumof1-mis12757for(i=1;i<=50;i++)(Gdb)ssum(m=50)attest.c:1616inti,n=0;用Gdb调试(续)7恢复程序运行在查看完所需变量及堆栈情况后,就可以使用
命令“c”(continue)恢复程序的正常运行了。这时,它会把剩余还未执行的程序执行完,并显示剩余程序中的执行结果。(Gdb)cContinuing.Thesumof1-50is:1275Programe
xitedwithcode031.Linux多线程技术POSIX线程库Pthreads使用fork()创建进程代价昂贵进程间通信方式较复杂操作系统在实现进程间的切换比线程切换更费时使用pthreads库创建线程创建进程比创建线程更快线程间的通信方式更容操作系
统对线程的切换比对进程的切换更容易和快速线程的创建#include<pthread.h>intpthread_create(pthread_t*thread,pthread_attr_t*attr,void*(*start_routine)(void*),void*arg);第一个参数为指向线程标
识符的指针。第二个参数用来设置线程属性。第三个参数是线程运行函数的起始地址。最后一个参数是运行函数的参数。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EI
NVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。一个简单例子#include<stdio.h>#include<pthread.h>#include<string.h>#include<sys/types.h>#include<un
istd.h>pthread_tntid;void*thr_fn(void*arg){printids("newthread:");return((void*)0);}intmain(){interr;err=pthread_creat
e(&ntid,NULL,thr_fn,NULL);if(err!=0){printf("can'tcreatethread:%s\n",strerror(err));return1;}sleep(1);return0;}编译多线程程序gcc-omypthread-lpthre
admypthread.c线程的退出调用pthread_exit()结束线程执行voidpthread_exit(void*retval);让线程处理程序返回使用pthread_cancel()函数终止其他线程的
执行intpthread_cancel(pthread_tthread);向线程t发送取消请求,默认情况下线程thread自己调用pthread_exit(PTHREAD_CANCELED),等待线程结束使用pthread_join()函数等待被创建的线程结束pth
read_join()函数会挂起创建线程的线程的执行直到等待到想要等待的子线程函数原型:intpthread_join(pthread_tth,void**thread_return);线程的分离主线程可以不断地创建子线程
子线程本身自己有自我回收内存资源的能力函数原型:intpthread_detach(pthread_tth);pthread_detach()和pthread_join()一般情况下不能同时使用获得当前
线程的标志pthread_tpthread_self(void);本函数返回本线程的标识符。在LinuxThreads中,每个线程都用一个pthread_descr结构来描述,其中包含了线程状态、线程ID等所有需要的数据结
构,此函数的实现就是在线程栈帧中找到本线程的pthread_descr结构,然后返回其中的p_tid项。一个例子#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<pthread.h>#d
efineTHREAD_NUMBER2intretval_hello1=2,retval_hello2=3;void*hello1(void*arg){char*hello_str=(char*)arg;sleep(1);printf("%s\n",hello
_str);pthread_exit(&retval_hello1);}void*hello2(void*arg){char*hello_str=(char*)arg;sleep(2);printf("%s\n",hello_str);pthread_exit(&
retval_hello2);}intmain(intargc,char*argv[]){inti;intret_val;int*retval_hello[2];pthread_tpt[THREAD_NUMBER];constchar*arg[THREAD_NUMBER];a
rg[0]="helloworldfromthread1";arg[1]="helloworldfromthread2";printf("Begintocreatethreads...\n");ret_val=pthread_create(&pt[0],NULL,hello1,(void*)
arg[0]);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}ret_val=pthread_create(&pt[1],NULL,hello2,(void*)arg[1]);if(ret_va
l!=0){printf("pthread_createerror!\n");exit(1);}printf("Begintowaitforthreads...\n");for(i=0;i<THREAD_NUMBER;i++){r
et_val=pthread_join(pt[i],(void**)&retval_hello[i]);if(ret_val!=0){printf("pthread_joinerror!\n");exit(1);}
else{printf("returnvalueis%d\n",*retval_hello[i]);}}printf("Now,themainthreadreturns.\n");return0;}线程属性的初始化和撤销线程初始化:intpthread_attr_init(pt
hread_attr_t*attr)初始化线程属性对象attr,并用默认值填充线程撤销:intpthread_attr_destroy(pthread_attr_t*attr)销毁线程属性对象attr。*修改
线程属性对象attr只有在线程创建前有效,在线程创建后修改对当前线程不起作用。*返回0成功,否则失败。pthread_attr_t定义pthread_attr_t定义:typedefstruct__pthread_attr_s{int__detachstate;int__s
chedpolicy;struct__sched_param__schedparam;int__inheritsched;int__scope;size_t__guardsize;int__stackaddr_set;void*__stackaddr;size_t__stack
size;}pthread_attr_t;线程的属性属性名意义detachstate选择被创建的线程是处于可加入的状态还是分离状态schedpolicy为被创建的线程选择调度策略。schedparam为被创建的线程选择调度参数。inheritsche
d选择对新创建的线程的调度策略和调度参数是否被schedpolicy和schedparam属性决定或者是通过父线程继承而得到的scope为选择被创建的线程调度竞争范围。线程的属性(续)detachstatePTHREAD_CREATE_JOINABLEPTHREAD_CREATE_D
ETACHED默认:PTHREAD_CREATE_JOINABLE控制创建的线程是joinable态还是detached态schedpolicySCHED_OTHER(regular,non-realtimescheduling)SCHED
_RR(realtime,round-robin)SCHED_FIFO(realtime,first-infirst-out)默认:SCHED_OTHER优先级类别Schedparam默认:0线程优先级参数如果schedpolicy的值为SCHED_OTH
ER,schedpolicy此属性无关紧要线程创建后可修改此属性inheritschedPTHREAD_EXPLICIT_SCHEDPTHREAD_INHERIT_SCHED默认:PTHREAD_EXPLICIT_SCHED说明此线程优先级是否继承于
父线程还是通过上面两个属性确定scopePTHREAD_SCOPE_SYSTEMPTHREAD_SCOPE_PROCESS默认:PTHREAD_SCOPE_SYSTEM设置线程绑定状态部分Linux不支持PTHREAD_SCO
PE_PROCESS,需要查看man相关函数-分离状态设置分离状态:pthread_attr_setdetachstateintpthread_attr_setdetachstate(pthread_attr_t*attr,intdetac
hstate);返回值:函数成功返回0;任何其他返回值都表示错误设置分离状态。参数detachstate的值为:PTHREAD_CREATE_DETACHED、PTHREAD_CREATE_JOINABLE。获取分离状态:pthread_attr_getd
etachstateintpthread_attr_getdetachstate(pthread_attr_t*attr,int*detachstate);返回值:函数成功返回0;任何其他返回值都表示错误取线程分
离状态:分离的或是非分离的。相关函数-调度策略设置调度策略:pthread_attr_setschedpolicyintpthread_attr_setschedpolicy(pthread_attr_t*tattr,intpolicy);返回值:函数成功返回0;任何其他返回
值都表示错误。POSIX标准定义的调度策略有:SCHED_FIFO(先入先出)、SCHED_RR(循环)、SCHED_OTHER(由不同版本的POSIX线程库定义的缺省调度策略)。获取调度策略:pthread_attr_getschedpolicyintpthread_attr_ge
tschedpolicy(pthread_attr_t*tattr,int*policy);返回值:函数成功返回0;任何其他返回值都表示错误。相关函数-调度参数设置调度参数:pthread_att
r_setschedparamintpthread_attr_setschedparam(pthread_attr_t*tattr,conststructsched_param*param);返回值:函数成功返回0;任何其他返回值都表示错误。属性对
象的调度参数定义在param结构中;在这个结构中只定义了优先级priority成员。新创建线程的优先级由属性对象中param结构的priority参数指定。有两种方式可以修改线程的优先级。可以在创建子线程前设置属性对象的优先级参数;也可以先修改父线程的
优先级,然后创建子线程。sched_param结构中有可能存放着其他一些调度信息。所以在修改线程属性对象的调度参数前先取现有的调度参数是良好的习惯。一段合理的代码应该是这样的:先取线程属性对象中现有的调度参数,对取出的调度参数进行操作,再用修改过的
调度参数重置线程属性对象。获取调度参数:pthread_attr_getschedparamintpthread_attr_getschedparam(pthread_attr_t*tattr,consts
tructsched_param*param);返回值:函数成功返回0;任何其他返回值都表示错误。相关函数-域设置域:pthread_attr_setscopeintpthread_attr_setscope(pthread_attr_t*tatt
r,intscope);返回值:函数成功返回0;任何其他返回值都表示错误。指定将来创建的线程是绑定(PTHREAD_SCOPE_SYSTEM)的还是非绑定的(PTHREAD_SCOPE_PROCESS)。
在一个进程中可以同时有这两种不同类型的线程。获取域:pthread_attr_getscopeintpthread_attr_getscope(pthread_attr_t*tattr,int*scope);返回值:函数成功返回0;任何其他返回值都表示错误。例子:threadattr#i
nclude<stdio.h>#include<stdlib.h>#include<pthread.h>void*sum_val(void*arg){intsum=0;inti;intcoun
t=*(int*)arg;for(i=0;i<count;i++)sum=sum+i;printf("sumis%d\n",sum);pthread_exit(0);}例子:threadattr(续)intmain(i
ntargc,char*argv[]){pthread_tpt;intcount=10;intret_val;pthread_attr_tattr;structsched_paramsp;sp._sc
hed_priority=2;ret_val=pthread_attr_init(&attr);if(ret_val!=0){printf("pthread_attr_initerror!\n");exit(1);}例子:threada
ttr(续)ret_val=pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);if(ret_val!=0){printf("pthread
_attr_setdetachstateerror!\n");exit(1);}ret_val=pthread_attr_setschedpolicy(&attr,SCHED_RR);if(ret
_val!=0){printf("pthread_attr_setschedpolicyerror!\n");exit(1);}ret_val=pthread_attr_setschedparam(&attr,&sp);if(ret_val!
=0){printf("pthread_attr_setschedparamerror!\n");exit(1);}例子:threadattr(续)ret_val=pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED);if
(ret_val!=0){printf("pthread_attr_setinheritschederror!\n");exit(1);}ret_val=pthread_attr_setsco
pe(&attr,PTHREAD_SCOPE_SYSTEM);if(ret_val!=0){printf("pthread_attr_setscopeerror!\n");exit(1);}ret_val=pthread_create(&pt,NULL,s
um_val,(void*)&count);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}pthread_attr_destroy(&attr)
;sleep(5);return0;}Linux下线程的同步和互斥mutexMutex:互斥设备(MUTualExclusiondevice)mutex有如下特性:原子性:对mutex的加锁和解
锁操作是原子的单一性:拥有mutex的线程除非释放mutex,否则其他线程不能拥有此mutex非忙等待:等待mutex的线程处于等待状态,直到要等待的mutex处于未加锁状态,这时操作系统负责唤醒等待
此mutex的线程Mutex类型在POSIX线程库中,存在三中类型的mutex:快速(fast)mutex递归(recursive)mutex:获得锁的线程可以多次加锁错误检测(errorche
cking)mutex:锁定时返回错误与mutex相关函数intpthread_mutex_init(pthread_mutex_t*mutex,constpthread_mutexattr_t*mutexattr);intpthread_mu
tex_lock(pthread_mutex_t*mutex);intpthread_mutex_trylock(pthread_mutex_t*mutex);intpthread_mutex_unlock(pthread_mutex_t*mutex);intpth
read_mutex_destroy(pthread_mutex_t*mutex);初始化互斥锁intpthread_mutex_init(pthread_mutex_t*mp,constpthread_mutexattr_t*mattr);成功完成之后会返回零。
其他任何返回值都表示出现了错误。例子#include<pthread.h>pthread_mutex_tmp=PTHREAD_MUTEX_INITIALIZER;pthread_mutexattr_tmattr;intret;/*ini
tializeamutextoitsdefaultvalue*/ret=pthread_mutex_init(&mp,NULL);锁定互斥锁intpthread_mutex_lock(pthread_mutex_t*mutex);在成功完成之后会返回零。其他任何返回值都表示出现了错误。
当返回时,该互斥锁已被锁定。调用线程是该互斥锁的属主。互斥锁类型为快速锁:如果该互斥锁已被另一个线程锁定和拥有,则调用线程将阻塞,直到该互斥锁变为可用为止。互斥锁类型为错误锁:则会提供错误检查。如果某个线程尝试重新锁定的互斥锁已经由该
线程锁定,则将返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。互斥锁类型为递归锁:则该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,锁定计数会设置为1。线程每重新锁定该互斥锁一次,锁定计数就增加1。线程每解除锁定该互斥锁一
次,锁定计数就减小1。锁定计数达到0时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。解除锁定互斥锁intpthread_mutex_unlock(pthread_mutex_t*mutex);释放引
用的互斥锁对象。互斥锁的释放方式取决于互斥锁的类型属性。在成功完成之后会返回零。其他任何返回值都表示出现了错误。使用非阻塞互斥锁锁定intpthread_mutex_trylock(pthread_mutex_t*mutex);在成功完成之后会返回零。其他任何返回值都表示出现了错误。是p
thread_mutex_tlock的非阻塞版本。如果所引用的互斥对象当前被任何线程(包括当前线程)锁定,则将立即返回该调用。否则,该互斥锁将处于锁定状态,调用线程是其属主。销毁互斥锁intpthread_mutex_destroy(pthread_mut
ex_t*mp);在成功完成之后会返回零。其他任何返回值都表示出现了错误。使用MUTEX的简单代码pthread_mutex_tmylock;mylock=PTHREAD_MUTEX_INITIALIZER;pthrea
d_mutex_lock(&mylock);Dosomething….pthread_mutex_unlock(&mylock);Mutex例子#include<stdio.h>#include<stdlib.h>
#include<pthread.h>#include<errno.h>#defineTHREAD_NUMBER10staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIA
LIZER;intsum=0;void*inc(void*arg){inti=(*(int*)arg);pthread_mutex_lock(&mutex);sum=sum+i;pthread_mutex_unlock(&mutex);returnNU
LL;}Mutex例子(续)intmain(intargc,char*argv[]){pthread_tpt[THREAD_NUMBER];inti;intarg[THREAD_NUMBER];for(i=0;i<THREAD_NUMBER;i++){arg[i]=i;
if(pthread_create(&pt[i],NULL,inc,(void*)&arg[i])!=0){printf("pthread_createerror\n");exit(1);}}Mutex例子(续)for(i=0;i<THREAD_NUMBER;i++
)if(pthread_join(pt[i],NULL)!=0){printf("pthread_joinerror\n");exit(1);}printf("sumis%d\n",sum);pthread_mutex_destroy(&mutex);return0
;}条件变量可以使得一个线程在执行过程中,因满足某个条件而发出信号通知另一个线程。而另一个线程可以处于挂起状态,等待某个条件的满足后,才继续执行。条件变量必须和mutex一起使用来避免竞争。条件
变量相关的操作函数pthread_cond_tcond=PTHREAD_COND_INITIALIZER;intpthread_cond_init(pthread_cond_t*cond,pthread_con
dattr_t*cond_attr);intpthread_cond_signal(pthread_cond_t*cond);intpthread_cond_broadcast(pthread_cond_t*cond);intpthread_cond_wait(pthread_cond
_t*cond,pthread_mutex_t*mutex);intpthread_cond_timedwait(pthread_cond_t*cond,pthread_mutex_t*mutex,conststructtimespec*abstime);intpthread_con
d_destroy(pthread_cond_t*cond);在成功完成之后会返回零。其他任何返回值都表示出现了错误。初始化条件变量intpthread_cond_init(pthread_cond_t*cv,constpthread_condattr_t*cattr);使用PTHREA
D_COND_INITIALIZER宏可以将以静态方式定义的条件变量初始化为其缺省属性。PTHREAD_COND_INITIALIZER宏与动态分配具有null属性的pthread_cond_init等效,但是不进行错误检查
。多个线程决不能同时初始化或重新初始化同一个条件变量。如果要重新初始化或销毁某个条件变量,则应用程序必须确保该条件变量未被使用。基于条件变量阻塞intpthread_cond_wait(pthread_cond_t*cond,pthread_mutex_t*mutex
);阻塞的线程可以通过pthread_cond_signal或pthread_cond_broadcast唤醒,也可以在信号传送将其中断时唤醒。该条件获得信号之前,该函数一直被阻塞。该函数会在被阻塞之
前以原子方式释放相关的互斥锁,并在返回之前以原子方式再次获取该互斥锁。通常,对条件表达式的评估是在互斥锁的保护下进行的。如果条件表达式为假,线程会基于条件变量阻塞。然后,当该线程更改条件值时,另一个线程会针对条件变
量发出信号。这种变化会导致所有等待该条件的线程解除阻塞并尝试再次获取互斥锁。必须重新测试导致等待的条件,然后才能从pthread_cond_wait处继续执行。唤醒的线程重新获取互斥锁并从pthread_cond_wait返回之前,条件可能会发生变化。等待线程可能并未真正唤醒。建议使用的测
试方法是,将条件检查编写为调用pthread_cond_wait的while循环:pthread_mutex_lock();while(condition_is_false)pthread_cond_wait();p
thread_mutex_unlock();解除阻塞一个线程intpthread_cond_signal(pthread_cond_t*cond);应在互斥锁的保护下修改相关条件,该互斥锁用于获得信号的条件变量中。否则,可能在
条件变量的测试和pthread_cond_wait阻塞之间修改该变量,这会导致无限期等待。在指定的时间之前阻塞intpthread_cond_timedwait(pthread_cond_t*cond,pthread_mute
x_t*mutex,conststructtimespec*abstime);每次返回时调用线程都会锁定并且拥有互斥锁,即使返回错误时也是如此。函数会一直阻塞,直到该条件获得信号,或者最后一个参数所指定的时间已过为止。解
除阻塞所有线程intpthread_cond_broadcast(pthread_cond_t*cond);使用pthread_cond_broadcast()可以解除阻塞所有这些线程。销毁条件变量状态
intpthread_cond_destroy(pthread_cond_t*cond);用pthread_cond_destroy()可以销毁与cond所指向的条件变量相关联的任何状态。例子1#include<stdio.h>#include<stdlib
.h>#include<unistd.h>#include<pthread.h>#defineTHREAD_NUMBER2staticpthread_cond_tcond=PTHREAD_COND_INITIALIZER;
staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;void*thread1(void*arg){pthread_mutex_lock(&mutex);printf(
"thread1lockedthemutex\n");printf("thread1iswaitingforconditionsignal...\n");pthread_cond_wait(&cond,&mutex);printf("thread1receive
dconditionsignal!\n");pthread_mutex_unlock(&mutex);printf("thread1unlockedthemutex\n");pthread_exit(0);}例子1(
续)void*thread2(void*arg){inti=0;structtimevalold,new;gettimeofday(&old);new=old;pthread_mutex_lock(&mutex);printf("th
read2lockedthemutex\n");while(new.tv_sec-old.tv_sec<5){sleep(1);gettimeofday(&new);i++;printf("thread2sleep%dseconds\n",i);}printf
("thread1callspthread_cond_signal...\n");pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);printf("thread2unlockedthem
utex\n");pthread_exit(0);}例子1(续)intmain(intargc,char*argv[]){inti;intret_val;pthread_tpt[THREAD_N
UMBER];ret_val=pthread_create(&pt[0],NULL,thread1,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}ret_val=pthread_create(&pt[1]
,NULL,thread2,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}例子1(续)for(i=0;i<THREAD_NUM
BER;i++){ret_val=pthread_join(pt[i],NULL);if(ret_val!=0){printf("pthread_joinerror!\n");exit(1);}}pthread_mutex_destroy(&mutex);pthread_co
nd_destroy(&cond);return0;}例子2……#defineTHREAD_NUMBER2staticpthread_cond_tcond=PTHREAD_COND_INITIALIZER;staticp
thread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;staticintx=0,y=0;void*thread1(void*arg){structtimevalnow;structtimespectimeout;intretcode;
pthread_mutex_lock(&mutex);gettimeofday(&now);timeout.tv_sec=now.tv_sec+5;timeout.tv_nsec=now.tv_use
c*1000;retcode=0;例子2(续)while(x>=y&&retcode!=ETIMEDOUT){retcode=pthread_cond_timedwait(&cond,&mutex,&timeout);}if(retcode==ETIMEDOUT){printf
("pthread_cond_timedwaittimeout!\n");}else{printf("thread1gotconditionsignal!\n");}pthread_mutex_unlock(&mutex);pthread_exit(0);
}例子2(续)void*thread2(void*arg){inti;for(i=0;i<5;i++){x=rand()%5;y=rand()%5;sleep(1);printf("xis%d,yis%d\n",x,y);if(x<y)break;}p
thread_mutex_lock(&mutex);if(x<y){pthread_cond_broadcast(&cond);}pthread_mutex_unlock(&mutex);p
thread_exit(0);}例子2(续)intmain(intargc,char*argv[]){inti;intret_val;pthread_tpt[THREAD_NUMBER];ret_val=pthread_create(&
pt[0],NULL,thread1,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}ret_val=pthread_create(&pt[1],NU
LL,thread2,NULL);if(ret_val!=0){printf("pthread_createerror!\n");exit(1);}例子2(续)for(i=0;i<THREAD_NUMBER;i++){ret_val=pthread_join(pt[i],NULL);
if(ret_val!=0){printf("pthread_joinerror!\n");exit(1);}}pthread_mutex_destroy(&mutex);pthread_cond_
destroy(&cond);return0;}