The biggest single problem is one alluded to in a comment:
AFAICS, you send one message per iteration, so at most one child can read it. You do not send one message per child.
Any given message can be received by (at most) one process. For n
processes to receive a message, you have to send n
messages.
The other issues are mostly cosmetic. I've used logging code available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c
and stderr.h
in the src/libsoq sub-directory. Some of the messages are written to stdout
— there isn't a function that takes just a file stream, so I used err_logmsg()
which takes a file stream, control options and an exit status (but the function shouldn't exit, so that's unused) as well as the format and arguments.
The result is:
/* SO 7592-2454 */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <unistd.h>
#include "stderr.h"
#define MAX_LEN 50
struct details
{
int no;
int id;
char msg_text[MAX_LEN];
};
typedef struct msg_buf
{
long int msg_type;
struct details d;
} msg;
static char message[20][50] =
{
" ",
"Message1",
"Message2",
"Message3",
"Message4",
"Message5",
"Message6",
"Message7",
"Message8"
};
static const char usestr[] = "num_kids num_msgs";
static void dump_message(const char *tag, const msg *info)
{
err_logmsg(stdout, err_getlogopts(), 0, "%s: type %ld (details: no %d, id %d, text [%s])\n",
tag, info->msg_type, info->d.no, info->d.id, info->d.msg_text);
}
int main(int argc, char *argv[])
{
err_setarg0(argv[0]);
if (argc != 3)
err_usage(usestr);
int n = atoi(argv[1]);
int m = atoi(argv[2]);
int id1 = msgget((key_t)78, IPC_CREAT | 0666);
int id2 = msgget((key_t)56, IPC_CREAT | 0666);
if (id1 == -1 || id2 == -1)
err_syserr("failed to create a message queue: ");
pid_t p_id = getpid();
err_setlogopts(ERR_PID|ERR_MILLI);
err_logmsg(stdout, err_getlogopts(), 0, "Queues are created.\n");
pid_t pid;
for (int i = 1; i <= n; i++)
{
pid = fork();
if (pid == 0)
break;
}
msg snd;
msg rcvd;
if (pid == 0)
{
for (int j = 1; j <= m; j++)
{
err_logmsg(stdout, err_getlogopts(), 0, "Waiting for message %d\n", j);
while (msgrcv(id1, &rcvd, sizeof(struct details), j + 1, IPC_NOWAIT) < 0)
err_syserr("msgrcv() returned with error status: ");
dump_message("Message received", &rcvd);
strcpy(snd.d.msg_text, "Received");
snd.msg_type = rcvd.msg_type;
snd.d.no = rcvd.d.no;
snd.d.id = getpid();
if (msgsnd(id2, &snd, sizeof(struct details), IPC_NOWAIT) < 0)
err_sysrem("msgsnd() failed: ");
else
dump_message("Message sent", &snd);
}
err_logmsg(stdout, err_getlogopts(), 0, "Child process complete\n");
exit(EXIT_SUCCESS);
}
if (p_id == getpid())
{
for (int j = 1; j <= m; j++)
{
strcpy(snd.d.msg_text, message[j]);
snd.msg_type = j + 1;
snd.d.no = j;
for (int i = 0; i < n; i++)
{
if (msgsnd(id1, &snd, sizeof(struct details), 0) < 0)
err_sysrem("msgsnd() failed: ");
else
dump_message("Message sent", &snd);
}
for (int i = 1; i <= n; i++)
{
err_logmsg(stdout, err_getlogopts(), 0, "Dozing for %d seconds\n", i);
sleep(i);
if (msgrcv(id2, &rcvd, sizeof(struct details), j + 1, 0) >= 0)
dump_message("Reply received", &rcvd);
else
err_syserr("msgrcv() failed: ");
}
}
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
err_remark("Child %d exited with status 0x%.4X\n", corpse, status);
err_logmsg(stdout, err_getlogopts(), 0, "Communication End.\n\n");
}
return 0;
}
There is copious logging, because I need to see what's happening. The code should (but doesn't) validate the values for n
and m
. They should be at least 1
and not more than some faintly sane number (e.g. 10
), but there'd be one or two values — enumerations or defined constants — to limit the acceptable range.
Here's a sample output (source code msg79.c
, program msg79
):
$ ./msg79 2 3
msg79: 2023-04-03 21:36:38.215 - pid=67247: Queues are created.
msg79: 2023-04-03 21:36:38.217 - pid=67247: Message sent: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67247: Message sent: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67247: Dozing for 1 seconds
msg79: 2023-04-03 21:36:38.217 - pid=67248: Waiting for message 1
msg79: 2023-04-03 21:36:38.217 - pid=67249: Waiting for message 1
msg79: 2023-04-03 21:36:38.217 - pid=67248: Message received: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67249: Message received: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67248: Message sent: type 2 (details: no 1, id 67248, text [Received])
msg79: 2023-04-03 21:36:38.217 - pid=67248: Waiting for message 2
msg79: 2023-04-03 21:36:38.217 - pid=67249: Message sent: type 2 (details: no 1, id 67249, text [Received])
msg79: 2023-04-03 21:36:38.218 - pid=67248: Message received: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:38.218 - pid=67249: Waiting for message 2
msg79: 2023-04-03 21:36:38.218 - pid=67249: Message received: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:38.218 - pid=67248: Message sent: type 3 (details: no 2, id 67248, text [Received])
msg79: 2023-04-03 21:36:38.218 - pid=67249: Message sent: type 3 (details: no 2, id 67249, text [Received])
msg79: 2023-04-03 21:36:38.218 - pid=67248: Waiting for message 3
msg79: 2023-04-03 21:36:38.219 - pid=67249: Waiting for message 3
msg79: 2023-04-03 21:36:38.219 - pid=67248: Message received: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:38.219 - pid=67249: Message received: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:38.219 - pid=67248: Message sent: type 4 (details: no 3, id 67248, text [Received])
msg79: 2023-04-03 21:36:38.219 - pid=67249: Message sent: type 4 (details: no 3, id 67249, text [Received])
msg79: 2023-04-03 21:36:38.219 - pid=67248: Child process complete
msg79: 2023-04-03 21:36:38.219 - pid=67249: Child process complete
msg79: 2023-04-03 21:36:39.219 - pid=67247: Reply received: type 2 (details: no 1, id 67248, text [Received])
msg79: 2023-04-03 21:36:39.219 - pid=67247: Dozing for 2 seconds
msg79: 2023-04-03 21:36:41.220 - pid=67247: Reply received: type 2 (details: no 1, id 67249, text [Received])
msg79: 2023-04-03 21:36:41.220 - pid=67247: Message sent: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:41.220 - pid=67247: Message sent: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:41.220 - pid=67247: Dozing for 1 seconds
msg79: 2023-04-03 21:36:42.221 - pid=67247: Reply received: type 3 (details: no 2, id 67248, text [Received])
msg79: 2023-04-03 21:36:42.221 - pid=67247: Dozing for 2 seconds
msg79: 2023-04-03 21:36:44.223 - pid=67247: Reply received: type 3 (details: no 2, id 67249, text [Received])
msg79: 2023-04-03 21:36:44.223 - pid=67247: Message sent: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:44.223 - pid=67247: Message sent: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:44.223 - pid=67247: Dozing for 1 seconds
msg79: 2023-04-03 21:36:45.227 - pid=67247: Reply received: type 4 (details: no 3, id 67248, text [Received])
msg79: 2023-04-03 21:36:45.227 - pid=67247: Dozing for 2 seconds
msg79: 2023-04-03 21:36:47.227 - pid=67247: Reply received: type 4 (details: no 3, id 67249, text [Received])
msg79: 2023-04-03 21:36:47.227 - pid=67247: Child 67249 exited with status 0x0000
msg79: 2023-04-03 21:36:47.227 - pid=67247: Child 67248 exited with status 0x0000
msg79: 2023-04-03 21:36:47.228 - pid=67247: Communication End.
$