在C中将数据从一个程序发送到另一个非阻塞程序

时间:2014-10-31 20:15:36

标签: c linux ipc nonblocking

我正在寻找有关此方案的最佳,最简单的IPC方法的建议:

  • 同一Linux服务器上的两个程序。
  • 程序1有一个变量,其中有一个整数,定期更新为不同的值,比如说每1秒。
  • 程序2需要定期从程序1中获取此值。它只需要最新值,而不是任何排队值。
  • 阅读或写作都不应该阻止。

我查看了命名管道,消息队列,Unix域套接字,但还没有找到可行的解决方案。我已经使用命名管道,但它阻止。当我尝试使用非阻塞O_NDELAY标志打开管道以便在程序1中写入时,程序2在读取时仅获得“0”。

关于如何最好地解决这个问题的任何一般性建议?

3 个答案:

答案 0 :(得分:1)

听起来像shared memory的工作。您只需将该值放在共享内存空间中即可。

答案 1 :(得分:1)

您可以使用共享内存;读/写整数在每个真实硬件上都是原子的。

当事情变得更复杂并且你想要真正的IPC时,你可以让程序A在管道或套接字中发送请求,在B中等待此消息然后返回值。

答案 2 :(得分:0)

您可以使用共享内存。以下代码提供了您描述的方案。发件人打开共享内存对象,请求mmap段,然后使用计数器将消息写入long。接收方进程与计数器一起读取消息。我把它们放在一个睡眠循环中(1)。 (请注意,应首先启动发件人)

/* sender.c */
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>


#define PATH         "/testSendRecv1234"

struct msg_s {
    int counter;
    int val;
};
typedef struct msg_s msg_s;

int main(int argc, char *argv[])
{
    int shmfd;
    int size = (sizeof(struct msg_s));
    msg_s *shared_msg;
    int counter = 0;

    /* create the shared obj */
    if (0 > (shmfd = shm_open(PATH, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG)))
        perror("shm_open()"), exit(1);

    /* make sure there is enough room */
    ftruncate(shmfd, size);

    /* request shared segment via mmap*/
    if (NULL == (shared_msg = (msg_s *) mmap(NULL, size,
                                PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)))
        perror("mmap()"), exit(1);

    /* write the message  -- in a loop */
    while (++counter < 10)
    {
        shared_msg->val = 100 + counter;
        shared_msg->counter = counter;
        sleep(1);
    }
    /* clean up: rm the shared obj*/
    if (shm_unlink(PATH) != 0)
        perror("shm_unlink()"), exit(1);

    return 0;
}

/*receiver.c*/
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>

#define PATH         "/testSendRecv1234"      

struct msg_s {
    int counter;
    int val;
};
typedef struct msg_s msg_s;
int main(int argc, char *argv[])
{
    int shmfd;
    int size = (sizeof(msg_s));
    msg_s *shared_msg;
    int counter;

    /* create the shared obj */
    if (0 > (shmfd = shm_open(PATH, O_RDWR, S_IRWXU | S_IRWXG)))
        perror("shm_open()"), exit(1);

    /* request the shared segment via mmap() */
    if (NULL == (shared_msg = (msg_s *)mmap(NULL, size,
                                PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0)))
        perror("mmap()"), exit(1);

    while (++counter < 10)
    {
        printf("Message[%d] is %d\n", shared_msg->counter , shared_msg->val);
        sleep(1);
    }

    return 0;
}

最后是Makefile:

all: receiver sender
receiver:
        gcc -Wall receiver.c -o receiver -lrt
sender: 
        gcc -Wall sender.c -o sender -lrt
clean:
        rm sender receiver

包括Linux在内的一些系统将这些函数(shm_ *)包装到posix实时库中。 出于这个原因添加了-lrt。您可以使用以下命令运行它:

$ ./sender &
$ ./receiver