【问题标题】:Multiple fork and printing something before exec在执行之前多次分叉和打印一些东西
【发布时间】:2020-01-28 02:49:35
【问题描述】:
// I have commands in commands[] array
pid_t pid[command_count];

for (int i = 0; i < command_count; i++) {
  if ((pid[i]=fork()) == 0) {
      printf("--%s\n", commands[i][0]);
      execvp(commands[i][0],commands[i]);
      _exit(1);
  }
  if (pid[i] < 0) {

  }
}

for (i = 0; i < command_count; i++) { 
  if (pid[i] > 0) {
    int status;
    waitpid(pid[i], &status, 0);
  }    
}

我有上面的代码,想一次(并行)运行命令数组中的命令,并且在每次运行之前,想打印命令。例如;

ls | pwd | ls -a

它应该在命令运行之前打印每个命令名称

--ls
.. a b.txt
--pwd
/a/a/
--ls -a
*some output*

但它打印如下

--ls
--pwd
--ls -a
.. a b.txt
*some directory as a result of pwd*
*some output*  

可能是什么原因,我该如何解决?

【问题讨论】:

  • 您希望程序同时运行,这意味着输出将是交错的,并且您还希望输出顺序。这是两个相互矛盾的要求。您可能可以使用作业控制原语做一些事情,以便子进程在 SIGTTOU 或类似的东西上被阻止,但您没有提到那种复杂性,所以这可能不是您应该做的事情.如果您在循环中等待每个进程,您将获得顺序输出,而不是并发(异步)执行。

标签: c shell process fork


【解决方案1】:

您必须使用pipe() 为每个命令创建新的标准输出和可选的标准错误文件描述符。然后你可以按顺序读取管道,直到每个命令完成。

否则,因为每个命令都被派生到自己的进程中,所以它将在自己方便的时候运行。来自同时运行的命令的文本输出并产生输出到同一个终端的混合可能比您在此处显示的还要多。

可能是这样的

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

struct cmd_data {
    const char *cmd;
    int fd[2];  // stdout pipe for command
    pid_t pid;
    int status; // exit status
};

void cmd_launch(struct cmd_data *p, const char *cmd) {
    int r;

    p->cmd = cmd;
    r = pipe(p->fd);
    if(r<0) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    r = fork();
    if(r < 0) {
        perror("fork");
        close(p->fd[0]);
        close(p->fd[1]);
    } else if( r > 0 ) {
        p->pid = r;
        close(p->fd[1]);
    } else {
        close(p->fd[0]);
        dup2(p->fd[1], STDOUT_FILENO);
        close(p->fd[1]);
        r = execlp(cmd, cmd, NULL);
        perror("execlp");
        exit(EXIT_FAILURE);
    }
}

void cmd_join(struct cmd_data *p) {
    char buf[4096];
    const size_t buflen = sizeof buf;
    ssize_t bytes;

    printf("-- %s\n", p->cmd);
    fflush(stdout);
    while( 0 != (bytes = read(p->fd[0], buf, buflen)) ) {
        write(STDOUT_FILENO, buf, bytes);
    }
    close(p->fd[0]);
    pid_t r = waitpid(p->pid, &p->status, 0);
    if(r<0){
        perror("waitpid");
    }
    printf("-- completed with status %d\n", p->status);
    fflush(stdout);
}

int main(int argc, char *argv[]) {
    size_t cmd_c = argc - 1;
    struct cmd_data *p = calloc(argc, sizeof *p);
    size_t i;

    for(i = 0; i < cmd_c; ++i) {
        cmd_launch(p + i, argv[i + 1]);
    }

    for(i = 0; i < cmd_c; ++i) {
        cmd_join(p + i);
    }

    free(p);
    return EXIT_SUCCESS;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-29
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多