进程间通信IPC-信号

时间:2023-03-09 00:31:45
进程间通信IPC-信号

1,signal-ANSI C信号处理

 #include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

signal是ANSI C实现的信号处理函数,signum表示信号ID,常用的信号有:

 ~$ kill -l
) SIGHUP ) SIGINT ) SIGQUIT ) SIGILL ) SIGTRAP
) SIGABRT ) SIGBUS ) SIGFPE ) SIGKILL ) SIGUSR1
) SIGSEGV ) SIGUSR2 ) SIGPIPE ) SIGALRM ) SIGTERM
) SIGSTKFLT ) SIGCHLD ) SIGCONT ) SIGSTOP ) SIGTSTP
) SIGTTIN ) SIGTTOU ) SIGURG ) SIGXCPU ) SIGXFSZ
) SIGVTALRM ) SIGPROF ) SIGWINCH ) SIGIO ) SIGPWR
) SIGSYS ) SIGRTMIN ) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+
) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+
) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMIN+
) SIGRTMIN+ ) SIGRTMIN+ ) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX-
) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX-
) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX- ) SIGRTMAX-
) SIGRTMAX- ) SIGRTMAX
每个信号的含义和产生可以通过 查看linux编程手册:man 7 signal 

handler参数有3种:

a)SIG_IGN,表示忽略该信号

b)SIG_DFL,表示捕捉到某信号采用系统默认的处理方式,查看signal(7)

c)自定义信号处理函数,如下:

 #include <signal.h>
void my_signal_handler(int sig)
{
//do something
} int main(int argc, char* argv[])
{
singal(SIGUSR1, my_signal_handler); //注册信号捕捉函数
//do something
return ;
}

2,sigaction-信号处理system call

 #include <signal.h>
int sigactoin(int signum, const struct sigaction *act, struct sigaction *oldact);//注册信号处理
int sigemptyset(sigset_t *set);//清空全部信号sigset_t,用于sa_mask
int sigfillset(sigset_t *set);//填充全部信号sigset_t,用于sa_mask
int sigaddset(sigset_t *set, int signum);//增加某信号到sigset_t,用于sa_mask
int sigdelset(sigset_t *set, int signum);//从sigset_t中删除某信号,用于sa_mask
int sigismember(const sigset_t *set, int signum);//是否存在
struct sigaction {
void (*sa_handler)(int); //默认信号处理函数
void (*sa_sigaction)(int, siginfo_t *, void *); //sa_flag设置为SA_SIGINFO时常用的信号处理函数
sigset_t sa_mask; //屏蔽信号集合
int sa_flags; //定义的行为
void (*sa_restorer)(void); //已弃用
}; #include <stdlib.h>
#include <signal.h> void my_signal_handler(int sig)
{
//do something
} int addmysignal(int signum, void (* my_signal_handler)(int))
{
struct sigaction sa;
memset(&sa, , sizeof(sa));
sa.sa_handler = my_signal_handler;
sa.sa_flags |= SA_RESTART; //自动重启该信号signum捕捉
sigfillset(&sa.sa_mask); //屏蔽(阻塞)所有其他信号,当捕捉到signum并执行信号处理函数时。
return sigaction(signum, &sa, NULL);//这里暂时忽略oldact;
} int main(int argc, char* argv[])
{
//注册信号捕捉函数
if (addmysignal(SIGUSR1, my_signal_handler) < )
{
exit(EXIT_FAILURE);
}
//do something
return ;
}

sa_flags参数可通过查看linux编程手册进一步了解:man sigaction

从上述两种信号处理的使用方式来看,好像没有进程间通信什么事。那进程间是如何利用signal来进行通信的呢?

 #include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

通过系统调用kill向指定进程发送指定信号,pid进程收到sig后,执行信号处理函数,这就实现了进程间通信。

同时我们在使用信号进程通信的同时,还可以借助管道,实现两进程间的数据交互。

示例代码略。