0

私の先生は、オペレーティング システムのクラスで勉強するための練習問題を私たちに与えました。課題は、3 つのプロセスをまとめてパイプし、タイトルのコマンドを一度に実装することでした。これらのコマンドは、実装時にのみ使用できます。

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

2 つを一緒にパイプすることはできますが、3 つを行う方法がわかりません。誰かがそれを行う方法を教えてくれるか、少なくとも正しい方向に向けてくれますか?

これまでの私のコードは次のとおりです。

#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*()呼び出しが必要になります。初期プロセスが最終的に実行するプロセスを決定する必要があります。ほとんどの場合、psまたは のいずれかwcです。どちらの方法でもコードを記述できますが、開始する前に決定してください。

中間プロセスであるgrepには、入力用のパイプと出力用のパイプが必要になります。1 つのパイプと 1 つの子プロセスを作成psし、出力をパイプに送って実行することができます。次に、別のパイプと別の子プロセスを作成し、実行する前にそのパイプを修正しgrepます。元のプロセスでは両方のパイプが開かれ、実行前にほとんどのファイル記述子が閉じられますwc

パイプで重要なことは、十分なファイル記述子を確実に閉じることです。標準入力または標準出力へのパイプを複製する場合、ほとんどの場合、呼び出しによって返された元のファイル記述子の両方を閉じる必要があります。pipe()あなたの例では、両方を閉じる必要があります。パイプが 2 つあるということは、閉じる必要がある記述子が 4 つあるということです。

作業コード

エラー報告と終了機能の使用に注意してください。エラー報告が大幅に簡素化されます。さまざまなエラー報告を行う関数のライブラリがあります。これは、これらの関数の 1 つの単純な実装です。(これは非常に単純です。メッセージにプログラム名が含まれていません。)

#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 に答える