分类: LINUX
2014-12-10 16:50:05
原文地址:进程间通信知识 作者:chengbin_liu
v 同主机进程间的数据交互机制:无名管道(pipe)、有名管道(fifo)、消息队列(messag queue)、共享内存(share memory)
v 同主机进程间的同步机制:信号量(semaphore)
v 同主机进程间的异步机制:信号(signal)
v 网络主机间数据交互机制:套接口(socket)
无名管道是一种专门用来实现进程间通信的特殊文件,和普通的文件有一定的差别:无名管道只能存在与进程通信期间,通信完成后自动消失,而且只能存放通信的临时信息,不能向普通文件那样存储大量的常规信息;
1、创建管道:
Extern int pipe(int pipedes【2】)
参数:一个整形的数组
返回值:
成功 将存储两个整形的文件描述符于数组中,分别指向管道的两端,pipedes【0】读文 件,pipedes【1】为写文件;
失败 返回-1
2、文件描述符重定向
重定向操作实际上就是关闭标准输入输出(文件描述符为0、1、2),而将另一个打开的文件的文件描述符设置为0、1、2. 例如:printf都是将某信息写入到文件描述符为1的文件中,从而实现将本应输出到标准输出设备的数据输出到对应的文件中实现重定向。
l Dup(int fd);
应用:
Int fdes【2】;
Pipe(fdes);
Close(fileno(stdout));
Dup(fdes【1】);
l Dup2(int fd ,int fd2);
参数fd2:是小于文件描述符的最大允许值的非负整数,如果fd2是一个以打开的文件描述符,首先关闭该文件,然后进行复制。
3、流重定向
1、信号中断处理
Linux提供的信号机制是一种进程间的异步通信机制,在实现上是一种软中断,信号可以导致一个正在运行的进程被另一个异步进程中断,转而处理某个突发事件,异步事件是不可预见的,只能通过某些特定的方式来预防。
2、信号的处理流程:
l 信号被某个进程产生,并设置此信号的传递的对象,然后传递给操作系统
l 操作系统根据接收进程的设置(是否阻塞)选择性的发送给接收者,如果接收者阻 塞该信号,操作系统将暂时的保留该信号,而不传递,直到该进程解除对此信号的 阻塞;如果对应进程没有阻塞操作系统将传递该信号
l 目的进程接收到该信号后,根据当前进程对此信号设置的预处理方式,暂时终止当 前代码的执行,保护上下文、转而执行中段服务程序,执行完成后在恢复到被中断 的位置,当然对于可抢占式的内核,在中断返回时还将引发新的调度。
3、相关术语:
n 发送一个信号:一个进程创建一个信号用于发送给另一个进程
n 生成一个信号:内核创建一个信号
n 唤醒一个信号:一个进程向自己发送一个信号
n 安装中断:为使某个信号到来时进程能够执行相应的中断服务程序,及设置某信号到来时执行的代码;
n 信号被捕捉:如果一个信号的递送导致一段处理程序被执行;
n 信号等待状态:如果一个信号被发送并且还没有引起任何动作。
4、信号的来源:
l 用户按某些终端键时将产生信号,如“ctrl+c”产生中止信号。
l 硬件异常产生信号;除数为零或无效的存储访问等。
l 终止进程信号;如进程调用kill()函数将信号发送给另一进程
l 软件异常产生信号;如sigpipe在管道的读进程已终止,后一个进程写此 管道,sigurg 在网络连接上传送非法波特率的数据
5、常用产生信号的函数:、usr/include/signal.h
l Extern int kill(pid_t pid,int sig);
向指定的进程传递信号,成功返回0,否则-1;
l Extern int raise(int sig);
向当前进程发送一个信号即唤醒一个进程,成功返回0,否则-1;
l Extern unsigned int alarm(unsigned ing seconds)
传递定时信号,即在给定时间内产生sigalarm信号,每调用一次产生一个信号,并不是 循环产生sigalarm信号
l Extern useconds_t ualarm(useconds_t value,useconds_t interval)
在给定的时间value内,每隔interval重复产生sigalarm信号。
6、信号的处理与信号的安装:
1) 信号的处理方式:
l 忽略此信号,sigkill 和sigstop不能被忽略,因为他向超级用户提供使进程终止和 停止的可靠方法
l 捕捉信号
l 执行系统默认:
ü SIG_ING:忽略信号
ü SIG_DFL:执行信号默认
ü SIG_ERR:返回错误
2) 信号的安装:
① Signal方式
格式:typedef void (*sighander_t)(int)
Extern sighander_t signal(int signo, sighander_t hander);
参数:signo 为接收到的信号
Hander 为接收到信号后的处理代码的入口(即处理子程序)
应用:
v Signal(SIGINT, my_function)
v Signal(SIGINT, SIG_DFL)
v Signal(SIGINT, SIG_ING)
② Sigaction方式
Sigaction()函数功能强大用来检测和更改信号处理操作
格式:extern int sigaction(int sig , struct sigaction *act, struct sigaction *oact);
参数:第二三、均为信号结构sigaction变量,(描述要采取的操作及相关的信息)
第二个参数:指定预设置的信号处理信息
第三个参数:返回执行此程序前此信号处理信息
Struct sigaction{
Union{
a. Sighander_t sa_hander;//SIG_DFL,SIG_ING,类似signal函数
b. Void (*sa_sigaction)(int , struct siginfo *, void *);//信号捕获函数
}_u;
c. Sigset_t sa_mask;//执行信号捕获函数期间要阻塞的其他信号集
d. Unsigned long sa_flags;//影响信号行为的特殊标志
e. Void (*sa_restorer) (void);
};
D、 sa_flags;用于更改指定信号的行为
² SA_NOCLDSTOP//子进程退出时不生成sigchld信号
² SA_ONSTACK//如果设置了该标志,并使用sigaltstack()或sigstack()声明了备用信号堆栈,信号将会传递给该堆栈中的调用进程,否则信号在当前堆栈上传递。
² SA_RESTHAND//
² SA_RESTART//此标志影响可中断函数的行为,即指定的可中断函数将会失败,并会设置errno
² SA_NOCLDWAIT//如设置了此标志,并且sig等于SIGCHLD,则调用进程的子进程在终止时将不会转换为死进程
² SA_NODEFER//如设置了此标志并捕获到sig,则在信号处理程序后,sig将不会添加到进程的阻塞信号集中,除非将其纳入sa_mask.
² SA_SIGINFO//
如果清除该标志并捕获到此信号,即act.Sa_flags=0;则捕获函数以一下形式使用:act.sa_hander=myhander; void myhander(int sig){};
如果设置标志并捕获到此信号即act。Sa_flags=SA_SIGINFO;则捕获函数以一下形式使用:
act.sa_sigaction=func(int signo, siginfo *info, void *context);
第二个参数:指向siginfo_t类型的一个对象,用于解释生成信号的原因
第三个参数:赋给指向ucontext_t 类型的一个对象指针,以引用在传递信号时被中断的接收进程或线程的上下文。
Typdef Struct siginfo{
Int si_signo;//信号编号
Int si_errno;
Int si_code;//标识信号产生的原因
Union{
Int _pad[SI_PAD_SIZE];
Struct{ //kill()
Pid_t pid; //sender's pid
Uid_t uid; //sender's uid
}_kill;
Struct{ //posix.1b timers
Unsigned int timer1;
Unsigned int timer2;
}_timer;
Struct{ //posix.1b signals
Pid_t pid; //sender's pid
Uid_t uid; //sender's uid
Sgval_t sigval;
}_rt;
Struct{ //SIGCHLD
Pid_t pid; //which child
Uid_t uid; //sender's uid
Int status; //exit's code
Clock_t utime;
Clock_t stime;
}_sogchld;
Struct{ //SIGILL,SIGFPE,SIGSEGV,SIGUS
Void *addr; //faulting insn/memory ref
}_sigfault;
Struct{ //SIGPOLL
Int band; //POLL_IN,POLL_OUT,POLL_MSG
Int fd;
}_sigpoll;
}_sifields;
}siginfo_t;
C、信号集函数组(信号阻塞)
设置进程阻塞的信号集:即将出现的信号集合set加入到进程的信号阻塞集中
对于该信号集可进行增删改查等操作:
u 组合信号集方法:
Extern int sigpending(sigset_t *set);//返回当前进程阻塞的集合
Extern int sigprocmask( int _how, const sigset_t *set , sigset_t *oset);
参数:
第一个为更改集合的方式:
ü SIG_BLOCK:将第二参数所描述的集合添加到当前的进程阻塞的信号集 合中
ü SIG_UNBLOCK:将第二参数所描述的集合从当前的进程阻塞信号集合中 删除
ü SIG_SETMASK:无论以前的集合,设置当前的进程阻塞集合为第二个参 数描述的对象
u 信号集的设置方法:
ü 判断是否为空信号集
Extern int sigisemptyset( const sigset_t *set);//成功返回1否则返回0
ü 清空信号集
Extern int sigemptyset( const sigset_t *set);//成功返回0否则返回-1
ü 添加信号到信号集
Extern int sigaddset(const sigset_t *set int sig);//成功返回0否则返回-1
ü 从信号集中删除信号
Extern int sigdelset(const sigset_t *set,int sig);//成功返回0否则返回-1
ü 完全填充信号集
Extern int sigfillset( const sigset_t *set);//成功返回0否则 返回-1
ü 检测信号是否在信号集中
Extern int sigismember( const sigset_t *set,int sig);//成功返回0否则返回-1
ü 两个信号的逻辑与和逻辑并
Extern int sigandset( const sigset_t *set, sigset_t *right,sigset_t *right);// 成功返回0否则返回-1
Extern int sigorset( const sigset_t *set, sigset_t *right,sigset_t *right);//成 功返回0否则返回-1
ü 等待出当前进程阻塞信号外的任意信号
Extern int pause( void)//成功返回0否则返回-1
ü 等待除指定信号外的任意信号
Extern int sigsuspend( const sigset_t *set);//成功返回0否则返回-1