【问题标题】:2 way pipe communication. hang2路管道通讯。悬挂
【发布时间】:2014-09-16 11:03:07
【问题描述】:

我正在尝试让父母使用 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. 然后在另一个描述符中,将信息从子级发送到其父级中的接收描述符。

目前正在挂起:fgets(mystring,100, read)

【问题讨论】:

  • 挂在 which fgets 电话上?有两个。
  • 另外,我不知道fdopen 使用什么缓冲模式,你可能想检查一下,它不是完全缓冲的。写完试试fflush
  • @JoachimPileborg,谢谢!你能解释一下为什么 fflush 有效吗?

标签: c fork pipe parent-child


【解决方案1】:

C I/O 流通常是缓冲的,这意味着当你做例如fprintf 那么您打印到流中的内容实际上并没有写入文件,而是写入内存缓冲区。当缓冲区已满时,其中的数据实际上会写入文件。 fflush 函数刷新缓冲区,即它获取缓冲区中的内容并立即将其写入文件。

这里的问题是,当您执行fdopen 时,文件流是使用完整缓冲创建的(与例如stdout 的行缓冲不同),因此实际上必须填充缓冲区才能实际写入。通过显式强制写入,管道的另一端可以读取它。

【讨论】:

  • setvbuf(3) 显式更改缓冲区类型。
【解决方案2】:
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));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    相关资源
    最近更新 更多