FIFOs implementation

前端 未结 5 1164
悲哀的现实
悲哀的现实 2020-12-17 04:35

Consider the following code:

writer.c

mkfifo(\"/tmp/myfifo\", 0660);

int fd = open(\"/tmp/myfifo\", O_WRONLY);

char *foo, *bar;

...

write(fd, foo         


        
5条回答
  •  -上瘾入骨i
    2020-12-17 05:08

    Many of the other answers mention using some sort of protocol for your data and I believe this is the correct approach. This protocol can be as simple or complex as necessary. I have provided a couple of examples that you may find useful1.


    In a simple case, you may only have a length byte followed by the data byte(s) (i.e. C string).

    +--------------+
    | length byte  |
    +--------------+
    | data byte(s) |
    +--------------+

    Writer:

    uint8_t foo[UCHAR_MAX+1];
    uint8_t len;
    int fd;
    
    mkfifo("/tmp/myfifo", 0660);
    fd = open("/tmp/myfifo", O_WRONLY);
    
    memset(foo, UCHAR_MAX+1, 0);
    len = (uint8_t)snprintf((char *)foo, UCHAR_MAX, "Hello World!");
    
    /* The length byte is written first followed by the data. */
    write(fd, len, 1);
    write(fd, foo, strlen(foo));
    

    Reader:

    uint8_t buf[UCHAR_MAX+1];
    uint8_t len;
    int fd;
    
    fd = open("/tmp/myfifo", O_RDONLY);
    
    memset(buf, UCHAR_MAX+1, 0);
    
    /* The length byte is read first followed by a read 
     * for the specified number of data bytes.
     */
    read(fd, len, 1);
    read(fd, buf, len);
    

    In a more complex case, you may have a length byte followed by data bytes containing more than a simple C string.

    +----------------+
    |  length byte   |
    +----------------+
    | data type byte |
    +----------------+
    |  data byte(s)  |
    +----------------+

    Common Header:

    #define FOO_TYPE 100
    #define BAR_TYPE 200
    
    typedef struct {
        uint8_t type;
        uint32_t flags;
        int8_t msg[20];
    } __attribute__((aligned, packed)) foo_t;
    
    typedef struct {
        uint8_t type;
        uint16_t flags;
        int32_t value;
    } __attribute__((aligned, packed)) bar_t;
    

    Writer:

    foo_t foo;
    unsigned char len;
    int fd;
    
    mkfifo("/tmp/myfifo", 0660);
    fd = open("/tmp/myfifo", O_WRONLY);
    
    memset(&foo, sizeof(foo), 0);
    foo.type = FOO_TYPE;
    foo.flags = 0xDEADBEEF;
    snprintf(foo.msg, 20-1, "Hello World!");
    
    /* The length byte is written first followed by the data. */
    len = sizeof(foo);
    write(fd, len, 1);
    write(fd, foo, sizeof(foo));
    

    Reader:

    uint8_t buf[UCHAR_MAX+1];
    uint8_t len;
    uint16_t type;
    union data {
        foo_t * foo;
        bar_t * bar;
    }
    int fd;
    
    fd = open("/tmp/myfifo", O_RDONLY);
    
    memset(buf, UCHAR_MAX+1, 0);
    
    /* The length byte is read first followed by a read 
     * for the specified number of data bytes.
     */
    read(fd, len, 1);
    read(fd, buf, len);
    
    /* Retrieve the message type from the beginning of the buffer. */
    memcpy(&type, buf, sizeof(type));
    
    /* Process the data depending on the type. */
    switch(type) {
        case FOO_TYPE:
            data.foo = (foo_t)buf;
            printf("0x%08X: %s\n", data.foo.flags, data.foo.msg); 
            break;
        case BAR_TYPE:
            data.bar = (bar_t)buf;
            printf("0x%04X: %d\n", data.bar.flags, data.bar.value); 
            break;
        default:
            printf("unrecognized type\n");
    }
    

    1 - This code was written from memory and is untested.

提交回复
热议问题