首页 文章

dup2阻塞printf,但不是fprintf?

提问于
浏览
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()已经在那里工作了,但是我不会把它放在那里?

编辑:我会把它带到我的教授/ TA,但他们都离开了城市,从现在到截止日期之间将无法到达......

2 回答

  • 0

    printf 打印到stdout,即文件描述符1(或等效 STDOUT_FILENO ) . dup2(3)正在复制当前标准输出顶部的管道文件描述符,这会产生关闭当前标准输出的副作用 . 所以,当你在调用特定的 dup2 后尝试 printf 时,你're really printing the data into the pipe you just created, which doesn' t转到你的终端输出 .

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

  • 1

    printf()不向路径0发送数据,它使用 stdout 发送缓冲数据 . 当你通过dup2 'ing something to it, you'扰乱路径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 那么它将继续工作是完全合理的,因为你没有对这条路做任何事情 .

相关问题