Передача сообщений в C/ Печать массива char из структуры в C

Я создал эту программу, чтобы передать сообщение родительскому процессу. Я хочу, чтобы родительский процесс распечатал полученное сообщение. Я не уверен, что это проблема чтения массива char или передачи сообщений, так как я новичок в программировании на c. Вот моя попытка:

struct msg {
        long int    mtype;      /* message type */
        char        mtext[1028];   /* message text */
} msg;
int pid, len;
int msgflg = 0;
int msqid;
char *mymsg[1028];
size_t msgsz;
long int msgtyp;

switch(pid=fork()) //fork child process
{//Child process
case 0:
    mymsg[1] = "serving for sender\n";
    len = strlen(mymsg[1]);
    msgsnd(msqid,mymsg[1],len,msgflg);
    break;
case -1:
    printf("fork failed");
    exit(-1);
    break;
default:
    msg.mtype = 0;
    msqid = msgget(IPC_PRIVATE,msgflg); 
    wait((int *) 0);
    msgrcv(msqid,&msg,msgsz,msgtyp,IPC_NOWAIT);

    printf("%s",msg.mtext);
    msgctl(msqid, IPC_RMID, NULL);
    exit(0);
}

У меня вопрос, почему сообщение, служащее для отправки, не отображается, когда этот код компилируется и выполняется?

3 ответа

Вы на самом деле не задавали вопрос, но я вижу несколько проблем с кодом:

char *mymsg[1028];
...
mymsg[1] = "serving for sender\n";

Здесь у вас есть mymsg который представляет собой массив 1028 указатели на char, который предназначен для обработки в виде строки. (Кстати, почему 1028? Не то, чтобы это имело значение, но вы знаете, что 2^10 - это 1024). Однако этот массив содержит указатели, которые не инициализированы и указывают на случайные местоположения. Важно то, что нет места, выделенного для возможного сообщения, которое вы хотите поместить в них.

Вторая проблема заключается в том, что массивы в C начинаются с индекса 0, так что вы, вероятно, хотели написать

mymsg[0] = "serving for sender\n";

Это не имеет значения, однако.

Что еще более важно, вы не можете копировать строки в C, используя =, вы должны использовать strcpy и скопируйте в область памяти, которую вы уже выделили. Вот два способа сделать это:

