0

我的老师给了我们一个练习作业,让我们在操作系统课上学习。任务是将三个进程连接在一起并同时执行标题中的命令。我们只允许在实现时使用这些命令:

dup2()
one of the exec()
fork()
pipe()
close()

我可以把两个管在一起,但我不知道怎么做三个。有人可以告诉我怎么做,或者至少给我指出正确的方向吗?

到目前为止,这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
        int pfd[2];
        int pfdb[2];
        int pid;

        if (pipe(pfd) == -1) {
                perror("pipe failed");
                exit(-1);
        }
        if ((pid = fork()) < 0) {
                perror("fork failed");
                exit(-2);
        }
        if (pid == 0) {
                close(pfd[1]);
                dup2(pfd[0], 0);
                close(pfd[0]);
                execlp("ps", "ps", "-ef", (char *) 0);
                perror("ps failed");
                exit(-3);
        } 
        else {
                close(pfd[0]);
                dup2(pfd[1], 1);
                close(pfd[1]);
                execlp("grep", "grep", "darrowr", (char *) 0);
                perror("grep failed");
                exit(-4);
        }
        exit(0);

}

任何帮助,将不胜感激。哎呀,如何完成它的教程将是奇妙的!

4

1 回答 1

0

您将需要 3 个进程和 2 个管道将它们连接在一起。您从 1 个进程开始,因此您将需要 2 个fork()调用、2 个pipe()调用和 3 个exec*()调用。您必须决定初始进程将最终运行哪些进程;很可能是pswc。您可以用任何一种方式编写代码,但在开始之前决定。

中间进程 ,grep将需要一个管道作为输入,一个管道作为输出。您可以创建一个管道和一个子进程,并让它运行ps,其输出进入管道;然后创建另一个管道和另一个子进程,并在运行之前修复它的管道grep;原始进程将打开两个管道,并在运行之前关闭大部分文件描述符wc

管道的关键是确保您关闭了足够多的文件描述符。如果您将管道复制到标准输入或标准输出,您应该几乎总是关闭调用返回的两个原始文件描述符pipe();在您的示例中,您应该关闭两者。并且有两个管道,这意味着有四个描述符要关闭。

工作代码

注意错误报告和退出功能的使用;它极大地简化了错误报告。我有一个函数库,可以执行不同的错误报告;这是其中一个功能的简单实现。(这太简单了:它不包括消息中的程序名称。)

#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void err_syserr(const char *fmt, ...);

int main(void)
{
  int p1[2];
  int p2[2];
  pid_t pid1;
  pid_t pid2;

  if (pipe(p1) == -1)
    err_syserr("failed to create first pipe");
  if ((pid1 = fork()) < 0)
    err_syserr("failed to fork first time");
  if (pid1 == 0)
  {
    dup2(p1[1], STDOUT_FILENO);
    close(p1[0]);
    close(p1[1]);
    execlp("ps", "ps", "-ef", (char *)0);
    err_syserr("failed to exec 'ps'");
  }
  if (pipe(p2) == -1)
    err_syserr("failed to create second pipe");
  if ((pid2 = fork()) < 0)
    err_syserr("failed to fork second time");
  if (pid2 == 0)
  {
    dup2(p1[0], STDIN_FILENO);
    close(p1[0]);
    close(p1[1]);
    dup2(p2[1], STDOUT_FILENO);
    close(p2[0]);
    close(p2[1]);
    execlp("grep", "grep", "root", (char *)0);
    err_syserr("failed to exec 'grep'");
  }
  else
  {
    close(p1[0]);
    close(p1[1]);
    dup2(p2[0], STDIN_FILENO);
    close(p2[0]);
    close(p2[1]);
    execlp("wc", "wc", (char *)0);
    err_syserr("failed to exec 'wc'");
  }
  /*NOTREACHED*/
}

#include <stdarg.h>
#include <errno.h>
#include <string.h>

static void err_syserr(const char *fmt, ...)
{
  int errnum = errno;
  va_list args;
  va_start(args, fmt);
  vfprintf(stderr, fmt, args);
  va_end(args);
  if (errnum != 0)
    fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
  putc('\n', stderr);
  exit(EXIT_FAILURE);
}

样本输出:

    234    2053   18213

看来,我的机器正忙于运行 root 拥有的程序。

于 2014-10-28T15:17:25.213 回答