澳门至尊网站-首页

您的位置:澳门至尊网站 > 程序编程 > Linux进度间通讯

Linux进度间通讯

2019-11-28 08:30

信号signal 是python进程间进行信号发送的一种机制,其原理是操作系统对进程的控制,是一种程序中断

1.什么是信号
信号是Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作。

一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。

2.信号的产生
1)由硬件产生,如从键盘输入Ctrl+C可以终止当前进程
2)由其他进程发送,如可在shell进程下,使用命令 kill -信号标号 PID,向指定进程发送信号。
3)异常,进程异常时会发送信号

 

3.信号的处理
信号是由操作系统来处理的,说明信号的处理在内核态。
信号不一定会立即被处理,此时会储存在信号的信号表中。
处理过程示意图:

那么singanl到底有什么用呢?

图片 1

siganl的应用:

由上图中可看出信号有三种处理方式:
1)忽略
2)默认处理方式:操作系统设定的默认处理方式
3)自定义信号处理方式:可自定义信号处理函数

1. 故障定位技术(进程的底层故障,例如进程突然中断和一些可能性较小的故障)

4.自定义信号处理方式
1)signal函数
原型:
void (*signal(int sig, void (*func)(int)))(int);
sig:信号值
func:信号处理函数指针,参数为信号值
代码示例如下:

  1. 对进程的流程控制 
#include <signal.h>
#include <stdio.h>
void ouch(int sig)
{
    printf("nOUCH! - I got signal %dn", sig);
    //恢复终端中断信号SIGINT的默认行为
    (void) signal(SIGINT, SIG_DFL);
}
int main()
{
    //改变终端中断信号SIGINT的默认行为,使之执行ouch函数
    //而不是终止程序的执行
    (void) signal(SIGINT, ouch);
    while(1)
    {
        printf("Hello World!n");
        sleep(1);
    }
    return 0;
}

 

输出结果:

首先说说与信号signal有关的几个函数

图片 2

(1)os.kill(pid,sig)

2)sigaction函数
原型:
int sigaction(int sig,const struct sigaction *act,struct sigaction *oact);
sig:信号值
act:指定信号的动作
oact:保存原信号的动作

发送一个信号给某个进程

sigaction结构体的定义如下:
void (*)(int) sa_handler;处理函数指针,相当于signal函数的func参数。
sigset_t sa_mask;处理过程中,屏蔽对sa_mask信号集的处理,sa_mask可以消除信号间的竞态。
int sa_flags;信号处理修改器:处理函数执行完后,信号处理方式修改。如SA_RESETHAND,将信号处理方式重置为SIG_DFL
代码示例如下:

参数解析:

#include <stdio.h>
#include <signal.h>
void ouch(int sig)
{
    printf("nOUCH! - I got signal %dn", sig);
}
int main()
{
    struct sigaction act;
    act.sa_handler = ouch;
    //创建空的信号屏蔽字,即不屏蔽任何信息
    sigemptyset(&act.sa_mask);
    //使sigaction函数重置为默认行为
    act.sa_flags = SA_RESETHAND;
    sigaction(SIGINT, &act, 0);
    while(1)
    {
        printf("Hello World!n");
        sleep(1);
    }
    return 0;
}

pid 指定发送信号的进程号

输出结果:

sig  要发送的信号代号(需要通过signal模块获取)

图片 3

 

4.信号的发送
1)kill函数
int kill(pid_t pid,int signo);
pid:进程ID
signo:信号值

 

2)raise函数:只能向当前进程发信号
int raise(int signo);
signo:信号值

(2)signal.alarm(sec)  非阻塞函数

3)abort函数:发送SIGABRT信号,可以让进程异常终止
void abort(void);

设置时钟信号,在一定时间后给自身发送一个SIGALRM信号

4)alarm函数:发送SIGALRM闹钟信号
unsigned int alarm(unsigned int seconds);

 

5.信号的阻塞
阻塞是阻止进程收到该信号,此时信号处于未决状态,放入进程的未决信号表中,
当解除对该信号的阻塞时,未决信号会被进程接收。

原理: 时钟的创建是进程交由操作系统内核(kernal)帮助创建的

