在我的任务中,我必须分叉进程来模拟分布式操作系统,并使用IPC在Linux上使用启发式算法分配进程。
现在我分叉n
个孩子,然后让他们模拟算法,虽然问题在于所有这些之间的消息队列连接,但这不是问题
有两个消息队列UP
和DOWN
他们都没有工作。
每当我尝试通过这些队列中的任何一个发送一些东西时,它们就会被另一方收到垃圾。
所以,我使用这个结构和那些方法来处理消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
struct msgbuff
{
long mtype;
char mtext[70];
};
void Send(key_t msgqid,char* S,long pid)
{
int send_val;
struct msgbuff message;
message.mtype = pid; /* arbitrary value */
strcpy(message.mtext,S);
cout<<"Message is "<<message.mtext<<endl;
//strcpy(message.mtext, str);
cout<<getpid()<<" Entering Send process"<<endl;
send_val = msgsnd (msgqid, &message, sizeof(message), IPC_NOWAIT);
if(send_val == -1)
perror("Error in send");
}
char* Recieve(key_t msgqid,bool nowait)
{
int rec_val;
struct msgbuff message;
cout<<getpid()<<" Entering Receive process"<<endl;
/* receive all types of messages */
if(nowait)
rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), IPC_NOWAIT);
else rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), !IPC_NOWAIT);
if(rec_val == -1){
// perror("Error in receive");
return "none";
}
return message.mtext;
}
然后我就像每个孩子一样使用它们
DOWN = msgget(200, IPC_CREAT|0644);
UP = msgget(201,IPC_CREAT|0644);
和
while(1)
{
int countfail =0;
char* ask =Recieve(DOWN,true); //nowait
string asks(ask);
cout<<getpid()<<" ask= "<<asks<<endl; //This here prints either garbage (symbols and other random characters) or "none"
if(strcmp(ask,"none")!=0)
{
///////Logic for the algorithm
cout<<"*********"<<getpid()<<" In ASK "<<endl;
stringstream ss1;
ss1.str(ask);
int senderpid=0,processSize=0;
ss1>>processSize>>senderpid;
char* processRecMessage = new char[70];
///setting up what will be sent to other process
if(count+ processSize <= load)
{
count+=processSize;
strcpy(processRecMessage,"Taken");
}
else
{
strcpy(processRecMessage,"Not Taken");
}
//Another Garbage here
Send(UP,processRecMessage,senderpid);
}
else{
int nextProcess = (rand()%3) +1;
if(count + nextProcess <=load)
{
count +=nextProcess;
}
else{
for(int k = 0;k<3;k++)
{
int selectedChild = rand()%n;
cout<<getpid()<<" Selected Child no "<<selectedChild+1<<" PID="<<children[selectedChild]<<endl;
char* x = new char[70];
stringstream ss;
ss<<nextProcess;
ss<<" "<<getpid();
strcpy(x,ss.str().c_str());// x= "nextProcess pid"
cout<<x<<endl;
//// sending here also recieves garbage
Send (DOWN , x,children[selectedChild]);
//// receiving garbage
x= Recieve(UP,false);
cout<<getpid()<<" UP Value = "<<x<<endl;
if (strcmp(x,"Taken")==0){
cout<<"Process sent from "<<getpid()<<" to "<<children[selectedChild]<<endl;
break;
}
else
{
countfail++;
printf("TRAIL #%d failed\n",countfail);
}
}
if(countfail==3)
{
cout<<"Algorithm failed to allocate process.\n";
cout<<"Terminating Process "<<getpid()<<endl;
break;
}
}
}
}
所以,如果有人能帮助我,我将不胜感激
P.S .: 我删除了程序每次失败后的所有消息队列,所以每次重新启动但仍然没有用。
修改: 添加完整代码
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <math.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <string.h>
#include <map>
#include <sstream>
#include <ctime>
using namespace std;
struct msgbuff
{
long mtype;
char mtext[70];
};
void Send(key_t msgqid,char* S,long pid)
{
int send_val;
struct msgbuff message;
message.mtype = pid; /* arbitrary value */
strcpy(message.mtext,S);
cout<<"Message is "<<message.mtext<<endl;
//strcpy(message.mtext, str);
cout<<getpid()<<" Entering Send process"<<endl;
send_val = msgsnd (msgqid, &message, sizeof(message), IPC_NOWAIT);
if(send_val == -1)
perror("Errror in send");
}
char* Recieve(key_t msgqid,bool nowait)
{
int rec_val;
struct msgbuff message;
cout<<getpid()<<" Entering Receive process"<<endl;
/* receive all types of messages */
if(nowait)
rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), IPC_NOWAIT);
else rec_val = msgrcv(msgqid, &message, sizeof(message), getpid(), !IPC_NOWAIT);
if(rec_val == -1){
// perror("Error in receive");
return "none";
}
return message.mtext;
}
int main()
{
int n ;
pid_t pid;
key_t DOWN,UP;
DOWN = msgget(200, IPC_CREAT|0644);//Creates new identifier
UP = msgget(201,IPC_CREAT|0644);
int shmid;
shmid = shmget(50, 393216, IPC_CREAT|0644);
void *shmaddr;
shmaddr = shmat(shmid, (void *)0, 0);
printf("DOWN = %d\n", DOWN);
printf("UP = %d\n", UP);
cout<<"Please enter the number of machines "<<endl;
cin>>n;
int* children = new int[n];
string pids;
stringstream ss4;
ss4<<n;
string number = ss4.str();
pids+=number;
pids+=" ";
for (int i=0;i<n;i++)
{
pid = fork();
children[i]=pid;
stringstream ss3;
ss3<<pid;
string pidstr=ss3.str();
pids+=pidstr;
pids+=" ";
if (pid==0)
break;
}
if (pid==-1)
cout<<"Error in fork" <<endl;
else if (pid==0) // child
{
sleep(1);
DOWN = msgget(200, IPC_CREAT|0644);
UP = msgget(201,IPC_CREAT|0644);
//cout<<"Entering child process"<<endl;
shmid = shmget(50, 393216, IPC_CREAT|0644);
shmaddr = shmat(shmid, (void *)0, 0);
char* pidsrec = new char[100];
strcpy(pidsrec,(char*) shmaddr);
stringstream sss;
string spid(pidsrec);
sss.str(spid);
sss>>n;
children = new int[n];
for(int i =0;i<n;i++)
{
sss>>children[i];
//cout<<getpid()<<"Child #"<<i<<" = "<<children[i]<<endl;
}
srand(getpid());
int load = (rand()%10) +1; // load of operating on this system from 1-10
int count=0;
while(1)
{
int countfail =0;
char* ask =Recieve(DOWN,true); //nowait
string asks(ask);
cout<<getpid()<<" ask= "<<asks<<endl;
if(strcmp(ask,"none")!=0)
{
cout<<"*********"<<getpid()<<" In ASK "<<endl;
stringstream ss1;
ss1.str(ask);
int senderpid=0,processSize=0;
ss1>>processSize>>senderpid;
char* processRecMessage = new char[70];
if(count+ processSize <= load)
{
count+=processSize;
strcpy(processRecMessage,"Taken");
}
else
{
strcpy(processRecMessage,"Not Taken");
}
Send(UP,processRecMessage,senderpid);
}
else{
int nextProcess = (rand()%3) +1;
if(count + nextProcess <=load)
{
count +=nextProcess;
}
else{
for(int k = 0;k<3;k++)
{
int selectedChild = rand()%n;
cout<<getpid()<<" Selected Child no "<<selectedChild+1<<" PID="<<children[selectedChild]<<endl;
char* x = new char[70];
stringstream ss;
ss<<nextProcess;
ss<<" "<<getpid();
strcpy(x,ss.str().c_str());// x= "nextProcess pid"
cout<<x<<endl;
Send (DOWN , x,children[selectedChild]);
x= Recieve(UP,false);
cout<<getpid()<<" UP Value = "<<x<<endl;
if (strcmp(x,"Taken")==0){
cout<<"Process sent from "<<getpid()<<" to "<<children[selectedChild]<<endl;
break;
}
else
{
countfail++;
printf("TRAIL #%d failed\n",countfail);
}
}
if(countfail==3)
{
cout<<"Algorithm failed to allocate process.\n";
cout<<"Terminating Process "<<getpid()<<endl;
break;
}
}
}
}
}
else //parent
{
strcpy((char*) shmaddr,pids.c_str());
}
cout<<getpid()<<" GOODBYE"<<endl;
return 0;
}
我尝试使用任意数量的进程,并且在消息队列的接收端始终收到垃圾
答案 0 :(得分:1)
在Receive
功能中,当您执行
return message.mtext;
您正在返回指向堆栈本地分配的数据的指针。函数返回后,堆栈的这个区域将无效,因此取消引用指针将导致未定义的行为。此外,如果在调用另一个函数后使用此指针,则堆栈的该区域很可能已被其他函数覆盖。
由于您使用的是C ++,为什么不返回std::string
?它将解决这个问题。