Сообщения Posix Плохой адрес на mq_open - PullRequest
1 голос
/ 02 мая 2019

Краткое описание проблемы

Я пишу программу, предназначенную для разветвления нескольких процессов, каждый из которых открывает уникальную очередь сообщений для получения сообщений. Однако каждый раз, когда я запускаю свою программу, каждый разветвленный процесс сталкивается с ошибкой Bad address при инициализации соответствующих очередей с помощью mq_open.

Некоторые детали

Мой код предназначен для динамического генерирования имен очереди сообщений, следующих по форме "/_*, где * - это некоторая уникальная буква (a, b, c и т. Д.). Однако при попытке использовать тот же код со строкой "/hello" поставить вместо динамически сгенерированных имен, программа все равно не удалось с той же ошибкой.

Это привело меня к мысли, что проблема заключается не в создании новой очереди, а в проблеме с самим именем. Однако я считаю, что правильно передаю O_CREAT, поэтому не могу понять, в чем проблема.

Я нашел эту предыдущую ветку на эту тему, но не похоже, что у этого парня были такие же проблемы. Я считаю, что я включил весь соответствующий код ниже, но, пожалуйста, дайте мне знать, если нужно больше. Любая помощь очень ценится!

Мой код

Вот функция-обертка, которая на самом деле вызывает mq_open:

mqd_t init_queue(char *desc, long m_flags, long m_max, long m_size)
{
  mqd_t mq_des;
  struct mq_attr attr;
  mode_t mode = 0664;
  attr.mq_maxmsg = m_max;
  attr.mq_msgsize = m_size;
  attr.mq_flags = m_flags;

  if ((mq_des = mq_open(desc, O_CREAT | O_RDWR, mode, attr)) == -1) {
    perror("Error at init_queue");
    exit(1);
  }

  return mq_des;
}

Вот функция, которая вызывает init_queue. Я вставил соответствующие макросы и вспомогательную функцию (nid) вверху, так что вы можете увидеть их:


#define DESCPREF "/_"
#define DESCSIZE 4
#define FIRSTID 97
#define MAXMSGS 200
#define M_SIZE sizeof(struct _message)

char *nid(int id)
{
  char *desc = malloc(sizeof(char) * DESCSIZE);
  char c = id;
  snprintf(desc, DESCSIZE, "%s%c", DESCPREF, c);
  return desc;
}

int node(int id, int inc)
{
  /* INIT */
  proc_info me = malloc(PROCINF_SIZE);
  me->id = id;
  me->curr = id - FIRSTID + 1;
  me->inc = inc;
  char *mypath = nid(id);
  me->listen = init_queue(mypath, O_NONBLOCK, MAXMSGS, M_SIZE);

  /* Do some stuff ... */

  close_queue(me->listen);
  mq_unlink(mypath);
  free(me);
  return 0;
}

Наконец, фрагмент кода, который разветвляет мои отдельные процессы:

int main(){

  pid_t pid;
  int nodes = TESTNODES;

  for (int i = 0; i < nodes; i++) {
    if ((pid = fork()) == -1) {
      perror("Fork error\n");
      exit(1);
    } else if (pid == 0) {
      node(FIRSTID + i, nodes);
      exit(0);
    } else {
      printf("Forked: %d\n", (int) pid);
    }
  }
  return 1;
}

Ожидаемые и фактические результаты

Я ожидал бы, что этот код просто запустится, напечатает pids разветвленных процессов и завершится. Вместо этого я получаю следующие ошибки (для одного примера выполнения):

Forked: 27448
Forked: 27449
Error at init_queue: Bad address
Error at init_queue: Bad address
Forked: 27450
Error at init_queue: Bad address
Forked: 27451
Error at init_queue: Bad address
Forked: 27452
Error at init_queue: Bad address

Как упоминалось ранее, я также попытался сделать это с простой строкой "/hello", использованной в качестве имени ввода для mq_open, и получил тот же набор ошибок (все пять также не сработали в этом случае).

1 Ответ

0 голосов
/ 02 мая 2019

Вам нужно передать указатель на структуру mq_attr, например:

if ((mq_des = mq_open(desc, O_CREAT | O_RDWR, mode, &attr)) == -1) {
    perror("Error at init_queue");
    exit(1);
}

также, как указано на странице руководства, убедитесь, что значения для максимальных сообщений и размера сообщения имеют смысл, иначе вы получите EINVAL.

   EINVAL O_CREAT was specified in oflag, and attr was not NULL, but
          attr->mq_maxmsg or attr->mq_msqsize was invalid.  Both of
          these fields must be greater than zero.  In a process that is
          unprivileged (does not have the CAP_SYS_RESOURCE capability),
          attr->mq_maxmsg must be less than or equal to the msg_max
          limit, and attr->mq_msgsize must be less than or equal to the
          msgsize_max limit.  In addition, even in a privileged process,
          attr->mq_maxmsg cannot exceed the HARD_MAX limit.  (See
          mq_overview(7) for details of these limits.)
...