简体   繁体   English

在Linux中使用fgets在C程序中命名管道丢弃数据

[英]Named Pipe Dropping Data in C Program Using fgets in Linux

I'm trying to pull data from a named pipe in a C program (gcc -std=c99) using fgets. 我正在尝试使用fgets从C程序(gcc -std = c99)中的命名管道中提取数据。 I created the pipe at the command line and I can see that it exists in the file system and is parked with ap when using "ls -la" and the rights are set for anyone to use. 我在命令行上创建了管道,可以看到它存在于文件系统中,并且在使用“ ls -la”时已将其停在ap中,并且权限已设置为任何人都可以使用。

prw-rw-rw-  1 www-data www-data    0 Dec 23 00:39 mypipe

I am sending data to the pipe with a simple script: 我使用一个简单的脚本将数据发送到管道:

#script
myPipe="/tmp/mypipe"
    for j in {0..255}
    do
#       echo "C $j"             #when this is enabled slightly more data gets through
        echo "C $j" >> $myPipe
#       sleep 0.00000000000001      #when this is enabled all the data gets through           
    done

The loop my program is trying to read from this pipe is: 我的程序试图从该管道读取的循环是:

void * reader(){

    int messages = 0;                           // keep track of how many messages we process
    char buf[PIPE_BUF];     buf[0] = 0;         //#defined  PIPE_BUF    1024
    int x=100, y=101, z=102, count=103;         //initialized to unlikely initial input results
    char linetag[PIPE_BUF]; linetag[0] = 0;     //space to store the data label
    char * pScan = NULL;
    FILE *myStream ;

    syslog (LOG_INFO, "Reader started\n");

    myStream = fopen(pipeName, "r");
    if ( myStream == NULL ) {
        syslog (LOG_INFO, "Could not open pipe %s as input to Cota\n", pipeName ) ;
        return 0;
    }
    while (1) {

        //>>> This was the problem and removing it seems to fix the issue
        //freopen(pipeName, "r", myStream);  <<<<This was the problem !!!!

        pScan==buf;
        syslog (LOG_INFO, "readp-1:msg:%i >>%s<<>>%s<< pBuf=%p, pScan=%p, count=%i, tag=%s, x=%d, y=%d, z=%d\n", messages, buf, pScan, buf, pScan, count, linetag, x,y,z);

        while ( (pScan = fgets(buf, PIPE_BUF, myStream)) == NULL){};

        if (pScan == NULL){syslog (LOG_WARNING, "ERROR NULL pScan error");}

        syslog (LOG_INFO, "readp-2:msg:%i >>%s<<>>%s<< pBuf=%p, pScan=%p, count=%i, tag=%s, x=%d, y=%d, z=%d\n", messages, buf, pScan, buf, pScan, count, linetag, x,y,z);

        count = sscanf(pScan, "%s %d %d %d", linetag, &x, &y, &z);

        syslog (LOG_INFO, "readp-3:msg:%i >>%s<<>>%s<< pBuf=%p, pScan=%p, count=%i, tag=%s, x=%d, y=%d, z=%d\n", messages, buf, pScan, buf, pScan, count, linetag, x,y,z);

        messages++;
    }
}

My syslog shows the following when I run the script as written above : 当我如上所述运行脚本时,我的系统日志显示以下内容:

