2010-05-29 104 views
1

我想制作一个简单的程序,即fork和子进程写入命名管道,父进程从命名管道读取并显示。 问题是,它进入父级,第一个printf,然后它变得奇怪,它不做任何其他事情,没有得到第二个printf,它只是在控制台输入的方式。C命名管道(fifo)。父进程卡住

所有的
#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
void main() 
{ 
char t[100]; 
mkfifo("myfifo",777); 
pid_t pid; 
pid = fork(); 
if (pid==0) 
{ 
    //execl("fifo2","fifo2",(char*)0); 
    char r[100]; 
    printf("scrie2->"); 
    scanf("%s",r); 

    int fp; 
    fp = open("myfifo",O_WRONLY); 
    write(fp,r,99); 
    close(fp); 
    printf("exit kid \n"); 
    exit(0); 
} else 
{ 
    wait(0); 
    printf("entered parent \n"); // <- this it prints 
    // whats below this line apparently its not being executed 
    int fz; printf("1"); 
    fz = open("myfifo",O_RDONLY); printf("2"); 
    printf("fd: %d",fz); 
    char p[100]; 
    int size; 
    printf("------"); 
    //struct stat *info; 
    //stat("myfifo",info); printf("%d",(*info).st_size); 
    read(fz,p,99); 
    close(fz); 
    printf("%s",p); 

    printf("exit"); exit(0); 
} 
} 

回答

3

首先,尝试fprintf中到stderr代替了printf(到stdout)

标准错误是无缓冲。

然后你可以知道实际打印什么和不打印什么。

或至少在等待任何事情之前添加fflush

5

你真的应该检查函数调用的错误返回值,特别是mkfifo()open()

您拨打wait()的电话会导致其当前位置出现问题。打开一个FIFO用于正常读取块,直到某个其他进程打开相同的FIFO进行写入,反之亦然。父母正在等待孩子终止,孩子正在等待读者进程(即父母)连接到FIFO。

1 - 见注上open()下面是一个用O_NONBLOCK与FIFO

移动wait()调用父进程在调用mkfifo()模式更改为0666退出一起之前似乎解决了一些你眼前的问题。

当你完成它时,删除FIFO也是一种很好的做法。

unlink("myfifo"); 

open() function documentation in IEEE Std 1003.1-2004

当打开一个FIFO与O_RDONLY或O_WRONLY设置:

  • 如果O_NONBLOCK被设置,一个开放的()用于读只应毫不迟延地返回。如果没有进程打开文件以供读取,则用于只写的open()应返回错误。

  • 如果O_NONBLOCK为空,则只读的open()将阻塞调用线程,直到线程打开文件进行写入。用于只写的open()应阻塞调用线程,直到线程打开文件以供读取。


下面的例子是和code in your original question的组合FIFO page of Beej's Guide to Unix IPC

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <unistd.h> 

#define FIFO_NAME "myfifo" 

int main(void) 
{ 
    char buf[256]; 
    int num, fd; 
    pid_t pid; 

    if (mkfifo(FIFO_NAME, 0666) < 0) 
     perror("mkfifo"); 

    pid = fork(); 
    if (pid == 0) 
    { 
     printf("child - waiting for readers...\n"); 
     if ((fd = open(FIFO_NAME, O_WRONLY)) < 0) 
      perror("child - open"); 

     printf("child - got a reader -- type some stuff\n"); 
     while (fgets(buf, sizeof(buf), stdin), !feof(stdin)) 
     { 
      if ((num = write(fd, buf, strlen(buf))) < 0) 
       perror("child - write"); 
      else 
       printf("child - wrote %d bytes\n", num); 
     } 

     close(fd); 
     exit(0); 
    } 
    else 
    { 
     printf("parent - waiting for writers...\n"); 
     if ((fd = open(FIFO_NAME, O_RDONLY)) < 0) 
      perror("parent - open"); 

     printf("parent - got a writer\n"); 
     do 
     { 
      if ((num = read(fd, buf, sizeof(buf))) < 0) 
       perror("parent - read"); 
      else 
      { 
       buf[num] = '\0'; 
       printf("parent - read %d bytes: \"%s\"\n", num, buf); 
      } 
     } while (num > 0); 

     close(fd); 
     wait(0); 
    } 

    unlink(FIFO_NAME); 
    return 0; 
}

这个例子在Linux的测试。按Ctrl - D终止程序。

+0

我打开FIFO,但我在同一个过程中关闭它。所以它不应该阻止。我需要我的父进程在孩子之后等待,因为孩子得到了输入,并且我不能等待父进程的第一行,因为那意味着开始从fifo读取,当我甚至没有完成时写在它上面 – Blitzkr1eg 2010-05-30 11:06:21

+0

现在我有: char c [2]; c [1] = 0; C [0] = 0; c [0] = strlen(r); // c [0]可以说是4 write(fp,c,1); // FP是FIFO 然后在另一个过程: //开口管,我检查错误,但没有错误,所以它打开细 炭C [2]; C [1] = 0; C [0] = 0; read(fz,c,1); // fz是管道 //现在c [0]是0而不是它应该是的,4 – Blitzkr1eg 2010-05-30 15:05:22

+0

在评论中描述的代码更改之后,可能很难。你最好编辑你的问题来展示你的尝试。我在我的回复中添加了一个例子,可以帮助你。 – jschmier 2010-05-30 17:23:14