课程名称:网络程序设计6.ppt_第1页
课程名称:网络程序设计6.ppt_第2页
课程名称:网络程序设计6.ppt_第3页
课程名称:网络程序设计6.ppt_第4页
课程名称:网络程序设计6.ppt_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、课程名称:网络程序设计,主讲教师:胡亮 Email:,第6章 机内进程间通信,网络编程通常涉及多个进程之间相互作用,相互协调它们的活动。这一协调是通过进程间的某些主动或被动通信实现的。系统可以提供多种在一个节点上进程间通信方式,主要有信号(Signal)、管道(pipe)、命名管道(FIFOS)、消息队列(message queue)、信号灯(semaphore)、共享内存(shared memory)和内存映象(memory mapped file)以及UNIX域类型的套接字。,6.1 信号,信号是Unix系统中最原始的进程间同步和通信的工具,它实际上是发送给进程的“软件中断”,用于通知进程

2、在它的运行环境中发生了某件事情。当引起信号的事件发生了,相应的信号就产生了。而当进程获得基于信号的行为时,这个信号就释放了,从信号的产生到信号被释放这段时间,称为信号的生命期。从信号的产生到信号的释放之间,信号可能被阻塞。通常是进程在执行某项任务时,不希望被相应的信号中断,这时进程可以阻塞这些信号。当进程完成任务时,再清除对这些信号的屏蔽,进程通过设置屏蔽码来实现信号的屏蔽。在进程阻塞期间产生的信号,进程仍然会收到,只是直到进程清除屏蔽后信号才被释放。 信号类似于硬件中断,但没有优先级,也就是说,进程平等地对待所有的信号。对于同时发生的信号,一次只给进程一个信号,而没有特别的次序。,Linux

3、系统支持的信号,在Linux系统中,可以使用kill l来显示系统中支持的信号,这些信号主要有: SIGHUPSIGINTSIGQUITSIGILLSIGTRAPSIGIOT SIGBUSSIGFPESIGKILLSIGUSER1SIGSEGVSIGUSER2 SIGPIPESIGALRM SIGTERM SIGCHLDSIGCONTSIGSTOP SIGTSTPSIGTTINSIGTTOUSIGURGSIGXCPUSIGXFSZ SIGVTALRMSIGPROF SIGWINCHSIGIOSIGPWR,信号分类,可以根据信号的来源将信号进行分类: 进程在运行过程中出现了错误,触发系统的信号处

4、理器对错误事件进行处理,这些信号是核心产生的。例如当进程遇到浮点运算错误,将触发SIGFPE信号进行相应的错误处理;段越界错误,核心将向进程发送SIGSEGV信号。 一个进程向另一个进程发送的信号,例如进程可以使用kill系统调用向某个进程或进程组发送信号,进程还可以使用raise向自己发送信号。,常用信号及其含义,信号的捕获和处理,Posix.1中的函数sigaction的功能是为进程安装信号处理器,struct sigaction数据结构用于保存信号处理器的相关信息。具体定义如下: #include int sigaction(int signo, const struct sigacti

5、on *act, struct sigaction *oact); struct sigaction void (*sa_handler)(); /* the action to be taken*/ sigset_t sa_mask; int sa_flags; ; 在sigaction数据结构中,sa_handler是函数指针,当用户想捕获信号时,可以使sa_handler指向信号处理器的入口地址,即一个函数地址,只要该函数声明在调用sigaction之前,sa_handler就可以设置为该函数的名字,编译器会知道这个函数名代表的就是函数地址;如果用户想忽略信号的处理,可以使sa_hand

6、ler等于SIG_IGN;如果用户想对信号进行缺省处理,可以使sa_handler等于SIG_DFL,核心对大多数信号的缺省处理是使进程退出。,信号集合设置,在Posix.1中,定义了sigset_t结构来实现信号集合,并提供了一组信号集合的操作函数,这些函数分别是: #include int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); int sigisme

7、mber(const sigset_t *set, int signo); sigemptyset函数将信号集合清空,sigfillset可以将信号集合设置为包含所有的信号。在对集合进行操作前,必须使用sigfillset或sigemptyset对信号集合进行初始化。否则,由于集合的初始状态是不确定的,不能保证集合能满足用户的需求。 Sigaddset将一个由signo指定的信号加入到信号集合中,sigdelset函数将signo指定的信号从信号集合中删除。Sigismember可以用来判断某信号是否在信号集合中,返回值是1表示信号在集合中,否则返回0表示信号不在集合中。,信号屏蔽码设置,进程

