第10章 UNIX进程的通信
第10章 UNIX系统的进程通信,进程是在特定的环境中执行的进程执行中需要进行进程间的协调进程间的协调机制是进程通信本章描述UNIX进程通信的机制和方法,进程通信基本概念,进程通信随着相关技术的发展不断增加复杂化度、灵活性,通常包括控制信息传递和大批量信息传递。1. 通信方式1) 主从式-通信进程间有主从之分2) 会话式-用请求/服务方式完成通信3) 消息或邮箱机制-通过消息缓冲或邮箱完成通信4) 共享存储区通信-通过共享缓冲区通信,2. Unix中进程通信包括三种:.基本通信用于传递进程间的控制信息;.管道通信将管道文件作为通信的介质,传递进程间的信息;.IPC(Inter Process Commuation)通信用于进程间大量的数据传送。,UNIX基本通信,1. 锁文件通信通信进程双方将某个文件的建立与撤消作为一个锁标志,即约定:在某个指定目录中(通常会是/tmp目录)查找是否有一个双方约定好的锁文件存在。存在时完成一种处理不存在时完成另一种操作,例:两进程P1和P2试图访问一个不能同时进入的临界资源打印机时,设定一个锁文件,执行中:P1查询锁文件是否存在,若不存在P1创建锁文件lock_file,然后使用该资源;使用完后释放该资源并删除lock_file;如锁文件存在P1等待一个时间再进行锁文件的查询。P2也执行与P1相似动作达到对共享临界资源的访问。可以用系统调用creat、unlink及库函数sleep完成,2. 用记录/文件锁定进行通信通过对文件或文件中的记录锁定实现通信,在UNIX中有一些加锁的系统调用和函数,可实现:建议型锁定-文件/记录可被锁定,进程执行时访问判断锁定的位置,决定是否能执行相应的访问。例:多个进程对某文件都具有访问权,通过对文件锁定位置的判别,实现进程间的合作,并访问文件内容。这种锁对rogue(诬赖)进程没有控制。,强制型锁定-确定一个锁协议,提供附加的安全性。即对文件做每一个read及write系统调用时检测锁信息,满足时访问,否则不能访问(包括rogue 进程)。例:如某文本文件x.dat(不可执行),它对某进程组ID=12的进程开放,同时用chmod关闭进程组ID=12的执行位,构成强制型锁定。通过系统调用fcntl及库函数lockf可完成文件中记录的锁定。,系统调用fcntl:功能:对文件或文件中部分内容进行锁定。头文件:<sys/types.h>, <fcntl.h>调用方式:int fcntl(int fid, int cmd, *arg*);参数说明:fid有效的整数,表示已打开的文件描述符cmd整数值,说明fcntl完成的行为,在头文件fcntl.h中*arg*选项,若采用锁时引用了一个flock结构,fcntl.h中定义的常量:F_SETLK: 设置或删除一个锁定,行为基于flock结构F_SETLKW: 与F_SETLK相同,但记录不可用时阻塞F_GETLK: 通过flock结构返回锁定状态信息,第三个参数引用的flock结构:typedef struct flockshort l_type; /*锁定类型*/short l_whence; /*开始位置*/off_t l_start; /*相对位移*/off_t l_len; /*长度(0=文件尾)*/long l_sysid; /分布的进程ID,适应分布体系*/pid_t l_pid; /与文件相关的进程ID*/long pad4; /*备用*/flock_t;,信号,信号的概念signal函数发送一个信号kill, raisealarm和pause函数可靠的信号机制,信号的概念,Signal软中断处理异步事件的机制每个信号有一个名字(以SIG开头)定义为一个整数 (<signal.h>)如何产生一个信号按终端键,硬件异常,kill(2)函数,kill(1)命令,软件条件,.,Linux/UNIX中的信号,Signals in Linux/UNIX (contd),信号处理,忽略信号不能忽略的信号:SIGKILL, SIGSTOP一些硬件异常信号执行系统默认动作捕捉信号,signal函数,改变指定signum信号的处理方式.#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);(返回值: 如果成功则返回先前的handler,否则返回SIG_ERR)“handler”:用户定义的函数,或SIG_DEF,或SIG_IGN,signal函数(contd),程序示例static void sig_usr(int);int main(void) if (signal(SIGUSR1, sig_usr) = SIG_ERR) err_sys("can't catch SIGUSR1"); if (signal(SIGUSR2, sig_usr) = SIG_ERR) err_sys("can't catch SIGUSR2"); for ( ; ; ) pause();,发送一个信号,kill(): 给一个进程发送一个信号#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);(返回值: 成功为0, 否则为-1)raise(): 给当前进程发送一个信号#include <signal.h>int raise(int sig);(返回值: 成功为0, 否则为-1),alarm和pause函数,alarm: 设置时钟信号#include <unistd.h>unsigned int alarm(unsigned int seconds);(Returned value: 0, or the number of seconds remaining of previous alarm)pause: 等待一个信号#include <unistd.h>int pause(void);(Returned value: -1, errno is set to be EINTR),alarm和pause函数,程序示例sleep函数的实现unsigned int sleep1(unsigned int nsecs) if ( signal(SIGALRM, sig_alrm) = SIG_ERR) return(nsecs); alarm(nsecs); /* 开始计时 */ pause(); /*定时信号来时被唤醒*/ return(alarm(0) ); /*关闭定时器 */,可能出现的问题,与时间有关的问题竞争条件中断的系统调用可重入问题,可靠的信号机制,Weakness of the signal functionSignal blocksignal maskSignal setsigset_t data typeSignal handling functions using signal setsigprocmask, sigaction, sigpending, sigsuspend,signal set operations,#include <signal.h>int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigdelset(sigset_t *set, int signum); (Return value: 0 if success, -1 if error)int sigismember(const sigset_t *set, int signum); (Return value: 1 if true, 0 if false),sigprocmask 函数,检测或更改(或两者)进程的信号掩码#include <signal.h>sigprocmask(int how, const sigset_t *set, sigset_t *oldset);(Return Value: 0 is success, -1 if failure)参数“how”决定对信号掩码的操作SIG_BLOCK: 将set中的信号添加到信号掩码(并集)SIG_UNBLOCK: 从信号掩码中去掉set中的信号(差集)SIG_SETMASK: 把信号掩码设置为set中的信号例外: SIGKILL, SIGSTOP,sigpending 函数,返回当前未决的信号集#include <signal.h>sigpending(sigset_t *set);(Returned Value: 0 is success, -1 if failure),sigaction 函数,检查或修改(或两者)与指定信号关联的处理动作#include <signal.h>sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);(Returned Value: 0 is success, -1 if failure)struct sigaction至少包含以下成员:handler_t sa_handler; /* addr of signal handler, or SIG_IGN, or SIG_DEL */sigset_t sa_mask;/* additional signals to block */int sa_flags;/* signal options */,sigsuspend 函数,用sigmask临时替换信号掩码,在捕捉一个信号或发生终止该进程的信号前,进程挂起。#include <signal.h>sigsuspend(const sigset *sigmask);(Returned value: -1, errno is set to be EINTR)sigsuspend和pause,signal function review,用sigaction实现signal函数Sigfunc * signal(int signo, handler_t func) struct sigactionact, oact;act.sa_handler = func;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (signo = SIGALRM) #ifdefSA_INTERRUPTact.sa_flags |= SA_INTERRUPT;/* SunOS */#endif else #ifdefSA_RESTARTact.sa_flags |= SA_RESTART;/* SVR4, 44BSD */#endifif (sigaction(signo, &act, &oact) < 0)return(SIG_ERR);return(oact.sa_handler);,