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

当我给 2 作为 argv[1]

所以,我想知道,为什么 dup2 部分会阻止 printf() 执行?如果我什至不能打印某些东西,我不确定我是否可以正确传递消息。另外,为什么 fprintf() 已经在那里工作了,但我不会放在那里?

编辑:我会把这个带给我的教授/助教,但他们都在城外,从现在到截止日期之前都无法到达......

4

2 回答 2

1

printf打印到标准输出,即文件描述符 1(或等效的STDOUT_FILENO)。 dup2(3)正在将管道的文件描述符复制到当前标准输出之上,这具有关闭当前标准输出的副作用。printf因此,当您在调用该 specific 之后尝试执行此操作时dup2,您实际上是在将数据打印到刚刚创建的管道中,而不会进入您的终端输出。

fprintf(stderr, ...)仍然有效,因为它打印到 stderr,而不是 stdout,并且 stderr 文件描述符(2 或等效STDERR_FILENO的)在程序期间不会更改,因此它继续打印到终端。

于 2012-09-20T17:16:46.497 回答
0

printf() 不向路径 0 发送数据,它使用stdout. 看起来,当您通过复制某些内容来破坏路径 0 时,您正在破坏stdout该过程。

从 dup2: 的手册页中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 回答