8、的信号屏蔽码也是一个sigset_t类型的结构,用户可以使用Posix. 中的函数sigprocmask来设置进程的信号屏蔽码。具体使用方法如下: #include int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 参数how指示将以什么方式来改变信号屏蔽码,它可能取如下值: SIG_BLOCK:增加一个信号到信号屏蔽码中; SIG_UNBLOCK:在信号屏蔽码中删除一个信号; SIG_SETMASK:将信号屏蔽码设置成给定的信号集合。 参数set是用于设置的集合,oset是进程原来的信号集合,通常进程可以保存并在需要

9、的时候将屏蔽码设置成原来的状态。 sigprocmask调用发生错误时返回值为-1,并将错误码设置在errno中,成功时返回0。,信号的处理,进程收到信号后,有三种方法处理所接收的信号。他们分别是: 接受默认动作。 默认动作一般是终止进程的执行。但是,对SIGUSER1和SIGUSER2来说却是忽略此信号。对SIGSTOP信号来说是停止进程的执行(挂起进程)。 忽略信号的发生,并继续执行程序。在大型的程序中,一些意想不到的信号可能导致程序运行的错误。例如,程序正在做重要的是数据库更新,用户并不想因为一个不小心的中断键而终止它的执行。 接受用户自定义的默认动作。每当一个程序退出时,无论是否正常退

10、出,进程在退出之前都应该做一些清理工作。,信号阻塞,当进程执行敏感任务时(例如数据库更新),不希望外界信号中断程序的运行。在这个阶段并不是简单地忽略信号,而是阻塞这些信号,也就是说进程在结束这些任务后,还会处理这些信号。 函数sigprocmask可以用来在一个进程中阻塞某些特定的信号,它的使用方法如下: #include int sigprocmask(int how, sigset_t *set, sigset_t *oset); 函数sigprocmask的第一个参数指定进程将对这个信号采取何种行动,例如,把第一个参数指定为SIG_SETMASK,这就意味着从现在开始,阻塞第二个参数指定

11、的信号集。第三个参数是当前阻塞信号的掩码信息,如果用户不想知道这些,可以把第三个参数设置为NULL。,向其它进程发送信号:kill,进程调用sigaction可以处理其它进程发送来的信号。如果进程本身想向其它进程发送信号,可以使用kill系统调用。具体使用方法如下: #include #include int kill(pid_t pid, int sig); kill的第一个参数是信号sig将要发送的进程或进程组的pid。通常pid都是一个整数,它是进程的真实id。例如: kill(7256, SIGTERM); 意味着向真实id为7256的进程发送SIGTERM信号,因为进程调用kill需

12、要知道进程id号,所以kill常用于两个联系紧密的进程之间,例如父子进程。值得指出的是进程可以向自己发信号。,向自己发送信号:raise和alarm,raise函数仅仅是向正在执行的进程发送一个信号,具体使用方法如下: #include int raise(int sig); raise把参数sig指定的信号发送到调用进程,成功时返回0。 alarm是一个比较简单而又实用的设定进程定时器的系统调用。当进程定时器超时后,它将以信号的形式通知进程。具体使用方法如下: #include unsigned int alarm(unsigned int secs); 在alarm调用中,secs给出了定

13、时器超时的时间。当给定时间超时后,进程将接收到一个SIGALRM信号。例如: alarm(60); 设定调用进程每60秒接收到一个SIGALRM信号。注意定时器与sleep调用不同,sleep会把进程挂起来,而alarm立即返回,进程按正常的顺序继续执行下去,至少在接收到一个SIGALRM信号之前是按顺序执行的。,pause系统调用,Unix系统还提供了与alarm相对应的系统调用pause,它的用法很简单,具体如下: #include int pause(void); 函数pause会把调用它的进程挂起来,使该进程不再耗费CPU时间,直至该进程接收到一个像SIGALRM这样的信号才会恢复执行

