此程序用于计算给定范围内的素数(作为命令行参数给出)。我必须为此程序使用进程和消息队列。素数范围被分成相等的数据大小(每个过程处理一个单独的范围)。父进程使用消息队列将范围发送到每个子进程。每个进程都会创建许多线程来计算素数。每个进程中的主线程对素数求和,并将结果发送给父进程。
我目前陷入第193行,我正在声明线程数组。然后代码跳到父进程并基本上给出随机数。
现在这是我在Ubuntu中编译后获得的输出:
// Linux input to run program:
// g++ prime.cpp -o prime -lpthread -std=c++11
// ./prime 10 60 5 2
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <sys/msg.h>
#include <fstream>
#include <iostream>
#include <mutex>
#include <math.h>
#include <vector>
#include <ctype.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#define PERM (S_IRUSR | S_IWUSR)
using namespace std;
void *primecalc(void *argument); // the runner
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; // define the mutex lock
// sets up message structure (holds what needs to be set to child process)
// min, max, etc
char cwdpath[600];
struct mystructure
{
long mtype;
int num_threads;
int min;
int max;
int process_id;
int sum_primes;
};
struct threadstructure
{
int min;
int max;
string filename;
};
// get the ID of the main process
int queueid;
int initqueue(int key)
{ /* initialize the message queue */
queueid = msgget(key, 0666 | IPC_CREAT);
if (queueid == -1)
{
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
if (argc !=5)
{
return 0;
}
// define the number the primes will be calculated up to
// and define the number of threads
// get arguments
int numprimesmin = atoi(argv[1]);
int numprimesmax = atoi(argv[2]);
int num_processes = atoi(argv[3]);
int num_threads = atoi(argv[4]);
int error;
// these are the leftover prime numbers
int leftover = numprimesmax%num_processes;
// the interval of prime numbers that each process checks
int range = numprimesmax/num_processes;
// the current minimum in each process
int currentmin = numprimesmin;
// the current maximum in each process
int currentmax = range + currentmin;
// get the current working directory, and define the key
getcwd(cwdpath, 600);
const char *path = cwdpath;
key_t key = ftok(path, 'd');
initqueue(key);
// initialize the message with beginning data
mystructure message = {1, num_threads, currentmin, currentmax, 0, 0};
// initialize the process
pid_t process;
// for each process, perform these actions
for(int i = 0; i<num_processes; i++)
{
// send the messages out
if (msgsnd(queueid, (const void*)&message, sizeof(message)-sizeof(message.mtype), 0) == -1)
{
error = errno;
}
// update the current proccesses
if(i != (num_processes-1))
{
currentmin = currentmax + 1;
currentmax = range +currentmin;
}
else // this is for the last process
{
currentmin = currentmax +1;
// last process does extra work
currentmax = leftover + currentmin + range;
}
message.min = currentmin; // update min and max for the structure
message.max = currentmax;
}
//printf("Prime Numbers: \n");
// Create the proccesss
pid_t pid;
for(int k = 1; k <= num_processes; k++)
{
pid = fork();
if (pid == 0)
{
break;
}
}
// this is the parent only
if (pid > 0)
{
int ftotal= 0;
while (wait(NULL)>0);
for (int u = 0; u < num_processes; u++)
{
mystructure finalmessage; // initialize the final message
msgrcv(queueid, (void*)&finalmessage, sizeof(finalmessage)-sizeof(finalmessage.mtype), 1, 0); // receive the final message
cout << "The sum of the prime number computed by process " << finalmessage.process_id << " is " << finalmessage.sum_primes << endl;
ftotal += finalmessage.sum_primes; // add the sum of primes in this process to the total
}
// output the sum of all prime number sums
cout << "The total of all prime numbers in this range is: " << ftotal << endl;
return 0;
}
// this is the child only
if(pid == 0)
{
mystructure threadmessage;
msgrcv(queueid, (void*)&threadmessage, sizeof(threadmessage)-sizeof(threadmessage.mtype), 1, 0);
srand (time(NULL));
int random = rand()%10000+1;
string name = "filething" + to_string(random);
// get arguments
int Cnumprimesmax = threadmessage.max;
int Cnumprimesmin = threadmessage.min;
int Cnum_threads = threadmessage.num_threads;
// get ranges
int Cleftover = Cnumprimesmax%Cnum_threads;
int Crange = Cnumprimesmax/Cnum_threads; // divides
int Ccurrentmin = Cnumprimesmin;
int Ccurrentmax = Crange + Ccurrentmin;
threadstructure minmax;
minmax.min = Cnumprimesmin;
minmax.max = Cnumprimesmax;
minmax.filename = name;
// HERE IT IS
cout << " this is before the threads declaration" << endl;
pthread_t tid[Cnum_threads];
cout << "test after array declaration" << endl;
for (int i = 0; i < Cnum_threads; i++)
{
pthread_attr_t attr; // define default attribute
pthread_attr_init(&attr);
cout << "test thing" << endl;
pthread_create(&tid[i], NULL, &primecalc, &minmax);// create each thread, using the primecalc function
if(i != (Cnum_threads-1))
{
Ccurrentmin = Ccurrentmax + 1;
Ccurrentmax = Crange +Ccurrentmin;
}
else // this is for the last process
{
Ccurrentmin = Ccurrentmax +1;
Ccurrentmax = Cleftover + Ccurrentmin + Crange; // last process does extra work
}
threadmessage.min = Ccurrentmin; // update min and max for the structure
threadmessage.max = Ccurrentmax;
}
for (int i = 0; i < Cnum_threads; i++)
{
pthread_join(tid[i],NULL);
cout << "test 5" << endl;
printf("\n");
}
cout << "skipped it all\n";
ifstream myfile (name.c_str());
int number;
int total = 0;
while(myfile >> number)
{
cout << "test text" << endl;
total += number;
}
myfile.close();
mystructure finalmessage = {1, 0, 0, 0, getpid(), total};
cout << "test 4" << endl;
msgsnd(queueid, (const void*)&finalmessage, sizeof(finalmessage)-sizeof(finalmessage.mtype), 0);
}
printf("\nComplete\n");
}
//Each thread will calculate the prime numbers in the range
void *primecalc(void *argument)
{
cout << "test 333" << endl;
threadstructure *variables = (threadstructure*)argument;
cout << "test 3334" << endl;
int i, j; // define loop variables
cout << "test 3335" << endl;
int lower = variables->min;
cout << "test 333" << endl;
int upper = variables->max; // dereference the argument
cout << "test 3336" << endl;
while (lower < upper)
{
int trap = 0;
for(i = 2; i <= lower/2; ++i)
{
if(lower % i == 0)
{
trap = 1;
break;
}
}
if (trap == 0)
{
pthread_mutex_lock(&mutex1); // set mutex lock for output
if(trap == 0)
{
ofstream myfile ((variables->filename).c_str());
if (myfile.is_open())
{
myfile << i <<endl;
myfile.close();
}
else cout << "Unable to open file";
}
pthread_mutex_unlock(&mutex1); // unlock mutex for output
}
++lower;
}
//Exit the thread
pthread_exit(NULL);
}