Reader started
readp-1:msg:0 >><<>>(null)<< pBuf=0xbe885df4, pScan=(nil), count=103, tag=, x=100, y=101, z=102
readp-2:msg:0 >>C 0#012<<>>C 0#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=103, tag=, x=100, y=101, z=102
readp-3:msg:0 >>C 0#012<<>>C 0#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=0, y=101, z=102
readp-1:msg:1 >>C 0#012<<>>C 0#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=0, y=101, z=102
readp-2:msg:1 >>C 1#012<<>>C 1#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=0, y=101, z=102
readp-3:msg:1 >>C 1#012<<>>C 1#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=1, y=101, z=102
readp-1:msg:2 >>C 1#012<<>>C 1#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=1, y=101, z=102
readp-2:msg:2 >>C 10#012<<>>C 10#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=1, y=101, z=102
readp-3:msg:2 >>C 10#012<<>>C 10#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=10, y=101, z=102
readp-1:msg:3 >>C 10#012<<>>C 10#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=10, y=101, z=102
readp-2:msg:3 >>C 11#012<<>>C 11#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=10, y=101, z=102
readp-3:msg:3 >>C 11#012<<>>C 11#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=11, y=101, z=102
readp-1:msg:4 >>C 11#012<<>>C 11#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=11, y=101, z=102
readp-2:msg:4 >>C 15#012<<>>C 15#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=11, y=101, z=102
readp-3:msg:4 >>C 15#012<<>>C 15#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=15, y=101, z=102
readp-1:msg:5 >>C 15#012<<>>C 15#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=15, y=101, z=102
readp-2:msg:5 >>C 16#012<<>>C 16#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=15, y=101, z=102
readp-3:msg:5 >>C 16#012<<>>C 16#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=16, y=101, z=102
readp-1:msg:6 >>C 16#012<<>>C 16#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=16, y=101, z=102
readp-2:msg:6 >>C 18#012<<>>C 18#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=16, y=101, z=102
readp-3:msg:6 >>C 18#012<<>>C 18#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=18, y=101, z=102
readp-1:msg:7 >>C 18#012<<>>C 18#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=18, y=101, z=102
readp-2:msg:7 >>C 24#012<<>>C 24#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=18, y=101, z=102
readp-3:msg:7 >>C 24#012<<>>C 24#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=24, y=101, z=102
readp-1:msg:8 >>C 24#012<<>>C 24#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=24, y=101, z=102
readp-2:msg:8 >>C 39#012<<>>C 39#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=24, y=101, z=102
readp-3:msg:8 >>C 39#012<<>>C 39#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=39, y=101, z=102
readp-1:msg:9 >>C 39#012<<>>C 39#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=39, y=101, z=102
readp-2:msg:9 >>C 50#012<<>>C 50#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=39, y=101, z=102
readp-3:msg:9 >>C 50#012<<>>C 50#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=50, y=101, z=102
readp-1:msg:10 >>C 50#012<<>>C 50#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=50, y=101, z=102
readp-2:msg:10 >>C 70#012<<>>C 70#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=50, y=101, z=102
readp-3:msg:10 >>C 70#012<<>>C 70#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=70, y=101, z=102
readp-1:msg:11 >>C 70#012<<>>C 70#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=70, y=101, z=102
readp-2:msg:11 >>C 81#012<<>>C 81#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=70, y=101, z=102
readp-3:msg:11 >>C 81#012<<>>C 81#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=81, y=101, z=102
readp-1:msg:12 >>C 81#012<<>>C 81#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=81, y=101, z=102
readp-2:msg:12 >>C 108#012<<>>C 108#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=81, y=101, z=102
readp-3:msg:12 >>C 108#012<<>>C 108#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=108, y=101, z=102
readp-1:msg:13 >>C 108#012<<>>C 108#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=108, y=101, z=102
readp-2:msg:13 >>C 119#012<<>>C 119#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=108, y=101, z=102
readp-3:msg:13 >>C 119#012<<>>C 119#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=119, y=101, z=102
readp-1:msg:14 >>C 119#012<<>>C 119#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=119, y=101, z=102
readp-2:msg:14 >>C 136#012<<>>C 136#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=119, y=101, z=102
readp-3:msg:14 >>C 136#012<<>>C 136#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=136, y=101, z=102
readp-1:msg:15 >>C 136#012<<>>C 136#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=136, y=101, z=102
readp-2:msg:15 >>C 155#012<<>>C 155#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=136, y=101, z=102
readp-3:msg:15 >>C 155#012<<>>C 155#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=155, y=101, z=102
readp-1:msg:16 >>C 155#012<<>>C 155#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=155, y=101, z=102
readp-2:msg:16 >>C 172#012<<>>C 172#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=155, y=101, z=102
readp-3:msg:16 >>C 172#012<<>>C 172#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=172, y=101, z=102
readp-1:msg:17 >>C 172#012<<>>C 172#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=172, y=101, z=102
readp-2:msg:17 >>C 193#012<<>>C 193#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=172, y=101, z=102
readp-3:msg:17 >>C 193#012<<>>C 193#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=193, y=101, z=102
readp-1:msg:18 >>C 193#012<<>>C 193#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=193, y=101, z=102
readp-2:msg:18 >>C 213#012<<>>C 213#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=193, y=101, z=102
readp-3:msg:18 >>C 213#012<<>>C 213#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=213, y=101, z=102
readp-1:msg:19 >>C 213#012<<>>C 213#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=213, y=101, z=102
readp-2:msg:19 >>C 233#012<<>>C 233#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=213, y=101, z=102
readp-3:msg:19 >>C 233#012<<>>C 233#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=233, y=101, z=102
readp-1:msg:20 >>C 233#012<<>>C 233#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=233, y=101, z=102
readp-2:msg:20 >>C 246#012<<>>C 246#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=233, y=101, z=102
readp-3:msg:20 >>C 246#012<<>>C 246#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=246, y=101, z=102
readp-1:msg:21 >>C 246#012<<>>C 246#012<< pBuf=0xbe885df4, pScan=0xbe885df4, count=2, tag=C, x=246, y=101, z=102

