Передача сообщений в 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]
вызовет ошибку сегментации / нарушение доступа.
Обратите внимание, что код, который я написал, - это просто руководство, не копируйте и не вставляйте его.
Есть несколько наблюдений, связанных с вашим кодом.
- При использовании системных вызовов (любая функция, которая возвращает любой код ошибки) проверьте возвращаемое значение функции. В случае системных вызовов, которые вы использовали, будет установлено
errno
т.е. номер ошибки, который можно использовать для проверки на наличие ошибок. Ты можешь использоватьperror
или жеstrerror
чтобы увидеть сообщение (уже отмеченное Джонатаном Леффлером) - Вам необходимо создать очередь сообщений перед ее использованием (опять же, на это уже указал Джонатан Леффлер).
- Вы отправляете
char *
вmsgsnd
и получениеstruct msg
введитеmsgrcv
, - Вы установили размер передаваемой в очередь сообщений отправки и получения вызовов, для которых вы используете
msgsz
но неинициализированный. Установить значениеmsgsz
к размеру, который вы хотите отправить / получить. При отправке кажется, что отправляется 17 байт, но при получении она не установлена. mtype
должен иметь значение больше чем0
,- Тип для
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);