1)阻塞信号
原型:
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
how:设置block阻塞表的方式
a.SIG_BLOCK:将信号集添加到block表中
b.SIG_UNBLOCK:将信号集从block表中删除
c.SIG_SETMASK:将信号集设置为block表
set:要设置的集合
oset:设置前保存之前block表信息

时钟和进程之间是异步执行的,当时钟到时,内核会发送信号给进程,进程接收信号进行相应的响应操作.这就是所谓的python异步处理方案.

2)获取未决信号
前面已经讲过,阻塞的信号处于未决的状态,会放入进程的未决信号表。
原型:
int sigpending(sigset_t *set);
set:out型参数,会将获得的当前进程的pending未决表中的信号集传入。

后面的时钟会覆盖前面的时钟,一个进程只有一个挂起的时钟

代码示例如下:

 

#include <stdio.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <signal.h>
void func(int num)
{
  printf("catch signal number is %d",num);
}
void printfpendingsignal(sigset_t *set)
{
  int i;
  for(i=1;i<32;++i)
  {
    if(sigismember(set,i))
    {
      printf("1");
    }
    else
    {
      printf("0");
    }
  }
  printf("n");
}
int main()
{ 
  sigset_t s,p,o;
  signal(SIGINT,func);
  sigemptyset(&s);
  sigemptyset(&p);
  sigemptyset(&o);
  sigaddset(&s,SIGINT);
  sigprocmask(SIG_SETMASK,&s,&o);
  int count=0;
  while(1)
  {
    sigpending(&p);
    printfpendingsignal(&p);
    sleep(1);
    if(count++==10)
    {
      printf("recover!n");
      sigprocmask(SIG_SETMASK,&o,NULL);
    }
  }
  return 0;
}

名词的理解:

输出结果:

异步: 程序在执行中利用内核功能帮助完成必要的辅助操作,不影响应用层持续执行

图片 4

 

6.信号处理函数的安全问题
如果信号处理过程中被中断,再次调用,然后返回到第一次调用时,要保证操作的正确性。
这就要求信号处理函数必须是可重入的。
可重入函数表如下:

注意: 这里的同步和异步机制是相对多进程而言的.(注意与多线程的异步执行相区分,之后我会写写多线程的异步机制的相关文章)

图片 5

 

7.一些常见的信号

在进程中通信这个概念下,只有singal是异步执行的,另外python进程间通信的机制还有pipe(管道),queue(队列),value(共享空间)等等

图片 6

有机会会将这几种机制进行一个对比

如果进程接收到上面的这些信号,又没有安排捕获它,进程就会终止。

 

其他的一些信号如下:

(3)signal.pause()

图片 7

阻塞进程,等待一个信号.当接收到信号时就会停止阻塞

例如:等待signal()函数的发送

 

(4)signal.signal(sig,handler)

当进程运行过程中出现故障异常或者需要进程间通信时,操作系统内核/进程发出处理信号

参数理解:

sig 要处理的信号名称

handler 信号处理方法   可选值: SIG_DFL   表示默认方法处理

                                                 SIG_IGN    表示忽略这个信号(一般为了避免父进程和子进程的互相干扰而使用)

                                                     func       自定义函数(实际上是回调函数的一类,信号发生时,调用处理函数,完成之后,回到原来的位置继续执行下面的程序)

自定义函数格式: (跟定义python普通函数的定义没有区别)

def  func(sig,frame):

 sig : 接收到的信号

 frame: 信号结构对象(可以通过结构对象查看信号信息,基本不用)

 

signal函数实际上是一个异步处理函数,只要执行了该函数,则进程任意时候接收到相应信号都会处理

 这里的异步就是上文提到的异步机制,是计算机内核程序与本进程间同时运行,互相不干扰的一种机制,对于进程的正常执行有着关键的作用。

这种异步机制在任何后端编程语言中都是存在的,只不过实现的方式和细节不一样而已。

 

那么singnal怎么用呢?

一般信号signal是在需要检测异常的程序的开头就定义好了,程序顺序向下运行时,一旦捕获到操作系统发出的signal或者其他进程发出的signal

马上就会停止当前的程序运行状态,去处理捕获到的signal。

 

本文由澳门至尊网站发布于程序编程,转载请注明出处:Linux进度间通讯

关键词: