任务是: 查找指定的数字间隔内的所有素数,并将其划分为多个范围。 每个范围都在生成的过程中处理。 好吧,我真的想成功。但是出了点问题。无法理解我的错误。 代码:
#include <stdio.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <stdbool.h>
#define MAX_SEND_SIZE 50
#define PROCESS_NUMBER 5
struct mymsgbuf {
long mtype;
int marray[MAX_SEND_SIZE];
};
typedef struct mymsgbuf type_mymsgbuf;
int msgqid, rc;
void send_message(int qid, type_mymsgbuf* qbuf, long type, int* text, int numbers_per_process) {
int i;
int length = sizeof(struct mymsgbuf) - sizeof(long);
qbuf->mtype = type;
for (i = 0; i < numbers_per_process; i++) {
qbuf->marray[i] = text[i];
}
if ((msgsnd(qid, (struct msgbuf*)qbuf, (size_t) length, 0)) == -1) {
perror("msgsnd");
exit(1);
}
}
void read_message(int qid, type_mymsgbuf* qbuf, long type, int numbers_per_process) {
int length = sizeof(struct mymsgbuf) - sizeof(long);
qbuf->mtype = type;
msgrcv(qid, (struct msgbuf*)qbuf, (size_t)length, type, 0);
for (int i = 0; i < numbers_per_process && qbuf->marray[i] != 0; i++) {
printf("%d\n", qbuf->marray[i]);
}
}
bool isprime (int a) {
if(a == 1) {
return false;
}
for (int i = 2; i*i < a; ++i) {
if ((a % i) == 0) {
return false;
}
}
return true;
}
int* find_primes_part (int a, int b) {
int j = 0;
int* primes = (int*)malloc(sizeof(int)*(b-a));
for (int k = 0; k < (b-a); ++k) {
primes[k] = 0;
}
for (int i = a; i < b; ++i) {
if(isprime(i)) {
primes[j] = i;
printf("%d\n TEST", primes[j]);
j++;
}
}
return primes;
}
int find_primes(int a, int b) {
int status, stat;
pid_t pid[PROCESS_NUMBER];
key_t key;
int qtype = 1;
type_mymsgbuf qbuf;
int numbers_per_process = (b-a)/PROCESS_NUMBER;
if ((key = ftok(".", 'm')) < 0) {
perror("ftok");
exit(1);
}
if((msgqid = msgget(key, IPC_CREAT|0660)) == -1) {
perror("msgget");
exit(1);
}
for (int i = 0; i < PROCESS_NUMBER; i++) {
pid[i] = fork();
if (-1 == pid[i]) {
perror("fork");
exit(1);
}
else if (0 == pid[i]) {
int* part_primes = find_primes_part(a + numbers_per_process*i, a + numbers_per_process*(i+1));
send_message(msgqid, (type_mymsgbuf*)&qbuf, qtype, part_primes, numbers_per_process);
}
}
for (int j = 0; j < PROCESS_NUMBER; ++j) {
status = waitpid(pid[j], &stat, 0);
if (pid[j] == status) {
if (WEXITSTATUS(stat) != 0) {
perror("process failed: ");
exit(1);
}
}
}
for (int i = 0; i < PROCESS_NUMBER; ++i) {
read_message(msgqid, &qbuf, qtype, numbers_per_process);
}
if ((rc = msgctl(msgqid, IPC_RMID, NULL)) < 0) {
perror("msgctl");
return 1;
}
return 0;
}
int main() {
find_primes(10, 200);
return 0;
}
输出非常错误,并且每隔一段时间都不同。 它类似于:
181
191
193
197
199
163
167
169msgsnd: Invalid argument
173
179
181
191
193
197
msgctl: Invalid argument
主要问题是这2个错误
msgsnd: Invalid argument
msgctl: Invalid argument
如何消除它?
答案 0 :(得分:2)
我怀疑过早删除了邮件队列。
问题可能是每个进程(包括子进程)都执行清理代码。只有父级应该运行清理代码。
我认为您在调用exit(0);
后立即错过了客户特定代码中的send_message()
或{{1}}。
答案 1 :(得分:1)
您应该按照以下方式完成您的子进程:
else if (0 == pid[i]) {
// I'm child
int* part_primes = find_primes_part(a + numbers_per_process*i, a + numbers_per_process*(i+1));
send_message(msgqid, (type_mymsgbuf*)&qbuf, qtype, part_primes, numbers_per_process);
return 0; // --> exit from the child process
}
/* Both parent and child come here if you do not return from child*/