The data alyays seems to be properly aligned with a 'C' at the start of the line. 数据分析似乎在行的开头与“ C”正确对齐。 If, in my script, I enable local terminal echo to the screen then I drop fewer lines. 如果在我的脚本中启用了本地终端echo到屏幕,那么我可以减少行数。 If I enable the sleep 0.00000000000001 I am able to read all of the data. 如果启用sleep 0.00000000000001可以读取所有数据。 I really need this to run a full speed and hate to slow things down with a sleep. 我真的需要它来全速运行,并且讨厌睡觉时放慢速度。 Am I simply over running a buffer and if so can the buffer size be increased? 我是否只是在运行缓冲区而已,如果可以,可以增加缓冲区的大小吗? I'm really stumped. 我真的很为难。 BTW, I'm using fgets rather than fscanf as I will eventually need to add in fastcgi and fsastcgi seems lacks support for fscanf (note in this test I am using the standard io libs, I am not linking in fastcgi and I am not including "fcgi/include/fcgi_stdio.h" in this test so there is no overwriting of the default libs). 顺便说一句,我使用的是fgets而不是fscanf,因为我最终将需要添加fastcgi,并且fsastcgi似乎缺乏对fscanf的支持(请注意,在此测试中,我使用的是标准io库,我没有在fastcgi中进行链接,并且不包括在此测试中为“ fcgi / include / fcgi_stdio.h”,因此不会覆盖默认库)。 Any direction to make this be reliable and efficient would be greatly appreciated. 任何使其可靠和有效的方向将不胜感激。

FIFOs are funny (peculiar) files. FIFO是有趣的(特殊的)文件。 A reading process blocks on open until there is a writer; 直到有作家为止,阅读过程一直处于开放状态。 a writing process blocks on open until there is a reader. 在没有读者之前,写作过程一直处于开放状态。 If there are no writers, the reader will get EOF; 如果没有作家,读者将获得EOF;如果没有作家,则读者将获得EOF。 at the point, it must close the FIFO and reopen it to allow more writers. 此时,它必须关闭FIFO并重新打开以允许更多写入器。 If there are no readers or writers, the content of the FIFO is discarded. 如果没有读取器或写入器,则FIFO的内容将被丢弃。 In your shell script, you are repeatedly opening and closing the FIFO. 在您的Shell脚本中,您反复打开和关闭FIFO。 You would do better to move the >> $myPipe onto the done line of the loop, so the FIFO is opened once, then all the messages written, and then the FIFO is closed. 您最好将>> $myPipe移动到循环的done行上,因此FIFO被打开一次,然后写入所有消息,然后关闭FIFO。

