Mandelbrot消息队列阻塞 - C.

时间:2012-05-18 05:03:34

标签: c message-queue mandelbrot

我在此程序中使用消息队列时遇到问题 它应该启动一些由命令提示符通过参数传递给程序的进程,但它只启动并计算一个进程的点...其他进程无法启动.. 请帮帮我。

这是创建消息队列并将所选数据输出为pgm格式的程序 只有第一个进程才能运行其他进程 谁能告诉我为什么?

 #include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
void output_pgm(char *filename,double *buffer, int nx, int ny, double max) {
  int i;
  FILE *file;
  file = fopen(filename,"w");
  fprintf(file,"P2\n");
  fprintf(file,"%d %d\n",nx,ny);
  fprintf(file,"%d\n",(int)max);
  for (i=0; i<nx*ny; i++) {
    if (!(i%nx)) fprintf(file,"\n");
    fprintf(file,"%d ",(int)buffer[i]);
  }
  fclose(file);
}

void main(int argc,char *argv[]) {

    if(argc != 2) {
    } else {

       int n = atoi(argv[1]);
       int i = 0;
       struct msgbuf {
              long mtype;
        int x;
        int y;
        double value;
       };

       struct envio {
          long mtype;
          long type;
          int ny;
          double yM1;
          double yM2;
       };


        key_t key = 123;
        key_t key2 = 124;
        int msgflg = IPC_CREAT | 0666;
        int msqid = msgget(key,msgflg);
        int msqid2 = msgget(key2,msgflg);
       switch(fork()) {
           case -1:
            printf("Erro de fork");
            break;
           case 0:
            printf("Oi: %d\n",n);           
            double *b;
            int x,y,i,m;

            double *ptr = b = malloc(1000*1000*sizeof(double));
            printf("Chego(1)\n");
                struct msgbuf a;
            struct envio c;
            size_t buflen = sizeof(a) - sizeof(long);
            size_t len2 = sizeof(c) - sizeof(long);
            printf("Chego(2)\n");
            int msid = msgget(key,msgflg);
            int msid2 = msgget(key2,msgflg);
            printf("Chego(3)\n");           
            double aux = -1.0;
            double multiplier = ((1.0/n) * 2);
            c.mtype = 300;
            int ny = (int)(1000/n);

            for(i = 0; i < n; i++) {
             c.type = (i+1);
               c.ny = (int)(1000/n);
               c.yM1 = aux;
               c.yM2 = aux+multiplier;
               printf("Chego aqui(2)\n");
                           if(msgsnd(msid2,&c,len2,0) < 0) {
                  perror("Erro do 1o envio\n");
               }
            }
        for(m = 0; m < n; m++) {
               printf("Entrei no ciclo(1)\n");

            for(y = 0; y <ny ;y++) {
                //printf("Chego(4)\n");
                 for(x = 0; x < 1000;x++) {
                if(msgrcv(msid,&a,buflen,(long)(m+1),0) < 0) {
                   perror("Erro na recepcao:\n ");       
                }
                //printf("Chego(5)\n");
                b[a.y * ny + a.x] = a.value;
                 }
            }

            b = b + (1000/n)*1000;
           }
            output_pgm("mandel.pgm", ptr, 1000, 1000, 255);
            //msgctl(msid, IPC_RMID, NULL);
            //msgctl(msid2, IPC_RMID, NULL);
            printf("Processo 1\n");
            break;
           default:
             for(i = 0;i < n;i++) {
              switch(fork()) {
                  case -1:
                   printf("Erro de fork");
                case 0:
                   exit(0);
                   break;
                default:
                    printf("Fui lancado\n");
                    execlp("/home/hyper/Documents/SO2/TP3-4/rec","rec",0);
                    break;
              }
                 }
             break;         
        }             
    }   

};

此程序中的for循环仅运行一次

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
double type;
       struct senbuf {
              long mtype;
        int x;
        int y;
        double value;
       };
int max_iterations = 256;

