我想要的是这样的: 1 个创建 4 个子进程的主进程,其中: -> 主进程通过队列接收来自子进程的消息并打印收到的消息。 -> children 通过队列发送消息(带有优先级的字符串+消息)并完成。 一切都在一段时间内 (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,我做错了什么? 如果您发现我的代码中有问题,除了我正在谈论的错误之外,为了执行我的意图,请告诉我。 预先感谢您,非常感谢您的帮助。
最佳答案
user58697触及最大的问题。
(1) 您的队列打开失败并显示 EINVAL,因为您注释掉了分配,从而传递了未初始化的属性。
(2) 您以只写方式打开两个队列。父队列需要以读取模式打开。
(3) 执行权限对队列没有任何意义,因此 777 权限虽然不是无效的,但是不必要的。
(4) 由于长度无效,您的发送/接收失败。在许多(如果不是大多数)情况下,将缓冲区分配给队列的长度属性会更容易、更安全。在这种情况下,您事先知道长度,但在不知道的程序中,您可以通过 mq_getattr
获取该值。
(5) 在调用 rand
之前,您没有调用 srand
为 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);
}
关于c - Fork() 和 Posix 队列。发送和接收字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23139379/