笔记四:进程间的通信(信号)

通信对象:信号
用户空间是不能发送信号必须通过内核,不像前面管道通信需要创建,而是信号已经存在于内核中
linux内核总共可以发送64种信号
查看内核可以发送多少种信号:kill -l
1)A要发送信号给B,必须告诉内核要发送什么信号(信号的id号);
2)告诉内核发送给谁;(pid号)
三:信号
信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发信号,用户空间进程不能发送信号。
内核可以发送多少种信号呢?
kill  -l
命令:kill  -9 pid       或者  killall  进程名   功能: 杀死一个进程
信号通信的框架(A发送信号,B接收信号,怎么处理)
信号的发送(发送信号进程):kill raise alarm
信号的接收(接收信号进程):  pause()  sleep  while(1)
信号的处理(接收信号进程):signal
1.信号的发送(发送信号进程)
kill 函数:
 
所需头文件
#include <signal.h>
#include <sys/types.h>
函数原型
int kill(pid_t pid, int sig);
函数传入值
p id
正数:要接收信号的进程的进程号
0 :信号被发送到所有和 pid 进程在同一个进程组的进程
-1 :信号发给所有的进程表中的进程 ( 除了进程号最大的进程外 )
sig :信号
函数返回值
成功: 0
出错: -1
 kill命令的程序实现实例
/*通过命令行参数实现信号的发送 mykill.c*/
#include "signal.h"
#include "sys/types.h"
#include "stdio.h"
#include "stdlib.h"
int main(int argc,char *argv[])
{
  int pid;
  int sig;
  if(argc < 3)
        return -1;
  pid=atoi(argv[2]);//将字符串转化为整型;
  sig=atoi(argv[1]+1);
  printf("pid=%d,sig=%d\n",pid,sig);
  kill(pid,sig);
  return 0;

}
raise函数  发信号给自己 == kill(getpid(), sig)
所需头文件
#include <signal.h>
#include <sys/types.h>
函数原型
int raise(int sig);
函数传入值
sig:信号
函数返回值
成功:0
出错:-1
例子1:
#include "signal.h"
#include "sys/types.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
    printf("raise before\n");//是一个库函数,只会把raise before写入库缓存,而没有写入内核,没有加\n也不会打印
    raise(9);//_exit();
    /*当执行raise == kill -9时,下面一条语句肯定不会执行(不会打印出来)*/
    printf("raise after\n");
    return 0;
}

例子2:

#include "signal.h"
#include "sys/types.h"
#include "stdio.h"
int main()
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
    {
        printf("创建进程失败\n");
        return -1;
    }
    /*对于父进程首先是睡眠(8秒)S状态,8秒后进入R(运行)状态
      对于子进程就变成了T状态;
     */
    if(pid > 0)
    {
        sleep(8);//睡眠状态;
        while(1);
    }
    if(pid == 0)
    {
        printf("raise function before\n");
        raise(SIGTSTP);//暂停程序,相当于ctrl+z;  T状态
        printf("raise function after\n");
        exit(0);
    }
}

alarm 与 raise 函数的比较:
相同点:让内核发送信号给当前进程
不同点:1.alarm 只会发送SIGALARM信号
             2.alarm 会让内核定时一段时间之后发送信号, raise会让内核立刻发信号
所需头文件
#include <unistd.h>
函数原型
unsigned int alarm(unsigned int seconds)
函数传入值
seconds:指定秒数
函数返回值
成功:如果调用此alarm()前,进程中已经设置了闹钟时间,则
返回上一个闹钟时间的剩余时间,否则返回0。
 
出错:-1
  
信号名
含义
默认操作
SIGHUP
该信号在用户终端连接(正常或非正常)结束时发出,通常是在终端的控制进程结束时,通知同一会话内的各个作业与控制终端不再关联。
终止
SIGINT
该信号在用户键入INTR字符(通常是Ctrl-C)时发出,终端驱动程序发送此信号并送到前台进程中的每一个进程。
终止
SIGQUIT
该信号和SIGINT类似,但由QUIT字符(通常是Ctrl-\)来控制。
终止
SIGILL
该信号在一个进程企图执行一条非法指令时(可执行文件本身出现错误,或者试图执行数据段、堆栈溢出时)发出。
终止
SIGFPE
该信号在发生致命的算术运算错误时发出。这里不仅包括浮点运算错误,还包括溢出及除数为0等其它所有的算术的错误。
终止
SIGKILL
该信号用来立即结束程序的运行,并且不能被阻塞、处理和忽略。
终止
SIGALRM
该信号当一个定时器到时的时候发出。
终止
SIGSTOP
该信号用于暂停一个进程,且不能被阻塞、处理或忽略。
暂停进程
SIGTSTP
该信号用于暂停交互进程,用户可键入SUSP字符(通常是Ctrl-Z)发出这个信号。
暂停进程
SIGCHLD
子进程改变状态时,父进程会收到这个信号
忽略
SIGABORT
该信号用于结束进程
终止
3.信号的处理(接收信号进程
    收到信号的进程,应该怎样处理?
2. 信号的接收(接收信号进程)
接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束 :
sleep
pause:进程状态为S
while(1) A:忽略
B:终止进程
C: 暂停
(1)自己的处理方式:
自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用你自己的的处理方式
signal函数
所需头文件
#include <signal.h>
函数原型
void (*signal(int signum, void (*handler)(int)))(int);
函数传入值
signum:指定信号
handler:
SIG_IGN:忽略该信号。
SIG_DFL:采用系统默认方式处理信号。(终止进程)
自定义的信号处理函数指针
函数返回值
成功:设置之前的信号处理方式
出错:-1
void (*handler)(int)  =>    函数指针变量,函数的形式:含有一个整形参数,无返回值的函数
signal函数有二个参数,第一个参数是一个整形变量(信号值),第二个参数是一个函数指针,是我们自己写的处理函数;
这个函数的返回值是一个函数指针。
signal告诉内核两个内容:第一个参数:处理哪个信号 
第二个参数:采用什么方式处理这个信号(收到这个信号,先进入处理函数,再回到B中进行处理)

例子:
#include "signal.h"
#include "sys/types.h"
#include "stdio.h"
#include "stdlib.h"
void myfun(int sig)
{
  int i;
  for(i=0;i<5;i++)
  {
   sleep(1);
   printf("recv sig:%d0,i=%d\n",sig,i);
  }
  return;
}
int main()
{
  int i=0;
  /*首先程序正常运行,当用户从键盘敲入Ctrl+C时,程序将会跳转到自定义函数myfun中运行,执行完myfun程序,程序将再跳转到main函数中做自己的事(继续运行);
 
  */
  signal(SIGINT,myfun);//SIGINT信号为
SIGINT
	
该信号在用户键入INTR字符(通常是Ctrl-C)时发出,终端驱动程序发送此信号并送到前台进程中的每一个进程。
	
终止
  while(1)
  {
    sleep(1);
    i++;
     printf("main function process things,i=%d\n",i);
  }
  return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值