unix/linux进程间通信------信号

        本文主要探讨unix/linux间的一种通信方式———信号。

信号简介

        信号是一种特殊的IPC(进程间通讯),它是系统里面已经设计好的,我们只能去使用它,且是一种异步通信方式。

信号相关函数

        捕捉信号

typedef void (*sighandler_t)(int signai_num);

                参数:

                        signai_num:数字信号

        信号转为指令

sighandler_t signal(int signum, sighandler_t handler);

                参数:

                        signum:信号指令

                        handler:捕获信号函数

                常见几种信号:

                                        2    SIGINT                     键盘产生的中断(Ctrl-C)
                                        9    SIGKILL                    强制进程
                                        10    SIGUSR1                用户信号,进程可自定义用途
                                        12    SIGUSR2                用户信号,进程可自定义用途   

        信号发送       

int sigqueue(pid_t pid, int sig, const union sigval value);

                参数:

                          pid:进程号

                          sig:数字信号

                          value:信号传递的参数,大小4字节

                           union sigval {
                                               int   sival_int;      数值
                                               void *sival_ptr;    字符串
                                               };

                返回值:

                        成功执行返回0,失败返回-1

        信号接收

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

                参数:

                        signum:数字信号

                        act:新的信号处理方式

                        oldact:老的信号的处理方式 

                        struct sigaction act {
                                        void (*sa_handler)(int);
                                        void (*sa_sigaction)(int, siginfo_t *, void *);
                                        sigset_t sa_mask;
                                        int sa_flags;
                                        void (*sa_restorer)(void);
                                                        };

                        struct sigaction *oldact 对struct sigaction *act备份,不需要备份为NULL


                        sigaction(SIGINT, &oldact, NULL); 恢复成原始

                        信号处理函数可以用void (*sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t *,

                        void*),取决于sa_flags的SA_SIGINFO位,设置了采用void (*sa_sigaction)(int,

                        siginfo_t *, void *),可向处理函数发附加信息;默认采用void (*sa_handler)(int),此

                        时只能向处理函数发送信号的数值。


                        sa_handler:此参数和signal()的参数handler相同
                        sa_mask:用来设置在处理该信号时暂时将sa_mask 指定的信号集搁置。
                        sa_flags:
                                        SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置

                                        为缺省值SIG_DFL
                                        SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动

                                        该系统调用
                                        SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该

                                        给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函

                                        数运行时,内核将不会阻塞该信号                      

                        void signal_handler(int signal_num,siginfo_t *info,void *context)
 
                                 siginfo_t {
                                                      int si_signo;信号号
                                                      int si_errno;错误值
                                                      int si_code;信号代码
                                                      int si_trapno;产生的Trap号来自硬件信号(大多数架构上未使用)
                                                      pid_t si_pid;发送进程号
                                                      uid_t si_uid;发送进程的真实用户ID 
                                                      int si_status;退出值或信号
                                                      clock_t si_utime;用户使用时间
                                                      clock_t si_stime;系统消耗时间
                                                      sigval_t si_value;信号值
                                                              对应发送sigqueue中的信号内容
                                                              union sigval {
                                                                                       int   sival_int;
                                                                                       void *sival_ptr;
                                                                                      };

                                                      int si_int; POSIX.1b信号
                                                      void * si_ptr; POSIX.1b信号
                                                      int si_overrun;定时器超时次数;POSIX.1b定时器
                                                      int si_timerid;定时器ID;POSIX.1b定时器
                                                      void * si_addr;导致故障的内存位置
                                                      long si_band;band event
                                                      int si_fd;文件描述符
                                                      short si_addr_lsb;地址的最低有效位

                                                  };

demo1:

                编写信号接收程序,接收SIGINT信号不能停止的程序

程序示例:

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

void sighandler_t(int sign_num)
{
        printf("input singnal num :%d\n",sign_num);
        printf("not quit\n");
}

