Linux进程间通讯-信号

进程间通讯-信号

目录

  • 信号概念
  • 常见信号及简单说明
  • 信号相关术语
  • 相关函数

概念

​ 信号(signal)是Linux系统下的一种进程间通信机制。它是在软件层对中断机制的一种模拟。所以信号也被成为软中断。应用程序收到信号后,有三种处理方式,忽略,默认或者捕捉处理。进程收到信号后,会检查对该信号的处理机制,通常是终止进程或者忽略该信号,如果该信号指定了一个处理函数(捕捉),则会中断当前正在执行的任务,转而去执行该信号的处理函数,返回后,再次继续执行被中断的任务。

​ 信号的处理可以看作是中断服务程序,要求快进快出。不能在这个函数中做太多的事情。否则,本次信号的处理还没有完成,下一个信号又发过来了,这样,我们就会丢失这个信号。如果这种丢失累积出现,程序便会完全乱套。所以,信号处理函数中实现的功能要求高效、简洁。

常见信号及简单说明

信号名 编号 含义 默认操作
SIGHUP 1 本信号在用户终端连接(正常或非正常)结束时发出,通常是在终端的控制进程结束时,通知同一会话内的各个作业,这时它们与控制终端不在关联。 终止进程
SIGINT 2 程序终止信号(interrupt),在用户键入INTR字符(通常是ctrl-c)时发出,用于通知前台进程组终止进程。 终止进程
SIGQUIT 3 和SIGINT类似,但由QUIT字符(通常是Ctrl-)控制,进程因SIGQUIT收到退出时会产生core文件,在这个意义上类似于一个程序错误信号。 终止进程
SIGKILL 9 用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。如果发现某个进程终止不了,可尝试发送这个信号。 终止进程
SIGSTOP 19 停止进程的执行。该进程还未结束,只是暂停执行。本信号不能被阻塞,处理或者忽略。 暂停进程

常用信号及简单说明

系统中的信号

Linux进程间通讯-信号_第1张图片

Linux 系统中有许多信号, 其中前面 31 个信号都有一个特殊的名字, 对应一个特殊的事件,将他们称为非实时信号, 这些信号都是从 Unix 系统继承下来的, 他们还有个名称叫“不可靠信号”。

信号相关术语

1.发送信号:

​ 产生信号,发送信号有多种方式,一个进程可以向另一个进程发送一个特定信号,内核也可以向用户进程发送信号,进程还可以向自己发送一个信号。

2.安装中断:

​ 信号到来时,为了不让信号执行默认操作,而是执行自己的代码,也就是说,期望信号到来时,让进程执行我们设置的中断服务程序。3.递送信号

​ 一个信号被操作系统发送到目标进程。

4.捕捉信号

​ 被递送的信号在目标进程引起处理程序的执行。

5.屏蔽信号

​ 进程告诉操作系统暂时不接受某些信号,如果在屏蔽期间向进程发送了屏蔽信号,该信号将不被捕捉,一段时间后,如果进程解除信号屏蔽,该信号就被捕捉到。

6.忽略信号

​ 信号被递送到目标进程,但目标进程不处理,直接丢弃。

7.未觉信号

​ 信号已经产生,但因为目标进程暂时屏蔽该信号而不能被捕捉的信号。

8.可靠与不可靠信号。

​ 编号<32 的叫不可靠信号,>32 的信号为可靠信号

不可靠信号与可靠信号

不可靠信号特点:

​ 1.不可靠信号不排队, 信号的响应会相互嵌套。

​ 2.如果目标进程没有及时响应不可靠信号,那么随后到达的该信号将会被丢弃。

​ 3.每一个不可靠信号都对应一个系统事件,当这个事件发生时,将产生这个信号。

​ 4.如果进程的挂起信号中含有实时和非实时信号,那么进程优先响应实时信号 并且会从大到小依此响应,而非实时信号没有固定的次序。可靠信号的特点:

1. 实时信号的响应次序按接收顺序排队,不嵌套。
2. 即使相同的实时信号被同时发送多次,也不会被丢弃,而会依次挨个响应。
3. 实时信号没有特殊的系统事件与之对应。 

相关函数

