Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 双向管道通信。悬挂_C_Fork_Pipe_Parent Child - Fatal编程技术网

C 双向管道通信。悬挂

C 双向管道通信。悬挂,c,fork,pipe,parent-child,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

我试图让家长向孩子发送信息,让孩子使用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);
}
#包括
#包括
#包括
#定义读取0
#定义写入1
内部主(空){
int-fdWrite[2];
int-fdRead[2];
int-pid,i,num;
文件*输出;
如果(管道(fdRead)=-1){
perror(“无法创建管道”);
出口(1);
}
if(管道(fdWrite)=-1){
perror(“无法创建管道”);
出口(1);
}
char mystring[100]={0};
字符c;
pid=fork();
如果(pid){
文件*读取;
文件*写入;
关闭(fdRead[WRITE]);
关闭(fdWrite[READ]);
write=fdopen(fdWrite[write],“w”);
fprintf(写入“父%s\n”、“jeronimooo…”);
read=fdopen(fdRead[read],“r”);
fgets(mystring,100,read);
fprintf(stdout,“%s\n”,mystring);
}否则{
/*孩子*/
dup2(fdRead[WRITE],标准输出文件号);
关闭(fdRead[READ]);
关闭(fdRead[WRITE]);
dup2(fdWrite[READ],标准文件号);
关闭(fdWrite[READ]);
关闭(fdWrite[WRITE]);
fgets(mystring,100,stdin);
fprintf(stdout,“子%s\n”,mystring);
}
出口(0);
}
我想做的是:

  • 写入父级中由其接收描述符读取的文件描述符
  • 然后在另一个描述符中,将信息从子描述符发送到父描述符中的接收描述符

  • 当前是挂起的:
    fgets(mystring,100,read)

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

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

    以下是如何使用管道的摘录,
    
    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));
    
    从工作系统中提取 这根管子是用来踢硬件看门狗的 通常,此示例仅包含以下所需的代码: 创建管道、分叉、写入管道、读取管道。 类型定义结构 { 结构时间段时间; int跟踪u数; 长魔术; }观察记录; 看门狗记录看门狗记录; pid_t childpid; int看门狗_管道[2]; //打开管子 管道(看门狗管道); //将管道两端设置为非阻塞 对于(管道末端=0;管道末端=sizeof(WatchdogRecord))) { wdrec=(WatchdogRecord*)读缓冲区; //检查幻数,确保记录在管道中正确对齐 如果(wdrec->magic==WD_magic) { //读取完整记录,因此将N字节重置为0 n字节=0; wd_syncerror=0; //和清晰的魔法,所以它必须是 //通过下一次读取有效重写 wdrec->magic=0L; } 否则//尝试重新同步 { 日志错误(“WDPipe不同步,magic=0x%p\n”,wdrec->magic); //删除其中一个N字节并等待下一次尝试重新同步 n字节=1; //如果这种情况发生太多次,就去死吧 如果(++wd_syncerror>sizeof(WatchdogRecord)) { 日志错误(“WDPipe不同步太长!\n”); 看门狗死了; }//?同步错误太多 //填写wdrec的临时信息,这样我们就不会使用坏数据 wdrec->time=curtime; wdrec->跟踪号=-1; }//管道不同步 } 其他的 {//else父进程 //父级关闭管道的“读取”侧 关闭(看门狗_管道[0]); //通过管道发送消息, //记住管道没有记录的概念, //所以包括一个“标记”,以便接收者可以找到记录的边缘 看门狗_record.time=curtime; 看门狗_记录。跟踪_编号=跟踪_编号; watchdog_record.magic=WD_magic; 写入(看门狗_管道[1],&watchdog_记录,sizeof(看门狗记录));
    挂起哪个
    fgets
    调用?有两个。另外,我不知道
    fdopen
    使用什么缓冲模式,您可能想检查一下,这样它就不会被完全缓冲。写完之后试试
    fflush
    。@JoachimPileborg,谢谢!您能解释一下fflush工作的原因吗?或者
    setvbuf(3)
    来明确更改缓冲类型。