2012-09-20 67 views
0

所以,我有一個作業系統類的任務,其中我要創建一個與管道連接的進程環,以便在它們之間傳遞消息。我發現了一些示例代碼,我希望能夠適應(或至少理解)我的需求。示例代碼(略有修改)是:dup2阻止printf,但不是fprintf?

/* 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,但現在並限期之間更有耐力都出城,將是不可到達...

回答

1

printf打印到標準輸出,即文件描述符1(或等效爲STDOUT_FILENO)。 dup2(3)在當前stdout的頂部複製了管道的文件描述符,這具有關閉當前stdout的副作用。因此,在調用特定dup2之後嘗試調用printf時,實際上是將數據打印到剛剛創建的管道中,而這些管道並不會傳送到終端輸出。

fprintf(stderr, ...)仍然有效,因爲打印到stderr而不是stdout,並且stderr文件描述符(2或等效STDERR_FILENO)在程序期間不會更改,因此它會繼續打印到終端。

+0

哇,是的,完全一直盯着這段代碼太長 – Drake

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,那麼它會很有意義,它會繼續工作,因爲您沒有采取任何行動。

相關問題