2路管道通讯。挂

时间:2014-09-16 11:03:08

标签: c fork pipe parent-child

我试图让父母向孩子发送信息,并让孩子使用2个文件描述符将其发回。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define READ 0
#define WRITE 1 
int main(void) {

  int fdWrite[2];
  int fdRead[2];
  int pid, i, num;
  FILE* output;

  if (pipe(fdRead) == -1) {
    perror("Can't create pipe");
    exit(1);
  }

  if (pipe(fdWrite) == -1) {
    perror("Can't create pipe");
    exit(1);
  }

  char mystring[100] = { 0 };

  char c;

  pid = fork();
  if (pid) {
    FILE * read;
    FILE * write;
    close(fdRead[WRITE]);
    close(fdWrite[READ]);

    write = fdopen(fdWrite[WRITE], "w");
    fprintf(write, "parent %s\n", "jeronimooo...");

    read = fdopen(fdRead[READ], "r");
    fgets(mystring, 100, read);
    fprintf(stdout, "%s\n", mystring);

  } else {
    /* child */
    dup2(fdRead[WRITE], STDOUT_FILENO);
    close(fdRead[READ]);
    close(fdRead[WRITE]);

    dup2(fdWrite[READ], STDIN_FILENO);
    close(fdWrite[READ]);
    close(fdWrite[WRITE]);

    fgets(mystring, 100, stdin);
    fprintf(stdout, "child %s\n", mystring);

  }
  exit(0);
}

我正在尝试做什么:

  1. 写入父接收描述符读取的父文件描述符。
  2. 然后在另一个描述符中,将子信息发送到父级的接收描述符。
  3. 目前暂停在线:fgets(mystring,100, read)

2 个答案:

答案 0 :(得分:1)

C I / O流通常是缓冲的,这意味着当您执行此操作时fprintf然后您打印到流中的内容实际上没有写入文件,而是写入内存缓冲区。当缓冲区已满时,其中的数据实际写入文件。 fflush函数刷新缓冲区,即它占用缓冲区中的内容并立即将其写入文件。

这里的问题是当你执行fdopen时,文件流是使用完全缓冲创建的(与例如stdout的行缓冲不同)所以缓冲区真的必须填充它才能成为实际写的。通过明确强制写入它,管道的另一端可以读取它。

答案 1 :(得分:0)

the following is  an excerpt for how to use a pipe, 
extracted from a working system
where this pipe was used to kick a hardware watchdog
In general, this example only contains the code needed to :
create pipe, fork, write pipe, read pipe.

typedef struct
{
    struct timespec time;
    int tracking_number;
    long magic;
} WatchdogRecord;

WatchdogRecord watchdog_record;
pid_t  childpid;
int watchdog_pipe[2];

// open the pipe
pipe(watchdog_pipe);

// Set both ends of pipe to nonblocking
for(pipe_end=0; pipe_end<2; pipe_end++)
{
    // Get previous flags
    int f = fcntl(watchdog_pipe[pipe_end], F_GETFL, 0);

    // Set bit for non-blocking flag
    f |= O_NONBLOCK;

    // Change flags on fd
    fcntl(watchdog_pipe[pipe_end], F_SETFL, f);

} // for each pipe_end

// fork the child process
if ((childpid = fork()) == -1)
{ // then fork failed

    perror("fork");
    exit(1);
}

// implied else, fork successful

if (childpid == 0)
{ // then child process

    // child closes up 'write' side of pipe
    close(watchdog_pipe[1]);


        // if any pipe input then store it
        while (((readret = read(watchdog_pipe[0],
                 readbuffer+nbytes, 
                 sizeof(readbuffer)-nbytes)) != -1) 
              && 
                ((nbytes+=readret) >= sizeof(WatchdogRecord)))
        {
            wdrec = (WatchdogRecord *)readbuffer;

            // check magic number to make sure record is aligned properly in pipe
            if (wdrec->magic == WD_MAGIC)
            {
                // read a full record, so reset nbytes to 0
                nbytes = 0;
                wd_syncerror = 0;

                // and clear magic so it will have to be 
                // rewritten validly by the next read
                wdrec->magic = 0L;
            }

            else // try to resynchronize
            {
                log_error("WDPipe Out Of Sync!, magic=0x%p\n", wdrec->magic);

                //drop one of nbytes and wait for next try to resync
                nbytes = 1;

                // if this happens too many times, die
                if (++wd_syncerror > sizeof(WatchdogRecord))
                {
                    log_error("WDPipe Out Of Sync Too Long!\n");
                    watchdog_die();

                } // ? too many sync errors


                // fill in temporary info for wdrec so we don't use bad data
                wdrec->time = curtime;
                wdrec->tracking_number = -1;

            } // pipe out of sync 
}
else
{ // else parent process

    // parent closes 'read' side of pipe
    close(watchdog_pipe[0]);


// send message through pipe,
// remember pipe has no concept of record, 
// so include a 'marker' so receiver can find edge of record
watchdog_record.time = curtime;
watchdog_record.tracking_number = tracking_number;
watchdog_record.magic = WD_MAGIC;
write(watchdog_pipe[1], &watchdog_record, sizeof(WatchdogRecord));