如何在 C 中实现消息传递 IPC?

How do implement message passing IPC in C?

我正在尝试编写一个程序来实现父进程和子进程之间的基本消息传递。我以前从未使用过 C,所以在过去的两天里我一直在摸索和阅读教程,但我似乎无法让它工作。我最多只能创建无错误的消息队列。 这是我的代码,评论了我对我在做什么的最佳理解:

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>

//this is the structure of the message i'm sending to the queue
struct message
{
    long messagetype;
    char text[10];
}; 

int main()
{

    key_t key = 2222;
    int msqid = msgget(key, IPC_CREAT); //create a message queue with the key


    pid_t parentpid = getpid();
    pid_t childpid = fork(); //these are mostly unused for now
    if(childpid < 0) //fork failed
    {
        printf("fork failed\n");
        return 1;
    } else if(childpid == 0) //in child process
    {
        struct message sndmsg; //create a message to be send to the queue
        printf("input message\n"); 
        scanf("%s", sndmsg.text);  //get the messages text fro input
        printf("Sending message to queue: %s\n", sndmsg.text); 
        sndmsg.messagetype = 1; //set message type to 1
        if(msgsnd(msqid, &sndmsg, sizeof(sndmsg.text), 0) < 0 ) // no idea what the last parameter really means here. check if message send fails 
        {
            printf("error sending message\n");
        } else
        {
            printf("sent message with text: %s\n",sndmsg.text);
        }

        printf("child process\n");
    } else
    {
        wait(NULL); //wait until child process is done
        struct message rcvmsg; //create a message to recieve the test from the queue
        rcvmsg.messagetype = 1; //matching the message type here
        if(msgrcv(msqid, &rcvmsg, sizeof(rcvmsg.text), 1, 0) < 0) //again, no idea what the last parameter does here. Checking to see if message recieve fails.
        {
            printf("error recieving message\n");
        } else
        {
        printf("recieved message text : %s\n", rcvmsg.text);
        }
        printf("Parent process\n");
    }
    return 0;
}

当我 运行 时,我的消息发送和接收都失败了。我完全不明白 IPC_CREATE、IPC_NOWAIT 等的含义。通常就是最后一个参数在 msgsnd 和 msgrcv 中的作用。在示例中,我看到人们使用 0660 | IPC_CREAT,没有解释 0660 是什么。任何人都可以阐明我在我的代码中做错了什么,或者一般性地为通常使用 C# 和 Java 的人解释在 C 中传递的消息,因为现在它基本上是黑魔法。到目前为止,我发现的每一个资源或教程一旦达到某个点就会让我头疼。谢谢

你不实现 Inter Process Communication in pure standard C, because the C11 standard (read n1570) 不知道它们,因为任何 IPC 设施都是特定于操作系统的(特别是 Windows 与 Linux) 上的非常不同。

但是,一些操作系统提供进程间通信设施。然后你可以使用它们(不需要实现它们),当然是以某种OS特定的方式。

在 Linux 上,更喜欢使用 POSIX 消息工具(而不是 svipc(7)), see mq_overview(7). Be also aware of pipe(7), fifo(7), socket(7), unix(7), signal(7), shm_overview(7), sem_overview(7) 中记录的旧 SystemV IPC(因为有很多方法可以进行进程间通信).

I am completely lost on what IPC_CREATE means

你需要先阅读svipc(7),上面写着:

IPC_CREAT Create entry if key doesn't exist.

那你问:

Can anybody shed some light on what I'm doing wrong in my code

您忘记了针对失败进行测试(另请参阅 errno(3) & perror(3) & strerror(3)). Every function you are using is documented (and you should read that documentation) and can fail (and you need to handle somehow the failure case). Read first msgget(2) 然后通过添加适当的检查进行编码,因此至少:

 int msqid = msgget(key, IPC_CREAT);
 if (msgid<0) { perror("msgget"); exit(EXIT_FAILURE); }

同样适用于您使用的所有其他系统功能。

不要忘记仔细阅读您使用的每个功能的man页面。另见 man(1).

收到错误消息后,您将能够再次参考文档并改进您的代码。

您可以使用 strace(1) (which gives every system call -listed in syscalls(2)- 由某些进程或命令完成)来了解正在发生的事情。

您需要花几天或几周的时间阅读更多关于 C 编程和 Unix 系统编程的内容(例如阅读旧的 ALP or something newer). You should also read something on OSes, e.g. Operating Systems: Three Easy Pieces(可免费下载)。

what 0660 is

可能与文件访问和权限有关(八进制 0660 可能对应于 rw-rw----)。另见 credentials(7), chmod(2), stat(2), inode(7).

PS。在更改一行代码之前,您确实需要阅读数天或数周的时间,并且一旦您了解更多如何对 Linux 系统进行编程,您最好从头开始。

还可以从与您的关注点和兴趣相关的 现有 free software projects (e.g. on github) 中寻找灵感。