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

c-使用单个管道的过程阵列

(c - Process array using a single pipe)

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

我是系统多重编程的新手。

我设法创建了一个允许父亲和孩子交谈的管道。子级写精灵的位置,而父级则使用ncurses库将其写入控制台。

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

我想生成N个孩子,这些孩子会生成精灵,而父亲则负责将其写入控制台。但是我不知道该怎么做,也不必用一根或多根管子来做

谁能帮助我找出正确的解决方案,以及如何实施?谢谢

编辑Barmar的答案是正确的,但是在GameBoard中也可能出了点问题,因为即使这两个进程都在运行(我已验证是否打印其pid),第二个敌人也没有显示出来

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

你可以在一个循环中创建N个子进程。

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]);

只要管道的写操作是原子的,只要它们小于PIPE_BUF,在Linux上为4096,并且POSIX要求将其写在lesat 512,因此你不必担心两个子进程的消息会混合在一起。