char mymsg[1028][1028];    // if you are sure your messages fit in 1028 chars
...
mymsg[1] = malloc(strlen("serving for sender)*sizeof(char)); // sizeof(char) not really needed
strcpy(mymsg[1], "serving for sender\n");
msgsnd(msqid,mymsg[1],len,msgflg);
free(mymsg[1]);

или же

char *mymsg[1028];
...
char str_to_be_printed[] = "serving for sender\n";
mymsg[1] = malloc(strlen(str_to_be_printed)*sizeof(char)); // sizeof(char) not really needed
strcpy(mymsg[1], str_to_be_printed);
msgsnd(msqid,mymsg[1],len,msgflg);
free(mymsg[1]);

Редактировать: во втором случае, где у вас уже есть строка (а не в форме "это строка"), достаточно присвоить указатели, и вы не копируете и не выделяете память. Однако, если ваша ситуация более сложна, чем эта, и между назначением mymsg[1] = ... а также msgsnd есть другой код, вы должны убедиться, что исходная строка остается в живых до msgsnd готово. В противном случае у вас есть свисающий указатель, который вызовет у вас проблемы. Вот идея:

                        +-+-+-+-+-+-+-+-+--+
str_to_be_printed ----->|A| |s|t|r|i|n|g|\0|
                        +-+-+-+-+-+-+-+-+--+
                        ^
mymsg[1]---------------/

если ты free память о str_to_be_printed, доступ к mymsg[1] вызовет ошибку сегментации / нарушение доступа.

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

Есть несколько наблюдений, связанных с вашим кодом.

  1. При использовании системных вызовов (любая функция, которая возвращает любой код ошибки) проверьте возвращаемое значение функции. В случае системных вызовов, которые вы использовали, будет установлено errno т.е. номер ошибки, который можно использовать для проверки на наличие ошибок. Ты можешь использовать perror или же strerror чтобы увидеть сообщение (уже отмеченное Джонатаном Леффлером)
  2. Вам необходимо создать очередь сообщений перед ее использованием (опять же, на это уже указал Джонатан Леффлер).
  3. Вы отправляете char * в msgsnd и получение struct msg введите msgrcv,
  4. Вы установили размер передаваемой в очередь сообщений отправки и получения вызовов, для которых вы используете msgsz но неинициализированный. Установить значение msgsz к размеру, который вы хотите отправить / получить. При отправке кажется, что отправляется 17 байт, но при получении она не установлена.
  5. mtype должен иметь значение больше чем 0,
  6. Тип для pid должно быть pid_tчто, кажется, тебе мало в этом случае все равно.

Некоторые разделы кода для вашей справки:

#include <stdio.h> /*For perror*/
...
/* Create message queue */
msqid = msgget(IPC_PRIVATE, IPC_CREAT);
if( 0 > msqid )
{
 perror("msgget");
 /* Handle error as per your requirement */
}

... 
/* Sending & receiving messages */
...
struct msg {
        long int    mtype;      /* message type */
        char        mtext[1028];   /* message text */
} sender_msg, receiver_msg;
...

size_t msgsz = 10; /* Send & receive 10 bytes, this can vary as per need. You can receive less than what was sent */
...
switch(fork())
{

case 0: /* Child */
    sender_msg.mtype = 1;
    strncpy(sender_msg.mtext,"01234567890123", 1027);
    /* Sending the whole text size */
    if ( 0 > msgsnd(msqid, &sender_msg, strlen(sender_msg.mtext),msgflg))
    {
      perror("msgsnd");
      /* Handle error as per your requirement */
    }
break;

case -1:
    perror("fork");
    exit(-1);
break;
default:
    wait((int *) 0);
    receiver_msg.mtype = 1;
    /* Receive only 10 bytes as set in msgsz */
    if( 0 > msgrcv(msqid,&receiver_msg,msgsz,msgtyp,IPC_NOWAIT))
    {
      perror("msgrcv");
      /* Error handling */
    }
    printf("%s",receiver_msg.mtext);
    if (0 > msgctl(msqid, IPC_RMID, NULL))
    {
      perror("msgctl");
      /* Handle error as per your requirement */
    }
break;

}

Похоже, вы используете API очередей сообщений System V, вы можете посмотреть на API очереди сообщений POSIX, например: mq_open, mq_close, mq_send, mq_receive и т. д. Обзор очереди сообщений см. на страницах руководства (man mq_overview)
Используйте справочные страницы для получения информации об API.
Надеюсь это поможет!

У вас есть несколько проблем:

  • Вам нужно создать очередь сообщений, прежде чем позвонить fork()так, чтобы и родитель и ребенок имели доступ к нему;

  • Права доступа к очереди сообщений устанавливаются из младших битов второго параметра msgget(), поэтому вам нужно указать как минимум права на чтение и запись для владельца очереди сообщений. Вы можете использовать константу S_IRWXU от <sys/stat.h> Вот;

  • Вы проходите msgsnd() указатель на строку, но на самом деле он хочет указатель на структуру сообщения, как ваш struct msg,

  • Вы должны проверить msgrcv() терпит неудачу.

После исправления этих проблем исправленный код выглядит следующим образом:

int pid;
int msqid;

msqid = msgget(IPC_PRIVATE, S_IRWXU);

if (msgid < 0) {
    perror("msgget");
    exit(1);
}

switch(pid=fork()) //fork child process
{//Child process
case 0:
    msg.mtype = 1;  /* Must be a positive value */
    strcpy(msg.mtext, "serving for sender\n");
    msgsnd(msqid, &msg, strlen(msg.mtext) + 1, 0);
    break;
case -1:
    printf("fork failed");
    exit(2);
    break;
default:
    wait(NULL);

    if (msgrcv(msqid, &msg, sizeof msg.mtext, 0, IPC_NOWAIT) >= 0)
        printf("%s",msg.mtext);
    else
        perror("msgrcv");

    msgctl(msqid, IPC_RMID, NULL);
    exit(0);
Другие вопросы по тегам