Linux进程间通信之信号

Linux进程间通信之信号

一:信号
信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发信号,用户空间进程不能发送信号。信号其实已经在内核存在了。
内核可以发送多少种信号呢?
kill -l
64种
命令:kill -9 pid
注:1.告诉内核发送什么信号;
2.告诉内核发给谁。
信号通信的框架
信号的发送(发送信号进程):kill raise alarm
信号的接收(接收信号进程) : pause() sleep while(1)//这3中方式可以
信号的处理(接收信号进程) : signal

1.信号的发送(发送信号进程)
kill :
头文件 #include <signal.h>
#include <sys/types.h>
函数原型 int kill(pid_t pid, int sig);
函数传入值
pid: 正数:要接收信号的进程的进程号
0:信号被发送到所有和pid进程在同一个进程组的进程
-1:信号发给所有的进程表中的进程(除了进程号最大的进程外)
sig:信号
函数返回值
成功:0
出错:-1

raise: 发信号给自己 == kill(getpid(), sig)
头文件 #include <signal.h>
#include <sys/types.h>
函数原型 int raise(int sig);
函数传入值 sig:信号
函数返回值
成功:0
出错:-1

#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{ 
  //没有加\n就会出现没有显示
  //数据写到了行缓存中去了的
  printf("raise before");
  raise(9);// _exit()相当于raise,不刷新缓存
  		   // exit()会把上面在行缓存中的数据发给内核,然后输出
  printf("raise after\n");
  return 0;
}

在这里插入图片描述

#include "stdio.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
  pid_t pid;
  pid=fork();
  if(pid > 0 )
  {
    sleep(8);
    //WNOHANG以非阻塞调用,没有子进程状态发生改变
    //waitpid不阻塞立即返回此时的返回值为0
	if(waitpid(pid,NULL,WNOHANG) == 0)
	{
	  kill(pid,9);//杀死子进程
	}
	//回收僵尸态子进程,如果没有僵尸态子进程
	//则阻塞,null是指忽略子进程退出的状态
	wait(NULL);
	while(1);
  }
  if(pid ==  0)
  {
   printf("raise function before\n");
   raise(SIGTSTP);
   printf("raise funtion after\n");
   exit(0);
  }
  return 0;
}

在这里插入图片描述
alarm : 发送闹钟信号的函数:
alarm 与 raise 函数的比较:
相同点:让内核发送信号给当前进程
不同点:
1.alarm 只会发送SIGALARM信号
2.alarm 会让内核定时一段时间之后发送信号, raise会让内核立刻发信号

所需头文件 #include <unistd.h>
函数原型 unsigned int alarm(unsigned int seconds)
函数传入值 seconds:指定秒数
函数返回值 成功:如果调用此alarm()前,进程中已经设置了闹钟时间,则
返回上一个闹钟时间的剩余时间,否则返回0。
出错:-1

在这里插入图片描述
2. 信号的接收(接收信号进程)
接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束 :
sleep
**pause:**进程状态为S(运行到这里会给当前进程发睡眠状态并一直处于睡眠状态)
while(1)
所需头文件 #include <unistd.h>
函数原型 int pause(void);
函数返回值 成功:0,出错:-1

#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>

int main()
{ 
  int i;
  i=0;
  printf("pause before\n");
  pause();
  printf("pause after\n");
  while(i< 20)
  {
	i++;
	sleep(1);
	printf("process things,i=%d\n",i);
  }
  return 0;
}

在这里插入图片描述
3.信号的处理(接收信号进程)
收到信号的进程,应该怎样处理? 处理的方式:
(1)进程的默认处理方式(内核为用户进程设置的默认处理方式)
A:忽略
B:终止进程
C: 暂停
(2)自己的处理方式:
自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用你自己的的处理方式

所需头文件 #include <signal.h>
函数原型 void (*signal(int signum, void (*handler)(int)))(int);
函数传入值 signum:指定信号(告诉内核处理哪一个信号)
handler: 告诉
内核用什么方法去处理
SIG_IGN:忽略该信号。
SIG_DFL:采用系统默认方式处理信号。
自定义的信号处理函数指针
函数返回值
成功:设置之前的信号处理方式
出错:-1

signal 函数有二个参数,第一个参数是一个整形变量(信号值),第二个参数是一个函数指针,是我们自己写的处理函数;
void (*handler)(int)是一个函数指针变量,函数的形式:含有一个整型参数,无返回值的函数,
这个函数的返回值是一个函数指针。

#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>

void myfun(int signum)
{
  int i;
  i=0;
  while(i < 5)
  {
	printf("process signal signum=%d\n",signum);
	sleep(1);
	i++;
  }
  //信号处理函数处理完之后就回到主函数中继续运行
  return; // return main

}
int main()
{ 
  int i;
  i=0;
  //9s后alarm发的14号信号后,执行信号处理函数
  signal(14,myfun);
  printf("alarm before\n");
  //alarm会给内核发SIGALRM(14号信号)
  alarm(9);
  printf("alarm after\n");
  while(i< 10)
  {
	i++;
	sleep(1);
	printf("process things,i=%d\n",i);
  }
  return 0;
}

在这里插入图片描述

#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>

void myfun(int signum)
{
  int i;
  i=0;
  while(i < 10)
  {
	printf("process signal signum=%d\n",signum);
	sleep(1);
	i++;
  }
  return; // return main
}
int main()
{ 
  int i;
  i=0;
  signal(14,myfun);
  printf("alarm before\n");
  alarm(9);
  printf("alarm after\n");
  signal(14,SIG_IGN);
  signal(14,SIG_DFL); //系统会以这条为最新的信号函数去执行,以默认的方式去处理9号信号的
  while(i< 20)
  {
	i++;
	sleep(1);
	printf("process things,i=%d\n",i);
  }
  return 0;
}

在这里插入图片描述
利用信号实现进程间的通信

#include "stdio.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

void myfun(int signum)
{
  int i;
  i=0;
  while(i <2)
  {
	printf("receive signum=%d,i=%d\n",signum,i);
	sleep(1);
	i++;
  }
  return;
}
void myfun1(int signum)
{
  printf("receive signum=%d\n",signum);
  wait(NULL);
  return ;
}

int main()
{
  pid_t pid;
  pid=fork();
  if(pid > 0 )
  {
	int i;
	i=0;
	signal(10,myfun);
	signal(17,myfun1);
	while(1)
	{
     printf("parent process things,i=%d\n",i);
	 sleep(1);
	 i++;
	}
  }
  if(pid ==  0)
  {
	sleep(5);
	kill(getppid(),10);
	sleep(5);
	exit(0);//kill(getppid(),17)
  }
  return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值