fflush在命名管道中不起作用

时间:2012-12-08 09:54:44

标签: c

我有这个代码: 当第一个孩子向第二个孩子发送数据时程序卡住, 第二个孩子做了fscanf然后卡住了因为他无法读到我找不到它的原因。 请帮助我找出如何确保fflush将传输数据。

int main()
{
    pid_t childPid ; //Child's and father process id.
    int i ; //An index to create children in loop.
    unsigned int st_search_prime = 0 ;

    if((mkfifo(FIRST_FIFO, S_IFIFO | 0644) == FAIL && errno != EEXIST) ||
       (mkfifo(SECOND_FIFO, S_IFIFO | 0644) == FAIL && errno != EEXIST))
    {
        perror("Cannot create fifo file") ;
        exit(EXIT_FAILURE) ;
    }
    //create the children
    for(i = 0 ; i < NUM_OF_CHILDS  ; i++)
    {
        childPid = fork() ;
        if(childPid < 0)    //Fork failed.
        {
            perror("Cannot fork()") ;
            exit(EXIT_FAILURE) ;
        }
        else if(childPid == CHILD)  //child process
        {
            if(i == FIRST_SON)  //the 1st child process
                doChild1(st_search_prime) ;
            else        //the 2nd child process.
                doChild2(st_search_prime) ;
        }
    }
    //wait for the children to exit.
    for(i = 0 ; i < NUM_OF_CHILDS ; i++)
        wait(&childPid) ;

    return(EXIT_SUCCESS) ;
}

void doChild1(unsigned int st_search_prime)
{
    int counter = 0 ; //Counter for N successfully raffle .
    FILE* fdw1 ;
    FILE* fdr2 ;

    if((!(fdw1 = fopen(FIRST_FIFO, "w"))))
    {
        perror("Cannot open fifo file for w/r") ;
        exit(EXIT_FAILURE) ;
    }

    if((!(fdr2 = fopen(SECOND_FIFO, "r"))))
    {
        perror("Cannot open fifo file for w/r") ;
        exit(EXIT_FAILURE) ;
    }

    for(; counter < N ; counter++)
    {
        st_search_prime = raffle_prime(st_search_prime) ;
        **fprintf(fdw1, "%u\n", st_search_prime) ;
        fflush(fdw1) ;**
        printf("%u\n", st_search_prime) ;
        fscanf(fdr2, "%u\n", &st_search_prime) ;
    }
    fclose(fdw1) ;
    fclose(fdr2) ;

    exit(EXIT_SUCCESS) ;
}

void doChild2(unsigned int st_search_prime)
{
    int counter = 0 ; //Counter for N successfully raffle .
    FILE* fdw2 ;
    FILE* fdr1 ;

    if((!(fdr1 = fopen(FIRST_FIFO, "r"))))
    {
        perror("Cannot open fifo file for w/r") ;
        exit(EXIT_FAILURE) ;
    }
    if(!(fdw2 = fopen(SECOND_FIFO, "w")))
    {
        perror("Cannot open fifo file for w/r") ;
        exit(EXIT_FAILURE) ;
    }

    for(; counter < N ; counter++)
    {
        **fscanf(fdr1, "%u\n", &st_search_prime);**
        st_search_prime = raffle_prime(st_search_prime) ;
        fprintf(fdw2, "%u\n", st_search_prime) ;
        fflush(fdw2) ;
        printf("%u\n", st_search_prime) ;
    }
    fclose(fdr1) ;
    fclose(fdw2) ;

    exit(EXIT_SUCCESS) ;
}

2 个答案:

答案 0 :(得分:0)

尝试添加致电setlinebuf(fdw1) - 这应该会有所帮助。

此换算在换行后强制刷新缓冲区。您也可以使用参数setvbuf()的{​​{1}}来获得相同的效果,或者使用_IOLBF来完全禁用缓冲。

答案 1 :(得分:0)

我认为问题在于\n模式中使用fscanffscanf的手册页说:

  

格式字符串由一系列指令组成   描述如何处理输入字符序列。如果   指令的处理失败,没有读取进一步的输入,和   scanf()返回。 A&#34;失败&#34;可以是以下任何一种:   输入失败,意味着输入字符不可用,或   匹配失败,意味着输入不合适......

此外,根据指示,我们有:

  

一系列空格字符(空格,制表符,换行符等;请参阅   isspace为(3))。该指令匹配任意数量的空白区域,   包括无,在输入中。

因此,当在doChild2中使用fscanf模式"%u\n"时,模式由两个输入指令组成,%u与传入的数字匹配,然后{{ 1}}匹配传入的换行符(空格)。此时\n将继续寻找更多输入,因为不再发送输入会导致程序阻塞。

为什么fscanf会回去寻找更多输入?上面的第一个引用告诉我们终止的两个条件,或者没有更多的输入;好了,fifo仍然是开放的,所以我们不知道更多的输入不在路上,所以不满足条件,或者,如果指令不匹配,fscanf将返回;但那还没有发生。

就修复而言,从fscanf模式中删除\n就足够了。手册页告诉我们:

  

大多数转化会丢弃初始空格字符......

fscanf就属于这种情况,因此,如果您使用%u%u\n的模式发送的模式为fscanf,那么%u将导致\n指令失败,导致%u返回。这会将fscanf留在输入缓冲区中,但是,对\n的下一次调用将丢弃初始空格(换行符),并且一切都应该正常。