14、。SIGALRM通常情况下会导致进程终止。如果进程忽略SIGALRM信号,pause也会忽略此信号。如果进程捕获了此信号,则在执行完处理函数之后,pause调用将立刻返回-1,并把errno设置为EINTR。,6.2 管道,为了完成一项任务,在两个或者多个进程进行合作时,必然会发生数据共享。即使信号在其处理异常事件或者错误的时候非常有用,但不适合从一个进程到另一个进程传输大量的信息。解决这个问题的一种方法是进程访问共享文件,因为没有任何限制阻止若干进程同时读写同一个文件,但是这种方法效率较低,而且不得不小心地避免进程间竞争的问题。 为了更好地解决这个问题,Unix提供了一个称为管道(pipe)

15、的技术。管道通常被用作单向的通信信道,该信道将一个进程与另一个进程连接在一起,进程可以使用write系统调用向管道发送数据,而另一端的进程也可以通过使用read调用来接收数据。,管道分类,管道提供了一种简单的、同步的进程之间传送信息的方式。管道可以被分为两类:未命名管道和命名管道。未命名管道只能在有亲缘关系的进程之间使用(例如父进程和子进程,子进程和子进程),并且与创建未命名管道的进程一起存在。因为命名管道作为拥有文件访问权限的目录入口而存在,所以它们可以在彼此无关的进程之间使用。,管道技术的实现,管道以先进先出(FIFO)方式保存一定数量的数据。使用管道的时候,一个进程从管道的一端写,另一个

16、进程从管道的另一端读。图中所示未命名管道的工作原理,在主进程中利用fork()函数创建一个子进程,现在,父子进程同时拥有对同一管道的读写句柄,因为管道必须是单向的(它没有提供锁定的保护机制),所以必须决定数据的流动方向,然后在相应进程中关闭不需要的句柄。,管道程序设计,在程序设计中可以通过pipe系统调用来创建管道。如果成功,该调用返回两个文件描述符:一个向管道写入,一个从管道读出。具体使用方法如下: #include int pipe(int filedes2); filedes是一个有两个成员的整形数组,用来保存标识管道的文件描述符。如果这个调用成功,filedes0将用来从管道读出数据,

17、filedes1用来向管道写入数据。 pipe调用失败时返回-1。当这个调用可能导致比每个用户进程限制更多的文件描述符被打开(这种情况下,errno设置为EMFILE),或者内核的打开文件表溢出时(errno将设置为ENFILE),都会发生错误。 一个管道创建之后,就可以使用read和write调用直接操作管道了。,关闭管道,在关闭管道其中一端的文件描述符时,通常有两种情况: 关闭只写文件描述符:如果其它进程仍然打开着以便这个管道进行写操作,这时什么也不会发生。但是,如果没有其它进程要写管道并且管道为空,那么任何一个试图从该管道读出的进程将不会返回任何数据。为读该管道而睡眠的进程将被唤醒,而它

18、们的read调用将返回0。这样,对于读进程的结果和读到一个常规文件的结束符类似。 关闭只读文件描述符:如果其它进程打开着以便这个管道进行读操作,这是什么也不会发生。但是,如果没有其它进程在读该管道,所有等待写入该管道的进程将收到内核发送的一个SIGPIPE信号。如果进程没有捕获该信号,这个进程将终止。如果捕获了这个信号,在中断例程结束之后,write将返回-1并且errno将设置为错误代码EPIPE。其后试图向该管道写入的进程也会收到SIGPIPE信号。,6.3 共享内存,共享内存是对将要在多个进程间映射和共享的内存区域(段)所作的映射。这是IPC的最快捷方式,因为这种通信方式没有中介(例如管道、消息队列等等)。相反,消息直接从某内存段映射,并映射到调用进程的寻址空间。 使用共享内存技术,不同进程可以同时访问相同的内存区域。能够通过共享它们地址空间的若干部分,然后对存储在共享内存中的数据进行读和写,从而实现直接彼此通信。对进程通信来讲,这是一种最快但在某种程度上讲并非最容易的方法。这些数据可以以一种非顺序的随机的方式来访问。为避免不一致的情况,常引入信号量来协调对共享内存段的访问。 多个进程共同使用同一段物理内存空间,不需要数据的多次复制,提高了进程间

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论