第七章 同步与进程间的通信.ppt
《第七章 同步与进程间的通信.ppt》由会员分享,可在线阅读,更多相关《第七章 同步与进程间的通信.ppt(64页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第七章 同步及进程间通信线程同步进程同步进程间通信7.1 线程同步(1)线程同步基础线程同步基础l由于同一进程可包括多个线程,这些线程又共享相同由于同一进程可包括多个线程,这些线程又共享相同的内存空间,不同的线程可以存取相同的全局变量、的内存空间,不同的线程可以存取相同的全局变量、相同的堆数据和文件描述符等。相同的堆数据和文件描述符等。l对于多线程对于多线程非共享数据非共享数据,考虑服务器的安全性问题,考虑服务器的安全性问题,可采用可采用线程专用数据线程专用数据TSD等方法解决。等方法解决。l对于多线程对于多线程共享共享数据和进程资源时必须使用数据和进程资源时必须使用同步机制同步机制。例如:例
2、如:struct employee int id;char name10;若两个线程同时修改一个结构,就可能造成数据的不若两个线程同时修改一个结构,就可能造成数据的不一致性,必须通过同步机制予以控制。一致性,必须通过同步机制予以控制。7.1 线程同步(2)互斥锁概念互斥锁概念互斥锁是提供线程同步的一种机制,是一种锁,用以保护线程互斥锁是提供线程同步的一种机制,是一种锁,用以保护线程代码中共享数据结构的完整性,其特点为:代码中共享数据结构的完整性,其特点为:l对互斥锁的操作(加锁对互斥锁的操作(加锁/解锁)是原子操作,操作系统保证同解锁)是原子操作,操作系统保证同时只有一个线程能成功完成对一个互
3、斥锁的加锁操作。时只有一个线程能成功完成对一个互斥锁的加锁操作。l若一个线程已经对某一互斥锁进行了加锁,其他线程只有等若一个线程已经对某一互斥锁进行了加锁,其他线程只有等待该互斥锁被解锁后,才能完成加锁操作。待该互斥锁被解锁后,才能完成加锁操作。l若一个线程已经对某一加锁的互斥锁进行了加锁操作,该线若一个线程已经对某一加锁的互斥锁进行了加锁操作,该线程被挂起,待该互斥锁被解锁后,该线程被唤醒并完成加锁程被挂起,待该互斥锁被解锁后,该线程被唤醒并完成加锁操作。操作。注意:注意:可使用以下伪代码实现数据完整性:可使用以下伪代码实现数据完整性:加锁互斥锁加锁互斥锁 (修改共享变量)(修改共享变量)解
4、锁互斥锁解锁互斥锁7.1 线程同步(3)互斥锁的初始化和消除互斥锁的初始化和消除使用互斥锁前,必须对其进行初始化;不用时,应撤消它使用互斥锁前,必须对其进行初始化;不用时,应撤消它l静态初始化方法静态初始化方法pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;l动态初始化方法动态初始化方法#include int pthread_mutex_init(pthread_mutex_t*mutex,const pthread_mutexattr_t*attr);成功返回成功返回0,否则返回错误码,否则返回错误码l撤消互斥锁(若动态)撤消互斥锁(若动态)
5、int pthread_mutex_destroy(pthread_mutex_t*mutex);成功返回成功返回0,否则返回错误码,否则返回错误码互斥锁互斥锁指向互斥锁指向互斥锁互斥锁属性,互斥锁属性,一般为一般为NULL7.1 线程同步(4)加锁和解锁互斥锁加锁和解锁互斥锁#include l加锁函数加锁函数pthread_mutex_lock()int pthread_mutex_lock(pthread_mutex_t*mutex);成功返回成功返回0,否则返回错误码,否则返回错误码l加锁函数加锁函数pthread_mutex_trylock()int pthread_mutex_tr
6、ylock(pthread_mutex_t*mutex);与与pthread_mutex_lock()函数最大区别是:当试图锁定一个已函数最大区别是:当试图锁定一个已被其他线程锁定的互斥锁时不阻塞,返回非零被其他线程锁定的互斥锁时不阻塞,返回非零EBUSY值值.l解锁函数解锁函数pthread_mutex_unlock()int pthread_mutex_unlock(pthread_mutex_t*mutex);成功返回成功返回0,否则返回错误码,否则返回错误码.7.1 线程同步(5)典型代码典型代码 int rc;rc=pthread_mutex_lock(&a_mutex);/*加锁操
7、作加锁操作*/if(rc)cout“pthread_mutex_lock error”;pthread_exit(NULL);/*关键代码关键代码*/rc=pthread_mutex_unlock(&a_mutex);/*解锁操作解锁操作*/if(rc)cout“pthread_mutex_unlock error”;pthread_exit(NULL);7.1 线程同步(6)实例实例程序名称:程序名称:mutex.cpp功能描述功能描述:使用互斥锁。该实例包含三个线程,第使用互斥锁。该实例包含三个线程,第1个线程反复将个线程反复将雇员雇员1的记录的记录(employee1)拷入拷入winne
8、r记录中,第记录中,第2个线程反个线程反复将雇员复将雇员2的记录的记录(employee2)拷入拷入winner记录中,第记录中,第3个线个线程(主线程)检查程(主线程)检查winner记录中的数据是否完整。记录中的数据是否完整。运行结果:运行结果:$./mutex Employees contents was always consistent结果分析结果分析:若去掉加锁和解锁的程序行,会出现数据的不一致。若去掉加锁和解锁的程序行,会出现数据的不一致。结果表明在多线程环境下,互斥锁可以保护共享数据的完整性结果表明在多线程环境下,互斥锁可以保护共享数据的完整性7.2 进程同步(1)父子进程关系
9、父子进程关系l父进程调用父进程调用fork()创建子进程创建子进程l子进程终止向父进程发信号子进程终止向父进程发信号SIGCHLD进程标识与进程组进程标识与进程组l用用getpid()获取本进程的获取本进程的ID号号l用用getppid()获取其父进程的获取其父进程的ID号号l用用getpgrp()获取进程组的获取进程组的ID号号(sys/types.h,unistd.h)l用用int setpgid(pid_t pid,pid_t pgid)可以将一个进程可以将一个进程加入到一个进程组中。加入到一个进程组中。7.2 进程同步(2)进程间的通信进程间的通信l低级通信:包括用低级通信:包括用原语
10、原语sleepsleep、wakeupwakeup和和软中断软中断信信号方式。号方式。l管道通信:使用管道通信:使用管道管道文件,传递进程间信息(有名文件,传递进程间信息(有名和无名管道)。和无名管道)。lIPCIPC通信:使用通信:使用消息消息机制用于进程间大量的数据传机制用于进程间大量的数据传送。送。7.2 进程同步(3)信号处理信号处理l信号信号是软中断,信号有名称是软中断,信号有名称(SIG开头开头)和对应的编号和对应的编号P167l产生信号产生信号的方法有多种,如的方法有多种,如C、硬件异常、硬件异常、kill、设置定时器设置定时器等。等。l处理信号处理信号由系统完成,通过函数调用完
11、成三个特定动作之一:由系统完成,通过函数调用完成三个特定动作之一:l忽略信号忽略信号SIG_IGNl捕获信号(自定义函数)捕获信号(自定义函数)l执行默认动作执行默认动作SIG_DFL等等l可能会返回错误值可能会返回错误值errno注意注意:SIGKILL和和SIGSTOP信号不能忽略,它们是超级用户提供信号不能忽略,它们是超级用户提供杀死和停止进程的必要方法。杀死和停止进程的必要方法。POSIX定义的常用信号定义的常用信号信号信号 动作动作 注释注释SIGINT A 来自键盘的中断信号来自键盘的中断信号SIGQUIT A 来自键盘的退出信号来自键盘的退出信号SIGABRT C 由由abort
12、发送终止信号发送终止信号SIGKILL AEF 由由KILL杀死进程信号杀死进程信号SIGALRM A 由由alarn时钟中断信号时钟中断信号SIGUSER1 A 用户自定义信号用户自定义信号1SIGUSER2 A 用户自定义信号用户自定义信号2SIGCHLD B 子进程终止信号子进程终止信号 SIGSTOP DEF 停止进程停止进程A表示默认动作是终止进程表示默认动作是终止进程B表示默认动作是忽略信号表示默认动作是忽略信号C表示默认动作是系统内核转储表示默认动作是系统内核转储D表示默认动作是停止进程表示默认动作是停止进程E表示信号不能被捕获表示信号不能被捕获F表示信号不能被忽略表示信号不能被
13、忽略7.2 进程同步(4)信号的产生信号的产生常用系统函数有:常用系统函数有:lkill()向其他进程发送信号向其他进程发送信号lraise()向当前进程发送信号向当前进程发送信号lalarm()设置定时器,定时器到期,产生设置定时器,定时器到期,产生 SIGALRM信号信号lsetitimer()设置定时器,比设置定时器,比alarm()精度高精度高labort()向进程发送向进程发送SIGABRT信号,导致程序信号,导致程序 非正常终止非正常终止7.2 进程同步(5)kill()与与raise()#include#include int kill(pid_t pid,int sig);in
14、t raise(int sig);其中:其中:pid0,信号信号sig发送到进程号为发送到进程号为pid的进程;的进程;pid=0,信号发送到与发送进程处于同一进程组的进程;信号发送到与发送进程处于同一进程组的进程;pid-1,信号发送到进程组信号发送到进程组ID为为-pid的所有进程;的所有进程;pid=-1,未指定。未指定。sig=0,不发送任何信号,但进行错误检查,用于检测是否有不发送任何信号,但进行错误检查,用于检测是否有向指定进程发送信号的许可。向指定进程发送信号的许可。注意:注意:raise(sig)等价于等价于kill(getpid(),sig)7.2 进程同步(6)alarm(
15、)#include unsigned int alarm(unsigned int seconds);其中:其中:seconds为为定时器设置的秒数,到期后产生定时器设置的秒数,到期后产生SIGALRM信号。信号。getitimer()与与setitimer()#include int getitimer(int which,struct itimerval*value);int setitimer(int which,const struct itimerval*value,struct itimerval*ovalue);abort()#include void abort(void);7
16、.2 进程同步(7)信号的捕获信号的捕获调用格式:调用格式:#include#include intint sig,funcsig,func(),(*(),(*funcpfuncp)();)();funcpfuncp=signal(sig,funcsignal(sig,func););其中:其中:sigsig为接收信号类型为接收信号类型(SIGKILLSIGKILL不能被捕获和处理不能被捕获和处理)funcfunc()()指定进程接收到信号后执行的动作指定进程接收到信号后执行的动作 (1 1)SIG_IGN SIG_IGN 忽略接收的信号忽略接收的信号 (2 2)SIG_DFL SIG_DFL
17、 恢复对信号的缺省处理恢复对信号的缺省处理 (3 3)一个返回值为整数的函数的地址,即函数名)一个返回值为整数的函数的地址,即函数名在在signal.hsignal.h中,有:中,有:define SIG_DFL(define SIG_DFL(intint(*)0(*)0 define SIG_IGN(define SIG_IGN(intint(*)1(*)17.2 进程同步(8)练习:练习:1.编写一个程序,循环编写一个程序,循环100次,输出每个次,输出每个i值,执行期间,值,执行期间,c试图终试图终止运行,如何对止运行,如何对SIGINT信号忽略。(信号忽略。(pp5.cpp)观察观察:
18、(1)不用不用c中断中断,输出结果为何输出结果为何?(2)第二次循环后第二次循环后,按下按下c键结果如何键结果如何?(3)第二、三次循环后第二、三次循环后,都按下都按下c键呢?键呢?(4)将原注释行注释标记去掉,最后一条语句加注释观察变化。将原注释行注释标记去掉,最后一条语句加注释观察变化。运行结果分别为运行结果分别为:(1)sleep call#1 sleep call#2 sleep call#3 sleep call#4 Exiting.(2)sleep call#1 sleep call#2 CATCHINT:signo=2 CATCHINT,returning.sleep call#
19、3 sleep call#4 Exiting.(3)sleep call#1(3)sleep call#1 sleep call#2 sleep call#2 CATCHINT:signoCATCHINT:signo=2=2 CATCHINT,returning.CATCHINT,returning.sleep call#3 sleep call#3 CATCHINT:signoCATCHINT:signo=2=2 CATCHINT,returning.CATCHINT,returning.sleep call#4 sleep call#4 Exiting.Exiting.(4)sleep c
20、all#1(4)sleep call#1 sleep call#2 sleep call#2 CATCHINT:signoCATCHINT:signo=2=2 CATCHINT,returning.CATCHINT,returning.sleep call#3 sleep call#3 sleep call#4 sleep call#4 Exiting.Exiting.只捕获第一次中断只捕获第一次中断只捕获第一次中断只捕获第一次中断,以后的忽略以后的忽略以后的忽略以后的忽略7.2 进程同步(9)7.2 进程同步(10)2.父子进程互发自定义信号父子进程互发自定义信号(pp6.cpp)运行结果为
21、运行结果为:Parent caught signal 10#1Child caught signal 10#1Parent caught signal 10#2Child caught signal 10#2Parent caught signal 10#3Child caught signal 10#3 注意注意:可以用类似的方法获得不同的信号名称与对应的编号可以用类似的方法获得不同的信号名称与对应的编号直到C终止互发信号7.2 进程同步(11)设置信号集设置信号集(略略)int sigemptyset(sigset_t*set);初始化信号集合初始化信号集合,设置为空设置为空int sig
22、fillset(sigset_t*set);初始化信号集合初始化信号集合,设置为所有信号集设置为所有信号集合合int sigaddset(sigset_t*set,int signo);将信号将信号signo加入到加入到set中中int sigdelset(sigset_t*set,int signo);将信号将信号signo从从set中中删删除除int sigismember(sigset_t*set,int signo);查信号查信号signo是否在是否在set中中int sigprocmask(int how,const sigset_t*set,sigset_t*oset);将指定的信
23、号集合将指定的信号集合set加入到进程的信号阻塞集合中加入到进程的信号阻塞集合中其中其中how为:为:SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中增加一个信号集合到当前进程的阻塞集合之中 SIG_UNBLOCK:从当前进程的阻塞集合之中删除一个信号集合从当前进程的阻塞集合之中删除一个信号集合 SIG_SETMASK:将当前的信号集合设置为信号阻塞集合将当前的信号集合设置为信号阻塞集合7.2 进程同步(12)信号的处理信号的处理(略略)在某个信号出现时,进程通过在某个信号出现时,进程通过sigaction()函数调用要求系统进行某函数调用要求系统进行某种操作,成功返回种操作,成功
24、返回0,否则,否则-1。#include int sigaction(int signum,struct sigaction*act,struct sigaction*oldact);其中:其中:signum为信号为信号,act结构指针,结构指针,oldact指向以前设置指向以前设置struct sigaction /用于描述相应的操作用于描述相应的操作void(*sa_handler)(int);/*指定信号动作,如指定信号动作,如 SIG_DFL、SIG_IGN或用户定义函数或用户定义函数*/void(*sa_sigaction)(int,siginfo_t*,void*);/*一般不用一
25、般不用*/sigset_t sa_mask;/*处理处理signum信号时,应阻塞的信号集信号时,应阻塞的信号集*/int sa_flags;/*指定信号处理过程中的行为指定信号处理过程中的行为P170,常设为常设为0*/void(*sa_restorer)(void);/*不用不用*/7.2 进程同步(13)其他信号函数其他信号函数lpause()暂停调用进程并等待信号暂停调用进程并等待信号#include int pause(void);lsleep(secend)使进程休眠指定的秒数使进程休眠指定的秒数#include unsigned int sleep(unsigned int se
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第七章 同步与进程间的通信 第七 同步 进程 通信
限制150内