2012-12-09 30 views
-1

下面的函數執行過程中,返回其PID,並提供文件描述符進行讀取和寫入:popen2:閱讀的作品,寫不

pid_t popen2(const char **command, int *infp, int *outfp) 
{ 
    int p_stdin[2], p_stdout[2]; 
    pid_t pid; 

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) { 
     return -1; 
    } 

    pid = fork(); 

    if (pid < 0) { 
     return pid; 
    } else if (pid == 0) { 
     close(p_stdin[WRITE]); 
     dup2(p_stdin[READ], READ); 
     close(p_stdout[READ]); 
     dup2(p_stdout[WRITE], WRITE); 

     execvp(*command, command); 
    } 

    if (infp == NULL) { 
     close(p_stdin[WRITE]); 
    } else { 
     *infp = p_stdin[WRITE]; 
    } 

    if (outfp == NULL) { 
     close(p_stdout[READ]); 
    } else { 
     *outfp = p_stdout[READ]; 
    } 

    return pid; 
} 

我打電話與

pid = popen2(..., &in, &out); 
上述功能

nBytes = read(out, line, sizeof(line)); 

從文件描述符out讀取和I R什麼ead非常有意義。它通常顯示在控制檯上。然而,當我嘗試寫一個命令,它通常會通過控制檯接收到的程序

nBytes = write(in, cmd, strlen(cmd)+1); 

沒有任何反應。該計劃沒有顯示任何反應。

我在這裏錯過了什麼?

+0

題外話:你做ralise上的錯誤這個片段會以不可思議的速度泄漏filedescriptors? – wildplasser

+0

@wildplasser:是的,我清除了錯誤處理。 – chessweb

+0

順便說一句,這個問題似乎出現在調用者(nBytes = write(in,cmd,strlen(cmd)+1);'(爲什麼你要寫nulbyte呢?)請告訴我們調用代碼 – wildplasser

回答

0

我確實改變了一點,但現在它可以工作。取出後fprintf(stderr,...驗證:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <signal.h> 

#define READ_END 0 
#define WRITE_END 1 

pid_t popen2(const char **command, int fdarray[]); 
pid_t popen2(const char **command, int fdarray[]) 
{ 
    int p_stdin[2], p_stdout[2]; 
    pid_t pid; 
    int rc; 

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) { 
     return -1; 
    } 
    pid = fork(); 

    if (pid < 0) { 
     return pid; 
    } else if (pid == 0) { 
     close(p_stdin[WRITE_END]); 
     dup2(p_stdin[READ_END], STDIN_FILENO); 
     close(p_stdin[READ_END]); 

     close(p_stdout[READ_END]); 
     dup2(p_stdout[WRITE_END], STDOUT_FILENO); 
     close(p_stdout[WRITE_END]); 

     rc = execvp(*command, command); 
     _exit(EXIT_FAILURE); 
    } 

    close(p_stdout[WRITE_END]); 
    close(p_stdin[READ_END]); 
    if (fdarray == NULL) { 
     close(p_stdin[WRITE_END]); 
     close(p_stdout[READ_END]); 
    } else { 
     fdarray[READ_END] = p_stdout[READ_END]; 
     fdarray[WRITE_END] = p_stdin[WRITE_END]; 
    } 

    return pid; 
} 
#define BUFF_SIZE 1024 
struct buff { 
     size_t used; 
     size_t size; 
     char data[BUFF_SIZE]; 
     } 
     ibuf = {0,BUFF_SIZE,} 
     , obuf = {0,BUFF_SIZE,} 
     ; 

int readbuff(int fd, struct buff *bp); 
int writebuff(int fd, struct buff *bp); 

int readbuff(int fd, struct buff *bp) 
{ 
size_t done; 
int rc=0; 

for (done=0; bp->used < bp->size; bp->used+=rc, done+=rc) { 
     if (done) break; 
     fprintf(stderr, "Read(%d,%zu)\n", fd, bp->size - bp->used); 
     rc = read(fd, bp->data+bp->used, bp->size - bp->used); 
     if (rc== -1) switch (errno) { 
#if (EWOULDBLOCK != EAGAIN) 
       case EWOULDBLOCK: 
#endif 
       case EAGAIN: 
       case EINTR: rc=0; continue; 
       default: 
         fprintf(stderr, "Error on readbuff: %d: %s\n", errno, strerror(errno)); 
         goto failed; 
       } 
     fprintf(stderr, "Readbuff(%d) := %d\n", fd, rc); 
     if (rc==0) { rc = -1; break; } 
     } 
failed: 
return done ? done : rc; 
} 

int writebuff(int fd, struct buff *bp) 
{ 
size_t done; 
int rc= 0; 

for (done=0; done < bp->used ; done+=rc) { 
     if (done) break; 
     fprintf(stderr, "Write(%d,%zu)\n", fd, bp->used - done); 
     rc = write(fd, bp->data+done, bp->used - done); 
     if (rc== -1) switch (errno) { 
#if (EWOULDBLOCK != EAGAIN) 
       case EWOULDBLOCK: 
#endif 
       case EINTR: 
       case EAGAIN:rc=0; continue; 
       default: 
       fprintf(stderr, "Error on writebuff: %d: %s\n", errno, strerror(errno)); 
       goto failed; 
       } 
     fprintf(stderr, "Writebuff(%d) := %d\n", fd, rc); 
     if (rc==0) { rc = -1; break; } 
     } 
failed: 
if (done == bp->used) bp->used =0; 
else { memmove(bp->data, bp->data+done, bp->used - done); bp->used -= done; } 
return done ? done : rc; 
} 

int main (void) 
{ 
int pipes[2] = {-1,-1}; 
int rc1, rc2,err; 
char *commands[] = { "tee", "teapot", NULL}; 

// signal(SIGCHLD, SIG_IGN); 
// signal(SIGPIPE, SIG_IGN); 

rc1 = popen2(commands, pipes); 
err = errno; 

fprintf(stderr, "Rc=%d:%d(%s) pipes[0]=%d, pipes[1]=%d\n" 
     , rc1 , rc1 == -1 ? err : 0 
     , strerror(rc1 == -1?err:0) 
     , pipes[0] 
     , pipes[1] 
     ); 
if (rc1 == -1) return EXIT_FAILURE; 

while(1) { 
     fprintf(stderr, "#----------------------------------------\n"); 
     rc1 = readbuff(STDIN_FILENO, &ibuf); 
#if 1 
     if (rc1 == -1 && ibuf.used ==0) { 
       fprintf(stderr, "Rc1=%d Close %d\n", rc1, pipes[WRITE_END]); 
       close(pipes[WRITE_END]); 
       } 
     else 
#endif 
     writebuff(pipes[WRITE_END] , &ibuf); 

     rc2 = readbuff(pipes[READ_END] , &obuf); 
     writebuff(STDOUT_FILENO, &obuf); 
     fprintf(stderr, "Rc=%d/%d Ibuf[0]=%zu/%zu, Obuf[0]=%zu/%zu\n" 
       , rc1, rc2 
       , ibuf.used, ibuf.size 
       , obuf.used, obuf.size 
       ); 
     if (rc1 < 0 && rc2 < 0) break; 
     } 
wait(NULL); 

return 0; 
} 
+0

對不起,但是當我將你的解決方案實現到我的代碼中時,我得到了與以前完全相同的行爲:閱讀作品,寫作不。無論如何,謝謝你的努力。 – chessweb

+0

好吧,也許你做錯了!我的作品。 – wildplasser