0

そのため、オペレーティング システム クラスの割り当てがあり、パイプで接続されたプロセスのリングを作成して、プロセス間でメッセージを渡す必要があります。私は、自分のニーズに合わせて (または少なくとも理解するために) 適応しようとしていたサンプル コードを見つけました。サンプル コード (少し変更) は次のとおりです。

/* Program 4.1 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

/* Sample C program for generating a unidirectional ring of processes.Invoke this program
 with a command-line arg ument indicating the number of processes on the ring.  Communication
 is done via pipes that connect the standard output of a process to the standard input of
 its successor on the ring.  After the ring is created, each process identifies itself with
 its process ID and the  process ID of its parent.  Each process then exits. */

void main(int argc,  char *argv[ ])
{
int master_pid = getpid();
printf("master pid: %i\n", master_pid);

int   i;             /* number of this process (starting with 1)   */
int   childpid;      /* indicates process should spawn another     */
int   nprocs;        /* total number of processes in ring          */
int   fd[2];         /* file descriptors returned by pipe          */
int   error;         /* return value from dup2 call                */
/* check command line for a valid number of processes to generate */
if ( (argc != 2) || ((nprocs = atoi (argv[1])) <= 0) ) {
    fprintf (stderr, "Usage: %s nprocs\n", argv[0]);
    exit(1);
}
/* connect std input to std output via a pipe */
if (pipe (fd) == -1) {
    perror("Could not create pipe");
    exit(1);
}
printf("%s\n", "test");
//this section is blocking printf()?
if ((dup2(fd[0], STDIN_FILENO) == -1) ||
    (dup2(fd[1], STDOUT_FILENO) == -1)) {
    perror("Could not dup pipes");
    exit(1);
}
printf("%s\n", "test");

if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
    perror("Could not close extra descriptors");
    exit(1);
}
/* create the remaining processes with their connecting pipes */
for (i = 1; i < nprocs;  i++) {
    if (pipe (fd) == -1) {
        fprintf(stderr,"Could not create pipe %d: %s\n",
                i, strerror(errno));
        exit(1);
    }
    if ((childpid = fork()) == -1) {
        fprintf(stderr, "Could not create child %d: %s\n",
                i, strerror(errno));
        exit(1);
    }
    if (childpid > 0)        /* for parent process, reassign stdout */
        error = dup2(fd[1], STDOUT_FILENO);
    else
        error = dup2(fd[0], STDIN_FILENO);
    if (error == -1) {
        fprintf(stderr, "Could not dup pipes for iteration %d: %s\n",
                i, strerror(errno));
        exit(1);
    }
    if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
        fprintf(stderr, "Could not close extra descriptors %d: %s\n",
                i, strerror(errno));
        exit(1);
    }
    if (childpid)
        break;
}

/* say hello to the world */
fprintf(stderr,"This is process %d with ID %d and parent id %d\n",
        i, (int)getpid(), (int)getppid());
wait(1);
exit (0);
}     /* end of main program here */

出力:

master pid: 30593
test
This is process 1 with ID 30593 and parent id 30286
This is process 2 with ID 30594 and parent id 30593

私が与えるときはargv [1]として2です

では、なぜ dup2 セクションが printf() の実行を妨げるのでしょうか? 何かを印刷することさえできない場合、メッセージを正しく渡すことさえできるかどうかわかりません。また、なぜ fprintf() が既に機能しているのに、私がそこに置くものではないのですか?

編集:私はこれを私の教授/TAに持って行きますが、彼らは町の外にいて、今から締め切りまでの間は連絡が取れません...

4

2 に答える 2

1

printfファイル記述子 1 (または同等のSTDOUT_FILENO) である stdout に出力します。 dup2(3)現在の標準出力の上にパイプのファイル記述子を複製しています。これには、現在の標準出力を閉じるという副作用があります。printfそのため、その特定の を呼び出した後にしようとするとdup2、作成したばかりのパイプにデータが実際に出力されますが、これは端末出力にはなりません。

fprintf(stderr, ...)stdoutではなくstderrに出力さSTDERR_FILENOれ、プログラム中にstderrファイル記述子(2、または同等)が変更されないため、引き続き機能します。したがって、端末に出力し続けます。

于 2012-09-20T17:16:46.497 に答える
0

printf() はパス 0 にデータを送信しませんstdoutstdoutパス 0 に何かを dup2 して中断すると、その過程で中断しているように見えます。

dup2 の man ページから: dup2() makes newfd be the copy of oldfd, closing newfd first if necessary. したがって、あなたが呼び出すとき、dup2(fd[0], STDIN_FILENO)あなたは壊れてstdoutいます。

fprintf() は機能していると述べていますが、printf() は機能していません... fprintf() に使用しているパスは何ですか? を使用している場合stderr、そのパスで何もしていないため、引き続き機能することは完全に理にかなっています。

于 2012-09-20T17:06:33.370 に答える