[置顶] Linux 下进程间通信机制(三) 信号Signal


信号的响应函数
void(*signal(int signum, void(*handler)(int)))(int);


解释:
signum:指定的信号(系统支持的)
handler:可能的取值有三种 SIG_IGN(忽略该信号)   SIG_DFL(系统默认操作) 自定义的处理函数指针
成功: 返回上一次设置的函数指针

失败:-1


demo1:

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

typedef void(*pFunc)(int);

void myhandler1(int signo)
{
    printf("myhander1 signo:%d\n", signo);
}


void myhandler2(int signo)
{
    printf("myhander2 signo:%d\n", signo);
}

int main()
{
    pFunc hander1, hander2;

    hander1 = signal(14, myhandler2);//第一次设置响应函数
    hander2 = signal(14, myhandler1); //设置信号响应函数,返回上一次设置的响应函数指针,但不会返回默认。
    alarm(5);//SIGALARM已经被设置响应函数 打印myhander1 signo:14
    pause();
    //hander1(100);//这里并没有返回默认的响应函数,会出现段错误
    hander2(100); //打印myhander2 signo:100
    printf("exit\n");//如果不设置14的响应函数,默认为关闭,所以这句不会被执行
    return 0;
}


司机售票员问题:


创建子进程代表售票员,父进程代表司机,同步过程如下:
售票员捕捉SIGINT(代表开车),发SIGUSR1给司机,司机打印("let's gogogo")
售票员捕捉SIGQUIT(代表停车),发SIGUSR2给司机,司机打印("stop the bus")
司机捕捉SIGTSTP(代表车到总站),发SIGUSR1给售票员,售票员打印("please get off the bus")

信号处理:

一、司机:
捕捉:SIGUSR1  SIGUSR2  SIGTSTP
忽略:SIGINT  SIGQUIT


二、售票员:
捕捉:SIGINT  SIGQUIT  SIGUSR1
忽略:SIGTSTP


demo2:

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

int pid;//pid设置为全局,子进程中等于0,父进程中为子进程的pid


//响应函数
void sellersigint(int signo)
{
    kill(getppid(),SIGUSR1);
}

void driversigusr1(int signo)
{
    printf("let's gogogo\n");
}


void sellersigquit(int signo)
{
    kill(getppid(),SIGUSR2);
}


void driversigusr2(int signo)
{
    printf("stop the bus\n");
}


void sellersigusr1(int signo)
{
    printf("please get off the bus\n");
}


void driversigtstp(int signo)
{
    kill(pid,SIGUSR1);
}

int main()
{

    if((pid=fork()) == -1)
    {
        perror("error");
        exit(1);
    }
    
    if(pid > 0)//driver
    {
        signal(SIGINT,SIG_IGN); //父进程(司机)忽略SIGINT信号(Ctrl + c)
        signal(SIGUSR1,driversigusr1);//设置父进程对SIGUSR1信号的响应函数

        signal(SIGQUIT,SIG_IGN);  //父进程(司机)忽略SIGQUIT信号(Ctrl + \)
        signal(SIGUSR2,driversigusr2);  //设置父进程对SIGUSR2信号的响应函数

        signal(SIGTSTP,driversigtstp);  //设置父进程(司机)对SIGSTSP信号(Ctrl + z)的响应函数
        while(1);
    }
    else  //seller
    {
        signal(SIGINT, sellersigint);//设置子进程(售票员)对SIGINT信号(Ctrl + c)的响应函数
        signal(SIGQUIT,sellersigquit); //设置子进程(售票员)对SIGQUIT信号(Ctrl + \)的响应函数
       
        signal(SIGTSTP,SIG_IGN);  子进程(售票员)忽略SIGTSTP信号(Ctrl + z)
        signal(SIGUSR1,sellersigusr1); 设置子进程(售票员)对SIGUSR1信号的响应函数
        while(1);
    }
}

更加精简的demo2:

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

pid_t pid;

void conductor_handler(int signo);
void driver_handler(int signo);

int main()
{

    if((pid = fork()) < 0){ 
        perror("fork error.\n");
    }
    else if(pid == 0){ 
        signal(SIGTSTP,SIG_IGN);   
        signal(SIGINT,conductor_handler);
        signal(SIGQUIT,conductor_handler);
        signal(SIGUSR1,conductor_handler);
        while(1){
            pause();
        }
    }
    else{  
        signal(SIGINT,SIG_IGN); 
        signal(SIGQUIT,SIG_IGN);  

        signal(SIGTSTP,driver_handler);
        signal(SIGUSR1,driver_handler);
        signal(SIGUSR2,driver_handler);
        while(1){
            pause();
        }
    }

    return 0;
}

void conductor_handler(int signo)
{
    switch(signo)
    {
    case SIGINT :
        kill(getppid(),SIGUSR1);
        break;
    case SIGQUIT:
        kill(getppid(),SIGUSR2);
        break;
    case SIGUSR1:
        printf("Final station ,all get off.\n");
        exit(0);    
    }
}

void driver_handler(int signo)
{
    switch(signo)
    {
    case SIGTSTP :
        kill(pid,SIGUSR1);
        wait(NULL); 
        exit(0);
    case SIGUSR1 :
        printf("bus will run...\n");
        break;
    case SIGUSR2 :
        printf("bus will stop...\n");
        break;
    }
}


你可能感兴趣的:(c,linux,kill,null,Signal)