该程序创建两个子进程。第一个子进程(1)从stdin读取文本,删除任何特殊字符,并将spilts转换为单词。程序的那部分工作得很好。然后,当child(1)正在分割单词时,它通过消息队列发送每个单词。此部分导致无效参数错误。然后,子项2应该只打印它返回到屏幕的消息。
至少这就是我计划这项工作的方式。我有点卡住,不太确定如何调试消息队列。现在它正在抛出错误
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <error.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <ctype.h>
# define QUEUE_PERMS 0644
static int message_queue = (int) 0;
static key_t key = (key_t) 0;
typedef struct message
{
long mtype;
char msg[100];
} mess_t;
int main(int argc, char *argv[]){
const char delimiters[] = " ,.-!?()1234567890@#$%^&*\n";
char *word = NULL;
size_t buffer = 100;
char *token;
mess_t message;
mess_t message2;
int i;
// set up a message queue
key = ftok(__FILE__,'x');
// create queue
message_queue = msgget(key, QUEUE_PERMS | IPC_CREAT);
if(message_queue == -1){
perror("creating message queue");
}
// create parcer process. This tokenizes the strings
// and send each work to the sort function(s)
switch(fork()){
case 0:
// child process # 1 starts here
key = ftok(__FILE__,'x');
message_queue = msgget(key, QUEUE_PERMS);
// splitting the words up here, this works fine
while(getline(&word, &buffer, stdin) != EOF){
token = strtok(word, delimiters);
while(token != NULL){
for(i = 0; token[i]; i++){
token[i] = tolower(token[i]);
}
// set type to 1 to send
message.mtype = 1;
// copy the word (token) over to the message struct
strcpy(message.msg,token);
// **** I get a send failed: Invalid argument here *****
if(msgsnd(key, &message, sizeof(message), MSG_NOERROR) == -1){
perror("send failed");
}
token = strtok(NULL, delimiters);
}
}
break;
case -1:
perror("error fork\n");
break;
default:
wait(NULL);
break;
}
// this process should read the message an print it out
switch(fork()){
case 0:
// child process # 2 starts here
key = ftok(__FILE__,'x');
message_queue = msgget(key, QUEUE_PERMS );
msgrcv(key, &message2, sizeof(message),1, MSG_NOERROR);
printf("child process got %s\n", message2.msg);
break;
case -1:
perror("error fork\n");
break;
default:
wait(NULL);
break;
}
return 0;
}
答案 0 :(得分:4)
您使用message_queue
设置msgget()
邮件队列ID,但之后尝试使用msgsnd()
而不是邮件队列ID发送到key
。
msgrcv()
也存在同样的问题。
当我修复这两个时,我可以运行程序:
$ ./mq
abelone apathy
child process got abelone
child process got apathy
$
我在一行输入abelone apathy
,然后 Control-D 以表示EOF。
在组织完成后,写入过程会在启用读取过程之前填充消息队列。只要输入不是太大,那就有效。但是,您可能真的希望这两个进程同时运行。您需要移动wait()
调用以获得并发性。 (将代码正确分离为函数的另一个优点 - 如果你尽可能地隐藏它,就更容易发现这些问题。)
答案 1 :(得分:2)
(1)msgsnd/msgrcv
的错误值。在代码中使用msgget
的{{1}}的返回值。
(2)您的message_queue
代码错误。父母将创建一个孩子,然后点击fork
并在第一个孩子死前等待,然后继续创建第二个孩子。您需要在切换语句中使用wait
的某些地方重新考虑使用exit
。