进程间通信之信号

说起信号,就像是一个软中断一样,就是一个信号来了以后我们程序中断当前执行的代码,找到之前注册过的相应信号的执行代码进行处理.其实我们使用的非常的广泛了,就像我们在终端里面要停止一个进程的运行,我们会同时按下ctrl+C的按键来终止程序,这个就是一个信号,是停止信号,是标号为9的信号,我们可以使用kill -l的命令来查看我们系统支持的信号.很多信号的处理都有系统默认的方式进行解决,所以我们在编程中并没有对9号信号进行处理,我们的程序却会在ctrl+C的信号到来的时候终止程序.一般Linux系统中支持的信号有64种,这里就不介绍了.我们可以在编程的时候使用自己的方式去对信号进行处理而不调用系统默认的处理方法.

我们要处理信号首先要进行信号处理函数的注册.

#include <signal.h>

void (*signal(int signum,void (*handler)(int)));

第一个参数是信号的编号,第二个参数是一个函数指针.指向的是信号处理函数,还可以为SIG_ING 或略参数指定的信号.

既然是进程之间的通信,所以就会有发送信号的进程,使用函数

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid,int sig);//pid 指定信号的接受者的进程号,sig 发送信号的编号

pid > 0 是将信号发送给该进程

pid = 0是将信号发送给和自己进程相同的进程组中的进程

pid = -1将信号广播给所有进程

pid < 0将信号发送给进程识别码为pid的绝对值的所有进程

因为管道的传输数据的方式容易失败和阻塞和程序不方便处理其他事情,我通常使用信号配合管道使用,当某一程序写完管道以后,向指定的程序发送信号,这样指定的接受到信号以后读取管道中的内容,这样可以及时的读取管道的内容,而且不会堵塞,程序还可以干其他的事情.

下面是信号处理的代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <signal.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <fcntl.h>
  7
  8 #define FIFO_PATH       "/home/cy/myfifo"
  9
 10 int Rfifo = 0;
 11
 12 void mySig(int sig_num){//信号处理函数
 13
 14         char buf[1024] = {0};
 15
 16         printf("信号来了\n");
 17
 18         read(Rfifo,buf,1024);//读取管道内容
 19         printf("%s\n",buf);
 20
 21 }
 22
 23 int main()
 24 {
 25         if(mkfifo(FIFO_PATH,0666) < 0 && errno !=EEXIST){//创建管道
 26         perror("创建错误\n");
 27         return -1;
 28     }
 29         Rfifo = open(FIFO_PATH,O_CREAT | O_RDONLY,0666);
 30         if(Rfifo < 0){
 31                 perror("wrong\n");
 32                 return -1;
 33         }
 34
 35
 36         while(1){
 37                 signal(10,mySig);//注册10号信号的处理函数
 38                 pause();//因为没有其他需要执行的工作,使用该函数将该进程休眠等待信号的到来
 39                 printf("sleeping\n");
 40         }
 41
 42         close(Rfifo);
 43         return 0;
 44 }

在向指定进程发送信号之前需要获取该进程的Pid,我们现在只知道对方进程的名称,而每次程序执行的时候Pid都是不一样的,这样我们就需要通过进程的名称获取到Pid的值,shell命令pidof 进程名,返回的结果就是该名称进程的Pid,我们可以在程序代码中执行这个命令来获取指定进程的Pid.  

