进程之间重定向输出和输入流的问题

问题描述 投票:0回答:1

我正在用 c 编写一个管道模拟。当有多个“|”时,它会崩溃而其他进程必须读取前一个进程的输出。

#define _GNU_SOURCE
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h>

enum {
  MAX_ARGS_COUNT = 256,
  MAX_CHAIN_LINKS_COUNT = 256
};

pid_t pid_arr[MAX_CHAIN_LINKS_COUNT];

typedef struct {
  char *command;
  uint64_t argc;
  char *argv[MAX_ARGS_COUNT];
} chain_link_t;

typedef struct {
  uint64_t chain_links_count;
  chain_link_t chain_links[MAX_CHAIN_LINKS_COUNT];
} chain_t;

void parse_commands(char *command, chain_link_t *link) {
  char *tmp = command;
  char *tmp2 = command;
  link->argc = 1;
  while ((tmp = strchr(tmp, ' '))) {
    link->argv[link->argc - 1] = strndup(tmp2, tmp - tmp2);
    link->argc++;
    tmp2 = ++tmp;
  }
  if (strlen(tmp2) > 0) {
    link->argv[link->argc - 1] = strdup(tmp2);
  }
  link->command = link->argv[0];
}

void create_chain(char *command, chain_t *chain) {
  char *tmp = command;
  char *tmp2 = command;
  chain->chain_links_count = 0;
  while ((tmp = strchr(tmp, '|'))) {
    if (tmp[0] == ' ') {
      ++tmp;
    }
    parse_commands(strndup(tmp2, tmp - tmp2 - 1), &(chain->chain_links[chain->chain_links_count]));
    tmp = tmp2 = tmp + 2;
    ++chain->chain_links_count;
  }
  if (strlen(tmp2) > 0) {
    if (tmp2[0] == ' ') {
      ++tmp2;
    }
    parse_commands(strdup(tmp2), &(chain->chain_links[chain->chain_links_count]));
    ++chain->chain_links_count;
  }
}

void run_chain(chain_t *chain) {
  size_t size = chain->chain_links_count - 1;
  if (chain->chain_links_count == 0) {
    fprintf(stderr, "No commands provided.\n");
    return;
  }
  int pipes[chain->chain_links_count][2];

  for (int i = 0; i < chain->chain_links_count - 1; ++i) {
    if (pipe(pipes[i]) == -1) {
      perror("pipe");
      exit(EXIT_FAILURE);
    }
  }

  for (int i = 0; i < chain->chain_links_count; ++i) {
    pid_t pid = fork();
    if (pid == -1) {
      perror("fork");
      exit(EXIT_FAILURE);
    } else if (pid == 0) {  // Child process
      if (i > 0) {
        dup2(pipes[i - 1][0], STDIN_FILENO);
        close(pipes[i - 1][0]);
        close(pipes[i - 1][1]);
      }
      if (i < chain->chain_links_count - 1) {
        dup2(pipes[i][1], STDOUT_FILENO);
        close(pipes[i][0]);
        close(pipes[i][1]);
      }
      execvp(chain->chain_links[i].command, chain->chain_links[i].argv);
      perror("execvp");
      exit(EXIT_FAILURE);
    }
  }
  for (int i = 0; i < chain->chain_links_count - 1; ++i) {
    close(pipes[i][0]);
    close(pipes[i][1]);
  }
  for (int i = 0; i < chain->chain_links_count; ++i) {
    wait(NULL);
  }
}

int main(int argc, char *argv[]) {
  chain_t chain;
  create_chain(argv[1], &chain);
  run_chain(&chain);
  return 0;
}

"pwd"
"ls"
"ls -l"
"ls -la"
"ls -la | wc -c"
"pwd | cut -d/ -f2"
"ls -la | wc | echo "1" | echo "1" | echo "1" | echo "1" | echo "1" | echo "1" | echo "1""
等类型的测试它可以成功运行,但在测试中
"ls -la | wc | wc -c"
它挂在最后一个过程。 我假设最后一个 wc 的输入是空的,这就是它挂起的原因。 可能是什么问题?

c process pipe io-redirection dup2
1个回答
0
投票

我看到的问题是管道的每一端在执行之前都被关闭。该代码适用于单个管道,因为它从标准 io fd 写入和读取。正如您在此 chart 中所看到的,某些末端应保持开放状态以供读取。

© www.soinside.com 2019 - 2024. All rights reserved.