在C / Linux中使用命名管道和fork

时间:2015-05-19 14:49:21

标签: c linux fork named-pipes

我正在尝试编写从用户读取文本的简单控制台应用程序,然后将小写更改为大写,最后在控制台中打印结果。 当我只使用一个管道时(例如没有从控制台读取文本)它工作正常,但当我使用两个管道时,它完全不可预测。

在发送短信之前,不应该'[写入]'等待'[上限]'?

我得到了以下输出:

  

[写入]等待txt显示。
  [To upper]等待txt改变。
  [写]收到以下txt:
  [To upper]收到txt()。
  [To upper]将txt发送更改为[Write]()   [扫描]输入你的txt:
  [扫描]收到Txt。发送至[To upper](y)

我的代码:

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#define SIZE 16
int main()
{
    int i=0;
    int f1,f2;
    char x[SIZE]={0};
    if( fork() )    
    {
        if( fork() )//[Write]
        {
            f1=open("upper-write",O_RDONLY);
            puts( "[Write] Waiting for txt to diplay." );
            read( f1, &x, sizeof( x ) );
            printf( "[Write] Received following txt: %s\n", x );
            close( f1 );
        }
        else//[Scan]
        {
            puts( "[Scan] Type your txt: " );
            //scanf ("%15s",x);//scanf not working now, so I change my char array by myself     
            x[0]='y';
            f2=open("scan-upper",O_WRONLY);
            printf( "[Scan] Txt received. Sending to [To upper] (%s)\n", x );
            write( f2, &x, sizeof( x ) );
            close( f2 );
        }
    } 
    else//[To upper]
    {
        puts( "[To upper] Waiting for txt to change." );
        f2=open("scan-upper",O_RDONLY);
        read( f2, &x, sizeof( x ) );
        close( f2 );

        printf( "[To upper] Received txt (%s).\n" ,x);  
        for(i=0;i<SIZE;i++)
            if(x[i]>=97 && x[i] <=122)//lowercase -> uppercase
                x[i]-=32;


        f1=open("upper-write",O_WRONLY);
        write( f1, &x, sizeof( x ) );
        printf( "[To upper] Changed txt send to [Write] (%s).\n" ,x);
        close( f1 );
    }
}

2 个答案:

答案 0 :(得分:2)

我认为你需要了解一些事情来理解这个问题。首先,在fork()之后,无法保证首先运行哪个进程。其次,如果管道的另一端没有打开写入,read()会立即返回值为零。

您依赖于按特定顺序运行的流程,以便在进行任何读取之前管道都在两侧打开。由于这并不总是发生,read()并不总是阻止。

您可以通过在fork()之前打开所有管道的两端来解决此问题。所有进程都会在管道的两端都有文件描述符。只需在相应流程中不需要的文件描述符上调用close()即可。

答案 1 :(得分:-1)

你确定这不是因为你的非扫描进程没有关闭stdin吗?您可能希望在fork之后执行类似“close(0)”的操作。

或者,有popen(),这可能对这种东西很有趣。