下面是向指定进程发送信号的代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <signal.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <fcntl.h>
  7
  8 #define FIFO_PATH       "/home/cy/myfifo"
  9
 10 int main(int argc,char *argv[])
 11 {
 12         pid_t pid = 0;
 13         FILE *fpid = NULL;
 14         char name[] = "pidof sig1";//shell命令,获取指定名称的函数的pid号.
 15         char needPid[6] = {0};
 16         int Wfifo = 0;
 17
 18         fpid = popen(name,"r");//执行获取pid号的命令并返回文件描述符
 19
 20         fgets(needPid,6,fpid);//根据文件描述符读取命令的返回结果
 21         pid = atoi(needPid);//将字符型的结果转化为int型的pid
 22
 23         pclose(fpid);//关闭该文件描述符
 24
 25         if(mkfifo(FIFO_PATH,0666) < 0 && errno != EEXIST){
 26         perror("创建错误\n");
 27         return -2;
 28     }
 29         Wfifo = open(FIFO_PATH,O_CREAT | O_WRONLY,0666);
 30         if(Wfifo < 0){
 31                 perror("wrong\n");
 32                 return -1;
 33         }
 34
 35         while(1){
 36
 37         printf("while\n");
 38                 write(Wfifo,name,15);//向管道中写信息
 39                 kill(pid,10);//向指定的进程发送指定的信号
 40                 sleep(2);//休眠两秒
 41                 printf("sending sig\n");
 42
 43         }

  

在使用自己处理信号的时候,如果不是需要修改系统预定义的信号的处理方式,最好不要使用系统已经定义好了的信号,可以使用系统预留给用户自定义的信号如10号12号等.还有一些信号是没法忽略的如SIGKILL和SIGSTOP不能忽略也不能被修改默认的执行方式.

还有用的比较多的是闹钟信号14号

#include <unistd.h>

unsignal int alarm(unsignal int seconds);

这个函数是向自己发送定时信号,默认的动作是退出程序,我们也可以自定义动作,执行周期性的操作.

int raise(int sig);//这个函数是向自己发送信号,个人感觉这个函数无关紧要

-------------------------------------------------------------------------------------------------

在实际的应用中一个应用程序需要对多个信号进行处理,为了方便,linux系统引进了信号集的概念。信号集用多个信号组成的数据类型sigset_t.可用以下的系统调用设置信号集中所包含的数据。

#include <signal.h>

int sigemptyset(sigset_t *set);//用作初始化set指向的信号集, 清空其中的所有信号.

成功则返回0, 出错则返回-1.

#include <signal.h>

int sigfillset(sigset_t *set);//初始化set指向的信号集, 填充其中的所有信号.

成功则返回0, 出错则返回-1.

#include <signal.h>

//向set指向的信号集中, 增加/删除一个signo代表的信号.

int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);

成功则返回0, 出错则返回-1.

#include <signal.h>

int sigismember(const sigset_t *set, int signo);//判断signo信号是否在set指向的信号集中.

真则返回1, 假则返回0, 出错则返回-1.

时间: 2024-10-16 18:07:24

进程间通信之信号的相关文章

进程间通信之-信号signal--linux内核剖析(九)

信号及信号来源 什么是信号 信号是UNIX和Linux系统响应某些条件而产生的一个事件.接收到该信号的进程会对应地採取一些行动.通常信号是由一个错误产生的. 但它们还能够作为进程间通信或修改行为的一种方式,明白地由一个进程发送给还有一个进程.一个信号的产生叫生成.接收到一个信号叫捕获. 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上.一个进程收到一个信号与处理器收到一个中断请求能够说是一样的. 信号是异步的.一个进程不必通过不论什么操作来等待信号的到达,其实,进程也不知道信号究竟什么

Linux系统编程——进程间通信:信号中断处理

什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFbo0_5uH5OQFr_vaRJaZ-3lq_" style="color:rgb(202,0,0); text-decoration:none">软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 . 信号能够导致一个正在执行的进程被还有一个正在执行的异

Linux进程间通信(三) - 信号

什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达.进程之间可以互相通过系统调用kill发送软中断信号.内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件.信号机制除了基本通知功能外,还可以传递附加信息. 收到信号的进程对各种信

深入理解进程间通信之信号

信号及信号源 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达. 信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了.信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息. 信号来源 信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故

进程间通信_04信号

一 概述 信号的作用是通知进程某一特定事件的发生,是一种软件中断.采用异步处理机制,即当信号发送到某个进程中的时候,操作系统会中断进程的正常处理流程,转而去进入信号处理函数进行操作,等信号处理函数完成之后,返回中断处继续执行. 信号的发送:硬件产生(按键 或者 硬件错误) .软件产生(程序调用kill.alarm等函数) 信号的处理:用户自定义函数处理.系统默认方式处理.忽略. 二 常见的信号 "动作(Action)"栏 的 字母 有 下列 含义: A  缺省动作是结束进程. B  缺

详解linux进程间通信-信号

前言:之前说看<C++ Primer >暂时搁浅一下,迷上公司大神写的代码,想要明白,主要是socket.进程间通信! 知道进程间通信:信号.信号量.管道.消息队列.共享内存(共享存储),也能写些简单代码进行通信,但不知道应用在哪?感觉很多小伙伴跟我有类似经历吧? 一.应用实例: 要去linux设备上去添加.改密用户:本地去linux设备添加用户,用socket实现,其实大神改的ssh源码来实现的,这不是我要讲的重点,而我要讲的是准备过程,去登陆linux设备,要准备好:管理员.密码等. 简略

进程间通信和线程间通信

进程间通信: # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系.# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信.# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问.它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源.因此,主要作为进程间以及同一进程内不同线程之间的同步手段.#

Linux进程间通信——使用共享内存(转)

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

Linux进程间通信——使用信号量(转)

这篇文章将讲述别一种进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同