Linux进程间通信(二)--- 信号机制

信号方式

软中断信号Signal,简称信号,用来通知进程发生了异步时间。
进程之间可以通过系统调用kill等函数来发送软中断信号,通知进程发生了某个事件,但信号只能用来通知进程发生了什么事件,并不给该进程传递任何数据
信号是异步的,一个进程不必通过任何操作来等待信号的到达

信号处理的三个过程:发送信号、接收信号、处理信号

信号处理的三种方式:

  • 忽略此信号:大多数信号都可以忽略,但是SIGKILL和SIGSTOP不可忽略
  • 捕捉信号:通知内核在某种信号发生时,调用用户的函数来处理时间
  • 执行系统默认动作:大多数信号的默认动作是终止该进程,可以使用man 7 signal查看默认信号。可以使用 kill –l(字母l)列出系统支持的信号 ,其中信号值小于34都是不可靠信号。
    在这里插入图片描述
一、使用
  • 头文件:#include <signal.h>
  • 函数原型:void (*signal(int sig, void (*func)(int)))(int),
  • 函数返回信号处理程序之前的值,当发生错误时返回 SIG_ERR
  • 参数说明
    sig:在信号处理程序中作为变量使用的信号码,可自定义
    func:一个指向信号处理函数的指针,可自定义
    常用的预定义信号处理函数为SIG_DFL,SIG_IGN(忽略此信号)
二、演示程序
1、程序一

Test3-1-2中自定义几个信号处理函数,其中部分是截获后打印信息,程序继续;部分是截获后打印信息,程序退出。
Test3-1-1中定时向test3-1-2发送相应的信号,同时可以通过控制台手工向test3-1-2发送相应的信号。

//test3-1-1
#include <signal.h> 
#include <stdlib.h> 
#include <stdio.h>  
#include <unistd.h>  
#include <string.h>
#define SIGPRINT_CONTINUE 34  //自定义信号,大于34的信号量都是未定义的,可使用
#define SIGPRINT_TERM 35  
int main()  
{  
	//fork子进程后父进程退出,创建守护进程
    pid_t pid1;
    pid1=fork();
    if(pid1==-1||pid1>0)
        return 0;   

    //获取test3-1-2的pid号
    int pid;
    FILE *fp = popen("ps -e | grep \'test3-1-2\' | awk \'{print $1}\'","r");
    char buffer[10] = {0};
    fgets(buffer, 10, fp);
    pid=atoi(buffer);

    kill(pid,SIGPRINT_CONTINUE); //向test3-1-2发送SIGPRINT_CONTINUE信号
    sleep(10);
    kill(pid,SIGPRINT_TERM); ////向test3-1-2发送SIGPRINT_TERM信号
    while(1)
        sleep(1);
}
#include <signal.h>  
#include <stdio.h> 
#include <stdlib.h>  
#include <unistd.h>  
#define SIGPRINT_CONTINUE 34
#define SIGPRINT_TERM 35  

/*信号SIGPRINT_CONTINUE的处理函数*/
void print_continue(int sig)  
{  
    printf("\nWARNING! - I got signal %d\n", sig); 
    printf("I need to print something and continue running!\n");      
}  

/*信号SIGPRINT_TERM的处理函数*/
void print_term(int sig)  
{  
    printf("\nWARNING! - I got signal %d\n", sig);  
    printf("End\n");
    exit(0);
}  

/*相应键盘输出产生的中断的处理函数*/
void replyKeyInput(int sig)
{
    printf("\nWARNING - I got signal %d\n", sig); 
    (void) signal(SIGINT, SIG_DFL); 
}

int main()  
{  
    pid_t pid;
    pid=fork();
    if(pid==-1||pid>0)
        return 0;   
    
    (void) signal(SIGPRINT_CONTINUE,print_continue); 
    (void) signal(SIGPRINT_TERM, print_term);
   
     //改变终端中断信号SIGINT的默认行为,使之执行replyKeyInput函数  
    (void) signal(SIGINT, replyKeyInput);
    while(1)  
        sleep(1);  
}  

