sigqueue与sigaction在不同进程间传递字符串

zzLINUX信号通信---不同进程间发送与接收携带字符串的信号(使用共享内存机制)_sigaction如何接收字符串-CSDN博客

问题的发现:不同进程如何传字符串

上面的博文中也提出了一样的问题

在学习信号的时候我曾在不同进程之间通过sigqueue和sigaction传递整型,然后尝试传递字符串的时候一直出现段错误

程序和实验结果如下:

下面是接收端的程序:

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


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

/*调用handler函数之后先打印信号的值,打印完之后判断携带的内容是否为空,非空的话打印info中的si_int,

*/


void handler(int signum,siginfo_t *info,void *context)
{
        printf("get signum = %d\n",signum);

        if(context != NULL)//判断携带内容是否为空
        {
                printf("the pid is:%d\n",getpid());
                printf("get data:%s\n",(char *)info->si_ptr);
        }

}

int main()
{
        struct sigaction act;

        act.sa_sigaction = handler;//收到信号之后调用handler处理信号
        act.sa_flags = SA_SIGINFO;//必须指定,以能够获得数据


        sigaction(SIGUSR1,&act,NULL);


        while(1);
        return 0;
}

这是发送端的程序:

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


int main(int argc,char **argv)
{
        int signum;
        int pid;
        char *p ="zcy,cool!";

        signum = atoi(argv[1]);
        pid = atoi(argv[2]);


        union sigval value;
        value.sival_ptr = p;

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

        sigqueue(pid,signum,value);


        printf("传输内容:%p\n",value.sival_ptr);

        return 0;
}
~               

但是当我打印发送和接受的字符串地址的时候确实可以正常打印,这说明数据确实传过去了,但是一旦强制类型转换然后 %s 输出成字符串就会出现段错误

打印地址时的结果:

打印字符串时的结果:

于是我又找到了这篇博文讲得很好,本质原因就是不同进程之间传递字符串必须要用 共享内存 来传递。

尝试通过共享内存解决问题

下面我尝试创建一个共享内存区域然后传递一下字符串试试:

老样子,先说结论:实验成功了

因为我叫zcy,所以自恋传了个我真帅

这个程序本质其实就是如何结合共享内存和不同进程传递函数sigaction及sigqueue

思路如下:

我需要写两个进程:分别是接收进程和发送进程

发送进程:

1、创建key值

2、通过key创建共享内存

3、定义好sigqueue函数需要的参数

4、将sigqueue函数中的联合体结构的void类型指针与共享内存连接起来,这样我往指针中传字符串,也会写到共享内存中

接收进程:

1、创建相同的key值

2、通过key值连接共享内存

3、定义好sigaction所需要的各个参数

4、连接sigaction中的info_t类型结构体中的void类型指针与共享内存连接起来,这样我可以直接读取该指针中的内容,需要注意强制类型转换

下面是发送进程的程序:

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

int main(int argc,char **argv)
{
        char *src = "zcy,cool!";
        int signum;
        int pid;

        union sigval value;
        //创建一个key值
        int key = ftok(".",3);

        if(key == -1)
        {
                printf("ftok failed\n");
                perror("ftok");
                exit(-1);
        }
        printf("key:%d\n",key);
        //创建共享内存
        int shm_id = shmget(key,1024,IPC_CREAT|0777);
        if(shm_id == -1)
        {
                printf("shmget failed\n");
                perror("shmget");
                exit(-1);
        }else
                printf("shmget success\n");
        //连接共享内存(重点)
        value.sival_ptr=(void *)shmat(shm_id,0,0);
        if(value.sival_ptr == (void *)-1)
        {
                printf("shmat failed\n");
                perror("shmat");
        }else
                printf("shmat success\n");
        //往共享内存中传字符串
        strcpy(value.sival_ptr,src);

        printf("strcpy success\n");

        signum = atoi(argv[1]);
        pid = atoi(argv[2]);


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

        sigqueue(pid,signum,value);


        printf("传输内容:%p\n",value.sival_ptr);

        return 0;
}

下面是接收进程的程序:

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


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

/*调用handler函数之后先打印信号的值,打印完之后判断携带的内容是否为空,非空的话打印info中的si_int,

*/

//信号处理函数
void handler(int signum,siginfo_t *info,void *context)
{
        //创建同一个key值
        key_t key;
        key = ftok(".",3);

        //连接共享内存
        int shm_id = shmget(key,1024,0);
         if(shm_id == -1)
        {
                printf("shemget failed\n");
                perror("shmget");
                exit(-1);
        }else
                printf("shmget success\n");
        //连接共享内存(重点)
        info->si_ptr =(void *) shmat(shm_id,0,0);
        if(info->si_ptr == (void *)-1)
        {
                printf("shmat failed\n");
                perror("shmat");

​}else
                printf("shmat success\n");

        printf("get signum = %d\n",signum);

        if(context != NULL)//判断携带内容是否为空
        {
                printf("the pid is:%d\n",getpid());
                printf("get data:%s\n",(char *)info->si_ptr);
        }

}

int main()
{

        struct sigaction act;

        act.sa_sigaction = handler;//收到信号之后调用handler处理信号
        act.sa_flags = SA_SIGINFO;//必须指定,以能够获得数据


        sigaction(SIGUSR1,&act,NULL);


        while(1);
        return 0;
}

 如果你掌握了sigaction和sigqueue函数的基本用法以及如何创建连接共享内存的方法,上面的代码还是比较好理解的,我个人觉得最头疼的还是sigaction函数中有太多的参数,而且我还没完全搞懂每个参数那么多选择的用法都是什么,只掌握了基本的使用方法,本文只是我刚入门这一块的一段历程,如有误请各位大佬多多指正,谢谢!

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值