函数名 signal
头文件 #includen
函数原型 sig_t signal(int signum, sighandler_t handler);
功能 设置某一信号的对应动作,signal()会依参数signum 指定的信号编号来设置该信号的处理函数。当指定的信号到达时就会跳转到参数handler指定的函数执行
参数说明 1.signum:指明了所要处理的信号编号,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
2.handler:描述了与信号关联的动作,它可以取以下三种值:
(1)一个无返回值的函数地址.这个函数应有如下形式 的定义:void func(int sig);
(2)SIG_IGN 这个符号表示忽略该信号
(3)SIG_DFL这个符号表示系统对信号的默认处理。
返回值 成功,返回上一个处理函数的地址,否则返回SIG_ERR,错误码放在errno
函数名 raise
头文件 #include #include
函数原型 int raise(int sig);
功能 将参数sig指定的信号发送给自身进程。
参数说明 1.sig:将要发送的信号ID。
返回值 成功,返回0,否则返回-1错误码放在errno
函数名 kill
头文件 #include #include
函数原型 int kill(pid_t pid,int sig);
功能 可以用来将参数sig指定的信号发送给参数pid指定的进程。
参数说明 1.pid:进程描述符
pid>0 将信号发送给进程ID为pid 的进程。
pid=0 将信号发送给和当前进程相同进程组的所有进程;
pid=-1 将信号广播发送给系统内所有的进程;
pid<-1 将信号发送给进程组号为pid绝对值的所有进程。
2.sig:表示信号编号。
返回值 成功,0,否则返回-1
函数名 sigprocmask
头文件 #include
函数原型 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能 阻塞或解除阻塞一个或者多个信号
注意:信号的阻塞不同于忽略, 阻塞指的是暂时将信号挂起,不响应他, 待解除阻塞之后还可以处理这个信号,忽略就是直接把信号丢弃了。
参数说明 1.how:操作方式SIG_BLOCK: 在原有阻塞信号基础上增加set中的信号。SIG_SETMASK: 用set中的信号替换原有阻塞信号;SIG_UNBLOCK: 在原有阻塞信号基础上解除set中的信号
2.set:要操作的信号集。
3.oldset:[out]原有的信号集。如果不关注原有的信号集,可设为NULL
返回值 成功,0,否则返回-1,错误码存在errno 里。
函数名 信号集操作函数族
头文件 #include
函数原型 int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
功能 1.sigemptyset( ): 将信号集清空
2.sigfillset( ): 将所有信号添加到信号集中
3. sigaddset( ): 将指定的一个信号添加到信号集中
4.sigdelset( ): 将指定的一个信号从信号集中剔除
5. sigismember( ): 判断一个指定的信号是否被信号集包含
参数说明 1.set:信号集
2. signum:要操作的信号。
返回值 成功:sigismembe 返回 1 其他返回0
失败:sigismembe 返回 0 其他返回-1。 错误码放在errno里
函数名 sigqueue
头文件 #include
函数原型 int sigqueue(pid_t pid, int sig, const union sigval value);
功能 给某进程发送一个指定的信号, 同时携带一些数据
参数说明 pid : 目标进程 PID
sig : 要发送的信号
value: 携带的额外数据
union sigval {
int sival_int;
void *sival_ptr;
};
返回值 成功返回0 ,失败返回-1;错误码放在errno里
函数名 sigaction
头文件 #include
函数原型 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
功能 捕捉一个指定的信号, 且可以通过扩展响应函数来获取信号携带的额外数据
参数说明 signum : 要捕捉的信号
act: 信号的新处理方式
oldact: [OUT] 原处理方式
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}; 结构体成员详见手册
返回值 成功返回0 ,失败返回-1;错误码放在errno里
函数名 alarm
头文件 #include
函数原型 unsigned int alarm(unsigned int seconds);
功能 在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号。如果忽略或者不捕获此信号,则其默认动作是终止调用该alarm函数的进程。要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。需要注意的是,经过指定的秒数后,信号由内核产生,由于进程调度的延迟,所以进程得到控制从而能够处理该信号还需要一些时间。如果有以前为进程登记的尚未超时的闹钟时钟,而且本次调用的seconds值是0,则取消以前的闹钟时钟,其余留值仍作为alarm函数的返回值。
参数说明 1.seconds:指定秒数。
返回值 成功:如果调用alarm前,进程已经设置了闹钟时间,则返回上一个闹钟的剩余时间,否则返回0
函数名 ualarm
头文件 #include
函数原型 __useconds_t ualarm(__useconds_t __value,__useconds_t __interval);
功能 在使当前进程在指定时间(第一个参数)内产生SIGALRM信号,然后每隔指定时间(第二个参数)重复产生SIGALRM信号。
参数说明 1.value:第一次间隔的微秒数;
2.interval:以后每次间隔的微秒数;
返回值 成功:如果调用此ualarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0;出错:-1;
函数名 pause
头文件 #include
函数原型 int pause(void);
功能 阻塞进程,等待信号到来。
参数说明
use(void);
功能 阻塞进程,等待信号到来。
参数说明
返回值 成功:返回0;出错:返回-1,并且设置errno为EINTR。

你可能感兴趣的:(linux,c语言)