运行结果:
在这里插入图片描述
在这里插入图片描述

2、程序二

Test3-2-1写文件(此时test3-2-2延时等待)后用自定义的特定信号通知test3-2-2去读,自己变为延时等待状态;
test3-2-2收到此信号后去读文件的内容,读取后清空文件,写入新的内容,再用自定义的特定信号通知3-2-1去读,自己变为演示等待状态。

//test3-2-1
#include <signal.h> 
#include <stdlib.h> 
#include <stdio.h>  
#include <unistd.h>  
#include <string.h>
#define SIGFILEREADY 34  //自定义信号量34为文件已准备信号
#define FILE_PATH "myfile"
#define BUFSIZE 50
#define HIS "test3-2-2"

char buffer[BUFSIZE];
int pid=0;

/*信号SIGFILEREADY的处理函数*/
void opFile(int sig)
{
	//收到信号表示对方写完成,我方可读取数据
	printf("It is test3-2-1 reading file...\n");
	FILE *fp=fopen(FILE_PATH,"r+");
	fgets(buffer,BUFSIZE,fp);
	printf("[Data]:%s\n\n",buffer);
	fclose(fp);

	sleep(1);
	
	fp=fopen(FILE_PATH,"w+");
	fputs("Hello,test3-2-2!These data is writen by test3-2-1!",fp);
	fclose(fp);

	sleep(1);
	//写完成后向对方发送SIGFILEREADY信号
	kill(pid,SIGFILEREADY);
} 

int main()  
{  
	//fork子进程后父进程退出,创建守护进程
    pid_t pid1;
    pid1=fork();
    if(pid1==-1||pid1>0)
        return 0;   

	FILE *fp=fopen(FILE_PATH,"w+");
	fputs("Hello,test3-2-2!These data is writen by test3-2-1!",fp);
	fclose(fp);
	
	sleep(1);

	fp=fopen(FILE_PATH,"r+");
	fgets(buffer,BUFSIZE,fp);
	printf("INIT DATA:%s\n",buffer);
	fclose(fp);
	
	sleep(1);

    while(pid<=0)
    {
    	//获取test3-2-2的pid号
        FILE *fp = popen("ps -e | grep \'test3-2-2\' | awk \'{print $1}\'","r");
        char buf[10] = {0};
        fgets(buf, 10, fp);
        pid=atoi(buf);
    }
    sleep(1);
    (void)signal(SIGFILEREADY,opFile);
	kill(pid,SIGFILEREADY);
    while(1)
    	sleep(1);
    
}  


//test3-2-2
#include <signal.h> 
#include <stdlib.h> 
#include <stdio.h>  
#include <unistd.h>  
#include <string.h>
#define SIGFILEREADY 34 //自定义信号量34为文件已准备信号
#define FILE_PATH "myfile"
#define BUFSIZE 50
#define HIS "test3-2-1"

char buf[BUFSIZE];
int pid=0;

/*信号SIGFILEREADY的处理函数*/
void opFile(int sig)
{
	printf("It is test3-2-2 reading file...\n");
	FILE *fp=fopen(FILE_PATH,"r+");
	fgets(buf,BUFSIZE,fp);
	printf("[Data]:%s\n\n",buf);
	fclose(fp);

	sleep(1);
	
	fp=fopen(FILE_PATH,"w+");
	fputs("Hello,test3-2-1!These data is writen by test3-2-2!",fp);
	fclose(fp);

	sleep(1);
	kill(pid,SIGFILEREADY);
} 

int main()  
{  
	//fork子进程后父进程退出,创建守护进程
    pid_t pid1;
    pid1=fork();
    if(pid1==-1||pid1>0)
        return 0;   

	while(pid<=0)
    {
    	//获取test3-2-1的pid号
        FILE *fp = popen("ps -e | grep \'test3-2-1\' | awk \'{print $1}\'","r");
        char buf[10] = {0};
        fgets(buf, 10, fp);
        pid=atoi(buf);
    }
    
    (void)signal(SIGFILEREADY,opFile);
    while(1)
    	sleep(1);
    
}  


运行结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Tong_jy/article/details/86620710