c - Fork() 和 Posix 队列。发送和接收字符串

标签 c process queue fork posix

我想要的是这样的: 1 个创建 4 个子进程的主进程,其中: -> 主进程通过队列接收来自子进程的消息并打印收到的消息。 -> children 通过队列发送消息(带有优先级的字符串+消息)并完成。 一切都在一段时间内 (1),因此,当您按下 CTRL+C 时,子级首先完成(信号位于子级代码中),然后父级完成。 目前,我在 mq_send() 和 mq_recieve() 方面遇到问题。 好吧,这是我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <mqueue.h>

void sigint_handler()
{
  /*do something*/
  printf("killing process %d\n",getpid());
  exit(0);
}

int main ()
{

    mqd_t mqd;

    struct mq_attr atributos;

//     atributos.mq_maxmsg = 10;
//     
//     atributos.mq_msgsize = 50;

  printf ("This is the parent. PID=%d\n",getpid ());

  int num_children = 4;

  int i;
  int pid;
  int status;

  char buffer [50];

  while (1){



    for (i=0; i<num_children ;i++){

      if ((pid=fork()==0)){

      signal(SIGINT, sigint_handler);


      int prio = rand () % 3;

      printf ("%d\n",prio);

      char * msg= "Hi dude";

      char * priority=NULL;

      if (prio == 0){

        priority = "NORMAL";

      }
       else {

        priority = "URGENT";

      }
      char* toSend=NULL;

     toSend = malloc(strlen(msg)+1+strlen(priority));

       strcpy (toSend,priority);
       strcat (toSend,msg);

      printf ("%s\n",toSend);


      if ((mqd=mq_open("/queue.txt", O_CREAT|O_WRONLY, 0777, &atributos))==-1){

      printf ("Error mq_open\n");

      exit(-1);

    }

    if (mq_send(mqd, msg , strlen(toSend), prio) == -1) {

      printf ("Error mq_send\n");

      exit (-1);


    }


      mq_close(mqd);




    printf ("This is children %d\n",getpid()); 

    sleep(1);

    exit(0);

      }

    }

     if ((mqd=mq_open("/queue.txt", O_CREAT|O_WRONLY, 0777, &atributos))==-1){

      printf ("Error mq_open\n");

      exit(-1);

    }

    //Rest Parent code
       if (mq_receive(mqd, buffer, strlen(buffer),0)==-1){

      printf ("Error mq_recieve\n");

      exit(-1);

    }

    printf("Received: %s\n",buffer);

    sleep (1);

    waitpid(pid,&status,0);

    printf ("This is the parent again %d, children should have finished\n",getpid());

    mq_close(mqd);
  }


}

我不知道为什么 mq_send() 和 mq_receive() 都返回 -1,我做错了什么? 如果您发现我的代码中有问题,除了我正在谈论的错误之外,为了执行我的意图,请告诉我。 预先感谢您,非常感谢您的帮助。

最佳答案

user58697触及最大的问题。

(1) 您的队列打开失败并显示 EINVAL,因为您注释掉了分配,从而传递了未初始化的属性。

(2) 您以只写方式打开两个队列。父队列需要以读取模式打开。

(3) 执行权限对队列没有任何意义,因此 777 权限虽然不是无效的,但是不必要的。

(4) 由于长度无效,您的发送/接收失败。在许多(如果不是大多数)情况下,将缓冲区分配给队列的长度属性会更容易、更安全。在这种情况下,您事先知道长度,但在不知道的程序中,您可以通过 mq_getattr 获取该值。

(5) 在调用 rand 之前,您没有调用 srand 为 RNG 播种。

(6) 您发生了内存泄漏,您为消息分配了空间(不必要)但从未释放它。

(7) 您尝试传递优先级的操作是多余的。 POSIX MQ 已经内置了优先级。您可以直接使用它们。

我去掉了一些多余的东西(主要是循环和信号),以更多地关注程序的队列方面。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <mqueue.h>

int main()
{
    srand(time(NULL));

    mqd_t mqd;

    struct mq_attr atributos = {.mq_maxmsg = 10, .mq_msgsize = 50};

    int i;
    int pid;
    int status;
    int num_children = 4;

    char buffer[atributos.mq_msgsize];

    for (i = 0; i < num_children; i++)
    {
        if ((pid = fork() == 0))
        {
            int prio = rand () % 3;

            char* msg = "Hi dude";

            strncpy (buffer, msg, sizeof(buffer));

            if ((mqd = mq_open("/queue.txt", O_CREAT | O_WRONLY, 0666, &atributos)) == -1)
            {
                perror("child mq_open");
                exit(1);
            }

            if (mq_send(mqd, buffer, sizeof(buffer), prio) == -1)
            {
                perror("mq_send");
                exit(1);
            }

            mq_close(mqd);

            exit(0);
        }

    }

    // parent

    if ((mqd = mq_open("/queue.txt", O_CREAT | O_RDONLY, 0666, &atributos)) == -1)
    {
        perror("parent mq_open");
        exit(1);
    }

    int priority;

    for (int i = 0; i < num_children; ++i)
    {
        if (mq_receive(mqd, buffer, sizeof(buffer), &priority) == -1)
        {
            perror("mq_recieve");
            exit(1);
        }

        printf("Received (%s): %s\n", (priority == 0) ? "NORMAL" : "URGENT", buffer);

        pid_t childpid;

        if ((childpid = waitpid(-1, &status, 0)) > 0)
        {
            if (WIFEXITED(status))
                printf("PID %d exited normally.  Exit status: %d\n",
                       childpid, WEXITSTATUS(status));
            else
                if (WIFSTOPPED(status))
                    printf("PID %d was stopped by %d\n",
                           childpid, WSTOPSIG(status));
                else
                    if (WIFSIGNALED(status))
                        printf("PID %d exited due to signal %d\n.",
                               childpid,
                               WTERMSIG(status));
        }
    }

    mq_close(mqd);
}

关于c - Fork() 和 Posix 队列。发送和接收字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23139379/

相关文章:

c - 未初始化指针的可能输出

bash - 在 bash 脚本中,如何从使用 eval 命令时执行的程序中获取 PID?

c# - 从 C# 启动 Excel 并在 "Save"上关闭它

python - 不使用堆栈的反向队列

c# - 等待阻塞集合(队列)在 C# 中减小大小

使用 gettext 时 gcc 可以检查 printf 格式吗?

c - x87 FPOP 和 FCOM 指令——它们是如何工作的?

c - 为什么我的主板会出现这样的困惑?

macos - 通过 Cocoa 终止进程

grails - 在Web应用程序中使用RabbitMQ,多个线程可以在同一队列上工作