0

在我的任务中,我必须分叉进程来模拟分布式操作系统,使用启发式算法在 Linux 上使用 IPC 进行进程分配。

现在我 forkn孩子,然后让他们模拟算法,这不是问题,尽管问题出在所有孩子之间的消息队列连接中

有 2 个消息队列UPDOWN它们都不能正常工作。每次我尝试通过这些队列中的任何一个发送一些东西时,它们都会在另一端作为垃圾接收。

所以,我使用这个结构和那些方法来处理消息队列

#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;
                        }
                    }
                }
            }

因此,如果有人可以帮助我,我将不胜感激

ps:程序每次运行失败后我都会删除所有消息队列,因此每次它们重新启动但仍然没有用。

编辑:添加完整代码

#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;
}

我尝试使用任意数量的进程,并且在消息队列的接收端总是收到垃圾

4

1 回答 1

1

在你的Receive功能中,当你这样做时

return message.mtext;

您正在返回一个指向在堆栈上本地分配的数据的指针。函数返回后,堆栈的该区域将无效,因此取消引用指针将导致未定义的行为。此外,如果您在调用另一个函数后使用此指针,则堆栈的该区域很可能已被另一个函数覆盖。

既然您使用的是 C++,为什么不返回std::string?它将解决这个问题。

于 2013-04-23T08:18:12.100 回答