Your code is peculiar. 您的代码很特殊。 This line is problematic: 这行是有问题的:

while ((pScan = fgets(buf, PIPE_BUF, myStream)) == NULL){};

I see two problems. 我看到两个问题。 The less serious is that you have a null statement after the empty loop body. 较不严重的是,在空循环主体之后有一个空语句。 This doesn't do anything harmful except show experienced readers that you're not confident in your C code. 除了向有经验的读者表明您对C代码不自信之外,这没有任何害处。 The {} would be sufficient; {}就足够了; it is an empty loop body. 它是一个空循环的主体。 A semicolon on the next line in lieu of the {} would be conventional. 在下一行代替{}的分号是常规的。

The more serious problem is that if you ever enter the loop, you are going to stay in it indefinitely. 更严重的问题是,如果您进入循环,则将无限期地停留在循环中。 Once myStream reports EOF (by returning NULL from fgets() , it will continue to do so indefinitely (unless you're on Linux and the input device is actually a terminal — which is a separate sore point with me). 一旦myStream报告EOF(通过从fgets()返回NULL ,它将无限期地继续这样做(除非您在Linux上,并且输入设备实际上是一个终端-这是我的一个烦恼)。

It seems that the code in the question was hacked after it was asked and the freopen() line at the top of the loop was commented out, and this 'fixed' the problem. 似乎问题中的代码在被询问后被黑了,并且在循环顶部的freopen()行被注释掉了,这“解决了”问题。 This is explicable. 这是可以解释的。 When the FIFO was closed for reopening, the content was discarded. 当FIFO关闭以重新打开时,内容被丢弃。

Better code would probably look more like this. 更好的代码可能看起来像这样。 It passes the pipe name directly to the function (avoid global variables when you can). 它将管道名称直接传递给函数(如果可以,请避免使用全局变量)。 The function only returns if it fails to open the FIFO. 该函数仅在无法打开FIFO时返回。 There's no obvious need or benefit to the function returning NULL (written 0 — it's OK; I do that too), so it is now a void function. 返回NULL的函数没有明显的需要或好处(写为0没关系;我也这样做),因此它现在是一个void函数。 The function declaration should be in a header file and not written inline in the code. 函数声明应该在头文件中,而不是内联在代码中。

On the whole, I'd move most of the variables much closer to their point of first use — only messages would stay outside the infinite loop. 总的来说,我会将大多数变量都移到更接近它们的首次使用点的位置,只有messages会停留在无限循环之外。 There would be a header to declare the various functions 将有一个标头来声明各种功能

#include <syslog.h>
#include <stdio.h>

#define PIPE_BUF 1024

extern void reader(const char *pipeName);

void reader(const char *pipeName)
{
    int messages = 0;
    char buf[PIPE_BUF];
    int x = 100, y = 101, z = 102, count = 103;
    char linetag[PIPE_BUF];

    syslog(LOG_INFO, "Reader started\n");

    while (1)
    {
        FILE *myStream = fopen(pipeName, "r");
        if (myStream == NULL)
        {
            syslog(LOG_INFO, "Could not open pipe %s as input to Cota\n", pipeName);
            return;
        }
        while (fgets(buf, sizeof(buf), myStream) != 0)
        {
            count = sscanf(buf, "%s %d %d %d", linetag, &x, &y, &z);
            syslog(LOG_INFO, "readp-3:msg:%i >>%s<< count=%i, tag=%s, x=%d, y=%d, z=%d\n",
                   messages, buf, count, linetag, x, y, z);
            messages++;
        }
        fclose(myStream);
    }

    /* NOTREACHED */
    syslog(LOG_INFO, "Reader finished\n");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM