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

时间:2014-04-17 17:12:44

标签: c process queue fork posix

我想要的是这个: 创建4个子进程的1个主要进程: - >主进程通过队列接收来自子进程的消息并打印收到的消息。 - >孩子们通过队列发送消息(带有优先级+消息的字符串)并完成。 所有在一段时间(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,我做错了什么? 而且你在我的代码中看到了一些错误,以便按照我所说的错误做我想做的事情,让我知道。 提前谢谢你,我感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

首先,当系统调用失败时,请打印errno(和strerror(errno))。

现在,明显的错误:

  • 如上所述,您需要具有读取权限才能mq_receive()
  • 什么是strlen(buffer)
  • 您正在传递属性而不初始化它们。

总结一下,打印errno并查看错误。

答案 1 :(得分:0)

user58697触及了最大的问题。

(1)您的队列打开时因EINVAL而失败,因为您传递了未初始化的属性,因为您注释了作业。

(2)您正在打开两个队列以进行只写。父队列需要以读模式打开。

(3)执行权限对队列没有任何意义,因此不需要777权限,而不是无效。

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

(5)在致电srand之前,你没有打电话给rand种子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);
}