double compute_point(double ci, double cr) {
  int iterations = 0;
  double zi = 0;
  double zr = 0;

  while ((zr*zr + zi*zi < 4) && (iterations < max_iterations)) {
    double nr, ni;

    /* Z <-- Z^2 + C */

    nr = zr*zr - zi*zi + cr;
    ni = 2*zr*zi + ci;

    zi = ni;
    zr = nr;

    iterations ++;
  } 
  return iterations; 
}

/* The "compute" function computes the Mandelbrot function over every
   point on a grid that is "nx" points wide by "ny" points tall, where
   (xmin,ymin) and (xmax,ymax) give two corners of the region the
   complex plane.
*/

void compute(int msqid,int nx, int ny, double xmin, double xmax,
         double ymin, double ymax,long type2 ) {

  double delta_x, delta_y;
  int x, y;
  struct senbuf sen;
  delta_x = (xmax - xmin)/nx;
  delta_y = (ymax - ymin)/ny;
  size_t buflen = sizeof(sen) - sizeof(long);
  for (y=0;  y<ny; y++) {
    //printf("Ja entrei aqui");
    double y_value = ymin + delta_y * y;
    for (x=0; x<nx; x++) {
      double x_value = xmin + delta_x * x;
      sen.mtype = type;
      sen.x = x;
      sen.y = y;
      sen.value = compute_point(x_value,y_value);
      if(msgsnd(msqid,&sen,buflen,0) < 0) {
        perror("Erro no envio:");
      };     
     // printf("%f",sen.a[y*nx + x]);
      //buffer[y*nx + x] = compute_point(x_value, y_value);
    }
  }
   printf("Ja mandei %d\n",type2);  
/*sen.mtype=500;
   sen.test = -1;
   printf("Ja to a sair\n");
   msgsnd(msqid,&sen,buflen,IPC_NOWAIT);*/
}

/* Output the data contained in the buffer to a Portable Greymap format
   image file.  The parameter "max" should be an upper bound for the
   data values in the buffer.
*/

void output_pgm(char *filename,double *buffer, int nx, int ny, double max) {
  int i;
  FILE *file;
  file = fopen(filename,"w");
  fprintf(file,"P2\n");
  fprintf(file,"%d %d\n",nx,ny);
  fprintf(file,"%d\n",(int)max);
  for (i=0; i<nx*ny; i++) {
    if (!(i%nx)) fprintf(file,"\n");
    fprintf(file,"%d ",(int)buffer[i]);
  }
  fclose(file);
}

int main()
{
    int msqid;
    int msqid2;
          struct recep {
          long mtype;
          long type;
          int ny;
          double yM1;
          double yM2;
       };

     struct recep a;
     size_t len = sizeof(a) - sizeof(long);
     key_t key = 124;
     msqid = msgget(key, 0666);
     if(msgrcv(msqid, &a, len, 300, 0) < 0) {
          perror("Error checking");
     };
    printf("Dados :\n Tipo : %d\n Ny: %d\n,yM1 : %f\n yM2: %f\n",a.type,a.ny,a.yM1,a.yM2);


     type = a.type;
     printf("Vou iniciar o compute");

     key_t key2 = 123;
         msqid2 = msgget(key2,0666);    
     compute(msqid2,1000,a.ny, -1.0, 1.0,a.yM1,a.yM2,a.type);
}

1 个答案:

答案 0 :(得分:1)

在你的第一个switch语句中,你创建了一个正在做任何事情的孩子。父进入第二个switch语句,其中子进程立即退出,父进程覆盖“rec”可执行文件。父级不再执行 - 它是程序“rec”。你永远不会执行循环的多次传递,因为正在执行的代码在那时就消失了。如果你想要运行“rec”的多个实例,你应该对孩子而不是父母使用execlp

修改

有两个系统调用waitwaitpid,提供各种选项。其中较简单的是wait,应该足以满足您的需求。在您创建的每个子项的父项中定义和增加计数器。然后,不是只退出父母,而是等待所有孩子完成。这样简单就足够了:

for (int i = 0; i < counter; i++)
{
    wait(NULL);
}