Warm tip: This article is reproduced from serverfault.com, please click

Process array using a single pipe

发布于 2020-12-02 20:58:59

I'm new to system multiprogramming.

I managed to create a pipe which allows father and child to talk. The child writes the position of the sprite, while the father writes it on the console using the ncurses library.

#include <curses.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define ENEMYSPRITE "()"
#define BOMB "#"

typedef struct {
  char * c;
  int x;
  int y;
  int oldx;
  int oldy;
  pid_t pid;
}
pos;

void gameBoard(int pipein) {
  int row, col;
  getmaxyx(stdscr, row, col);
  pos pos_enemy, readValue;

  while (1) {
    read(pipein, & readValue, sizeof(readValue));

    if (strcmp(readValue.c, ENEMYSPRITE) == 0) {
      if (pos_enemy.x >= 0) {
        mvaddstr(pos_enemy.y, pos_enemy.x, "   ");
      }
      pos_enemy = readValue; // e mi salvo la nuova
    } 

    mvaddstr(readValue.y, readValue.x, readValue.c);

    refresh();
  }
}

void enemy(int pipeout) {
  int passo = 1;
  int row, col;
  pos pos_enemy;
  pos_enemy.c = ENEMYSPRITE;
  pos_enemy.x = 10;
  pos_enemy.y = 5;

  getmaxyx(stdscr, row, col);

  write(pipeout, & pos_enemy, sizeof(pos_enemy));

  while (1) {

    getmaxyx(stdscr, row, col);

    if (pos_enemy.x < col - 3 && pos_enemy.x > 0)
      pos_enemy.x += passo;
    else {
      if (pos_enemy.x == 0)
        pos_enemy.x++;
      else
        pos_enemy.x--;
      passo = passo * -1;
    }

    write(pipeout, & pos_enemy, sizeof(pos_enemy));
    usleep(100000);
  }
}

int main(int argc, char ** argv) {
  initscr();
  noecho();
  curs_set(0);

  int fdescriptor[2];
  pipe(fdescriptor);
  pid_t pidEnemy = fork();
  if (pidEnemy == 0) {
    close(fdescriptor[0]);
    enemy(fdescriptor[1]);
  } else {
    close(fdescriptor[1]);
    gameBoard(fdescriptor[0]);
  }
  return 0;
}

I would like to generate N childs, which generate sprites, while the father takes care of writing them to the console. But I don't know how to do it, nor if I have to do it with 1 pipe or more than one

Can anyone help me figure out what the correct solution is, and how to implement it? Thanks

EDIT Barmar's answer is right however there might be something wrong also in gameBoard because even thoug the two processes are running (I verified if printing their pids) the second enemy is not getting displayed

Questioner
Mattek
Viewed
0
Barmar 2020-12-03 05:22:16

You can create N child processes in a loop.

for (int i = 0; i < N; i++) {
  pid_t pidEnemy = fork();
  if (pidEnemy == 0) {
    close(fdescriptor[0]);
    enemy(fdescriptor[1]);
  }
}
close(fdescriptor[1]);
gameBoard(fdescriptor[0]);

Writes to a pipe are atomic as long as they're smaller than PIPE_BUF, which is 4096 on Linux, and required to be at lesat 512 by POSIX, so you don't have to worry about messages from two child processes getting intermixed.