在树莓派上用 C++ 从一个 Linux 应用程序到另一个应用程序的最简单 IPC

Posted

技术标签:

【中文标题】在树莓派上用 C++ 从一个 Linux 应用程序到另一个应用程序的最简单 IPC【英文标题】:Simplest IPC from one Linux app to another in C++ on raspberry pi 【发布时间】:2020-01-10 23:09:20 【问题描述】:

我需要最简单最可靠的 IPC 方法,从 RPi 上运行的一个 C++ 应用程序到另一个应用程序。

我要做的只是从一个应用程序向另一个应用程序发送一条 40 个字符的字符串消息

第一个应用程序在启动时作为服务运行,另一个应用程序稍后启动,并且经常退出并重新启动以进行调试

第二个应用程序的频繁调试是我迄今为止尝试过的 IPC 出现问题的原因

我尝试了大约 3 种不同的方法,但都失败了:

    文件 FIFO,问题是一个程序挂起,而另一个程序正在写入文件

    共享内存:无法在一个线程上初始化并从另一个线程读取。调试时频繁退出导致 GDB 崩溃the following GDB command is taking too long to complete -stack-list-frames --thread 1

    带有 localhost 的 UDP 套接字 - 与上述相同的问题,加上不正确的退出会阻塞套接字,迫使我重新启动设备

    非阻塞管道 - 在接收进程中没有收到任何消息

我还能尝试什么?我不想得到 DBus 库,对于这个应用程序来说似乎太复杂了。

任何简单的服务器和客户端代码或指向它的链接都会有所帮助

这是我的非阻塞管道代码,对我不起作用, 我认为是因为我没有引用从一个应用程序到另一个应用程序的管道

代码来自这里:https://www.geeksforgeeks.org/non-blocking-io-with-pipes-in-c/

char* msg1 = "hello"; 
char* msg2 = "bye !!"; 
int p[2], i;

bool InitClient()
   
    // error checking for pipe 
    if(pipe(p) < 0) 
        exit(1); 

    // error checking for fcntl 
    if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0) 
        exit(2); 

    //Read
    int nread; 
    char buf[MSGSIZE]; 

    // write link 
    close(p[1]); 

    while (1)  

        // read call if return -1 then pipe is 
        // empty because of fcntl 
        nread = read(p[0], buf, MSGSIZE); 
        switch (nread)  
        case -1: 

            // case -1 means pipe is empty and errono 
            // set EAGAIN 
            if(errno == EAGAIN)  
                printf("(pipe empty)\n"); 
                sleep(1); 
                break; 
             

        default: 

            // text read 
            // by default return no. of bytes 
            // which read call read at that time 
            printf("MSG = % s\n", buf); 
         
     

    return true;
   

bool InitServer()
      
    // error checking for pipe 
    if(pipe(p) < 0) 
        exit(1); 

    // error checking for fcntl 
    if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0) 
        exit(2); 


    //Write
    // read link 
    close(p[0]); 

    // write 3 times "hello" in 3 second interval 
    for(i = 0 ; i < 3000000000 ; i++)  
        write(p[0], msg1, MSGSIZE); 
        sleep(3); 
     

    // write "bye" one times 
    write(p[0], msg2, MSGSIZE); 

    return true;
       

【问题讨论】:

您在共享内存方面遇到了什么问题——您尝试了什么?看看boost.interprocesstheboostcpplibraries.com/… FIFO 或具有非阻塞 io 的 Unix 域套接字。 非阻塞管道是更好的方法之一。添加您用于此的代码,有人可能会让您知道出了什么问题。 Geeks for geeks 管道代码会向控制台发送垃圾邮件,其中包含“(管道为空)”消息,因此很难查看您是否真的收到了消息。显然,对于您的实际情况,这不是一个好主意,但对于测试,请考虑向客户端循环添加半秒睡眠。在您的实际程序中,您将轮询管道以查看数据是否在其他任务之间定期到达。 Redis 非常简单,您可以使用 C/C++、Python、php 或 bash 命令行注入或读取它,因此调试起来很简单...***.com/a/58521903/2836621 【参考方案1】:

请考虑 ZeroMQ

https://zeromq.org/

它是轻量级的,并且包含所有主要编程语言的包装器。

【讨论】:

以上是关于在树莓派上用 C++ 从一个 Linux 应用程序到另一个应用程序的最简单 IPC的主要内容,如果未能解决你的问题,请参考以下文章

在树莓派上用Python控制LED

在树莓派上用PyQt5写GUI出现视频卡死

linux上用 apt-get install命令安装的包是放在哪个文件夹的?可以提取出来放到另一

教你树莓派4B的系统备份方法教程大全(全卡+压缩备份)

树莓派用啥版本的Linux

如何从0到1构建32Core树莓派集群