我想要的是这个: 创建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,我做错了什么? 而且你在我的代码中看到了一些错误,以便按照我所说的错误做我想做的事情,让我知道。 提前谢谢你,我感谢任何帮助。
答案 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);
}