Linux 多进程同步数据文件交付,采用select | poll | other?

Linux 多进程同步数据文件交付,采用select | poll | other?,linux,select,file-io,unix,polling,Linux,Select,File Io,Unix,Polling,我有一个大的数据文件,它不断地被现场的测量设备同步地附加到数据文件中。我需要将此文件的最新数据同步传送到在线仪表板。我之所以说等时,是因为仪表板不关心显示数据流的高延迟情况,它只关心文件中发送给它的最后几个数据点。我不能保证文件增长率低于我的有效出站吞吐量 所以我有一个附加文件,但我有多个进程需要定期发送最后一块信息。我想这是一个随便的酒吧酒吧酒吧吧 我可以: 轮询文件以查看是否有增长,然后从EOF中查找最后的数据块, 选择style并收到所述更改的通知,但我不需要查找最后一位数据吗? 有一个进

我有一个大的数据文件,它不断地被现场的测量设备同步地附加到数据文件中。我需要将此文件的最新数据同步传送到在线仪表板。我之所以说等时,是因为仪表板不关心显示数据流的高延迟情况,它只关心文件中发送给它的最后几个数据点。我不能保证文件增长率低于我的有效出站吞吐量

所以我有一个附加文件,但我有多个进程需要定期发送最后一块信息。我想这是一个随便的酒吧酒吧酒吧吧

我可以:

轮询文件以查看是否有增长,然后从EOF中查找最后的数据块, 选择style并收到所述更改的通知,但我不需要查找最后一位数据吗? 有一个进程将最后一位数据推入共享内存进行读取,但我不会遇到在1和2中需要解决的相同问题,因为共享内存编写器的行为相同。
还有其他建议吗?

如果我理解正确,您只想让仪表板定期更新上一个当前块。那么,一个简单的选择就是:

睡眠,统计文件以查看是否已更改,如果合适,则发送数据。 在Linux上,您可以使用inotify在文件更改时收到通知。这样,您可以避免前一种方法不必要的唤醒。因此,这一选择将是:

等待通知,若通知到达stat,若文件已更改,则发送数据并休眠以避免过于频繁的更新。 最后一个可能看起来像:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <sys/inotify.h>


#define BLOCK_SIZE 5


static ssize_t read_fully(int fd, void *buf, size_t count)
{
    ssize_t ret;
    size_t nread;

    nread = 0;
    do {
            ret = read(fd, buf, count);
            if (ret > 0)
                    nread += ret;
    } while ((ret > 0 && nread < count) || (ret < 0 && errno == EINTR));

    return ret < 0 ? ret : (ssize_t) nread;
}

static void show_current_block(int fd)
{
    static off_t size = 0;  /* non-theadsafe, move fd and size to a
                               context struct passed as an argument
                               if you want thread-safety            */
    signed char block[BLOCK_SIZE];  /* Assume only ASCII-compatible encoding */
    struct stat st;
    ssize_t ret;

    if (fstat(fd, &st) < 0) {
            perror("fstat");
            exit(1);
    }

    /* Handle truncated file */
    if (st.st_size < size) {
            size = 0;
    }

    if (st.st_size >= size + BLOCK_SIZE) {
            size = st.st_size / BLOCK_SIZE * BLOCK_SIZE;

            if (lseek(fd, -BLOCK_SIZE, SEEK_END) < 0) {
                    perror("lseek");
                    exit(1);
            }

            ret = read_fully(fd, block, BLOCK_SIZE);

            if (ret < 0) {
                    perror("read");
                    exit(1);
            }

            if (ret == 0) {
                    fprintf(stderr, "file closed!");
                    exit(1);
            }

            /* Assume only ASCII-compatible encoding, don't print
             * neither C0 control chars, nor > 0x7f chars (including C1)
             */
            printf("Current block: %c%c%c%c%c\n",
                    block[0] < 20 ? '.' : block[0],
                    block[1] < 20 ? '.' : block[1],
                    block[2] < 20 ? '.' : block[2],
                    block[3] < 20 ? '.' : block[3],
                    block[4] < 20 ? '.' : block[4]);

            /* Don't update too often */
            usleep(3000 * 1000);
    }
}

int main(void)
{
    int fd, ifd, wd;
    struct inotify_event ev;
    ssize_t ret;

    fd = open("testfile", O_RDONLY);
    if (fd < 0) {
            perror("open");
            exit(1);
    }

    ifd = inotify_init();
    if (ifd < 0) {
            perror("inotify_init");
            exit(1);
    }

    /* XXX race between open and inotify_add_watch */
    wd = inotify_add_watch(ifd, "testfile", IN_MODIFY);
    if (wd < 0) {
            perror("inotify_add_watch");
            exit(1);
    }

    show_current_block(fd);

    while ((ret = read(ifd, &ev, sizeof(struct inotify_event)))) {
            if (ret < 0) {
                    perror("read inotify watch");
                    exit(1);
            }
            if (ret == 0) {
                    fprintf(stderr, "inotify watch closed!\n");
                    exit(1);
            }
            if (ret != sizeof(struct inotify_event)) {
                    fprintf(stderr, "bad inotify event size %d (expected %d)\n",
                            ret, sizeof(struct inotify_event));
                    exit(1);
            }

            show_current_block(fd);
    }

    return 0;
}

所以您不能修改生产者流程?因为显而易见的解决方案是只使用当前块创建另一个文件。生产者进程基本上是将逻辑数据包中的所有传入数据记录到单个文件中。实际上每周都有一个新的文件,但我离题了。该文件通过各种其他批处理程序定期使用和处理。有什么建议吗?选项3是获得适当的锁定,重写所有内存1块,释放锁定吗?当然,3可以被锁定/扫描,但它仍然需要使用者从文件中读取,生产者从shm中读取,是吗?是的,我想你的意思是使用shm而不是文件。谢谢。我一定会在这里尝试一下这种方法。