繁体   English   中英

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

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

我正在尝试使用fgets从C程序(gcc -std = c99)中的命名管道中提取数据。 我在命令行上创建了管道,可以看到它存在于文件系统中,并且在使用“ ls -la”时已将其停在ap中,并且权限已设置为任何人都可以使用。

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

我使用一个简单的脚本将数据发送到管道:

#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

我的程序试图从该管道读取的循环是:

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++;
    }
}

当我如上所述运行脚本时,我的系统日志显示以下内容:

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

数据分析似乎在行的开头与“ C”正确对齐。 如果在我的脚本中启用了本地终端echo到屏幕,那么我可以减少行数。 如果启用sleep 0.00000000000001可以读取所有数据。 我真的需要它来全速运行,并且讨厌睡觉时放慢速度。 我是否只是在运行缓冲区而已,如果可以,可以增加缓冲区的大小吗? 我真的很为难。 顺便说一句,我使用的是fgets而不是fscanf,因为我最终将需要添加fastcgi,并且fsastcgi似乎缺乏对fscanf的支持(请注意,在此测试中,我使用的是标准io库,我没有在fastcgi中进行链接,并且不包括在此测试中为“ fcgi / include / fcgi_stdio.h”,因此不会覆盖默认库)。 任何使其可靠和有效的方向将不胜感激。

FIFO是有趣的(特殊的)文件。 直到有作家为止,阅读过程一直处于开放状态。 在没有读者之前,写作过程一直处于开放状态。 如果没有作家,读者将获得EOF;如果没有作家,则读者将获得EOF。 此时,它必须关闭FIFO并重新打开以允许更多写入器。 如果没有读取器或写入器,则FIFO的内容将被丢弃。 在您的Shell脚本中,您反复打开和关闭FIFO。 您最好将>> $myPipe移动到循环的done行上,因此FIFO被打开一次,然后写入所有消息,然后关闭FIFO。

您的代码很特殊。 这行是有问题的:

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

我看到两个问题。 较不严重的是,在空循环主体之后有一个空语句。 除了向有经验的读者表明您对C代码不自信之外,这没有任何害处。 {}就足够了; 它是一个空循环的主体。 在下一行代替{}的分号是常规的。

更严重的问题是,如果您进入循环,则将无限期地停留在循环中。 一旦myStream报告EOF(通过从fgets()返回NULL ,它将无限期地继续这样做(除非您在Linux上,并且输入设备实际上是一个终端-这是我的一个烦恼)。

似乎问题中的代码在被询问后被黑了,并且在循环顶部的freopen()行被注释掉了,这“解决了”问题。 这是可以解释的。 当FIFO关闭以重新打开时,内容被丢弃。

更好的代码可能看起来像这样。 它将管道名称直接传递给函数(如果可以,请避免使用全局变量)。 该函数仅在无法打开FIFO时返回。 返回NULL的函数没有明显的需要或好处(写为0没关系;我也这样做),因此它现在是一个void函数。 函数声明应该在头文件中,而不是内联在代码中。

总的来说,我会将大多数变量都移到更接近它们的首次使用点的位置,只有messages会停留在无限循环之外。 将有一个标头来声明各种功能

#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