void result()
{
        signal(SIGINT,sighandler_t);
        while(1);
}

int main()
{
        result();
        return 0;
}

结果示例:

demo2:

                编写程序,将输入2(SIGINT),变为9(SIGKILL)信号。

程序示例:

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

void sighandler_t(int sign_num)
{

}

void result()
{
        printf("input everyone,real input singnal num : 9\n");
        signal(SIGKILL,sighandler_t);
        while(1);
}

int main()
{
        result();
        return 0;
}

结果示例:

 demo3:

                1.编写信号发送程序,发送一个int值

                2.编写信号接收程序,接收int值

发送程序:

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

void result(char  pid_input[],char sig_num_input[],char num_input[])
{
        int pid;
        int sig_num;
        int num;
        sig_num = atoi(sig_num_input);
        num = atoi(num_input);
        pid = atoi(pid_input);
        union sigval value;
        value.sival_int = num;
        sigqueue(pid,sig_num,value);
}

int main(int argc,char **argv)
{
        if(argc != 4)
        {
                printf("param is error\n");
                perror("why");
                exit(-1);
        }
        result(argv[1],argv[2],argv[3]);
        return 0;
}

接收程序:

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

void signal_handler(int signal_num,siginfo_t *info,void *context)
{
        printf("signal num is %d\n",signal_num);
        printf("get data : %d\n",info->si_int);
        printf("get data : %d\n",info->si_value.sival_int);
}

void result()
{
        printf("pid : %d\n",getpid());
        struct  sigaction act;
        act.sa_sigaction = signal_handler;
        act.sa_flags = SA_SIGINFO;
        sigaction(SIGUSR1,&act,NULL);
        sigaction(SIGKILL,&act,NULL);
        while(1);
}

int main()
{
        result();
        return 0;
}

结果示例:

demo4:

                1.编写信号发送程序,发送hello word

                2.编写信号接收程序,接收hello  word

发送程序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>

void result(char pid_input[],char sig_num_input[])
{
        char *context = "hello word";
        int pid;
        int sig_num;
        key_t key;
        int shmid;
        char *shmaddr = NULL; 
        pid = atoi(pid_input);
        sig_num = atoi(sig_num_input);
        key = ftok(".",127);
        if(key == -1)
        {
                printf("create key fail\n");
                perror("why");
                exit(-1);
        }
        shmid = shmget(key,20,IPC_CREAT|0777);
        union sigval value;
        value.sival_ptr = (void *)shmat(shmid,0,0);
        strcpy((char *)value.sival_ptr,context);
        sigqueue(pid,sig_num,value);
        sleep(10);
        shmdt(shmaddr);
}

int main(int argc,char **argv)
{
        if(argc != 3)
        {
                printf("param is error\n");
                perror("why");
                exit(-1);
        }
        result(argv[1],argv[2]);
        return 0;
}

接收程序: 

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>

void signal_handler(int signal_num,siginfo_t *info,void *context)
{
        key_t key;
        int shmid;
        key = ftok(".",127);
        if(key == -1)
        {
                printf("creat key fail\n");
                perror("why");
                exit(-1);
        }
        shmid = shmget(key,20,IPC_CREAT|0777);
        info->si_value.sival_ptr = (void *)shmat(shmid,0,0);
        printf("signal num : %d\n",signal_num);
        if(context != NULL)
        {
                printf("get context : %s\n",info->si_value.sival_ptr);
        }
    shmctl(shmid,IPC_RMID,NULL);
        shmdt(info->si_value.sival_ptr);
}

void result()
{
        struct sigaction act;
        act.sa_sigaction = signal_handler;
        act.sa_flags = SA_SIGINFO;
        sigaction(SIGUSR1,&act,NULL);
        sigaction(SIGKILL,&act,NULL);
        while(1);
}

int main()
{
        printf("pid : %d\n",getpid());
        result();
        return 0;
}

结果示例:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值