简体   繁体   English

写入字节流的最有效方法

[英]Most efficient way of writing byte array for streaming

I need to create a byte array that is needed to be stream to another device through UART. 我需要创建一个字节数组,该字节数组需要通过UART流到另一个设备。 There are some fixed parameters that I can fill in before hand but variables such as string is dynamically sized. 我可以事先填写一些固定的参数,但是诸如字符串之类的变量是动态调整大小的。 Right up till now, I've been doing: 到目前为止,我一直在做:

unsigned char buffer[255];
unsigned char wr_head = 0;
buffer[wr_head++] = 0x01; // and so on
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;

I've experimented with other methods like std::string and std::vector but I felt that there is much manageable way of writing byte array for streams. 我已经尝试过其他方法,例如std::stringstd::vector但是我觉得为流编写字节数组有很多可管理的方法。 Suggestions? 建议?

edit : Please advice on performance as well because is threaded. 编辑 :也请性能建议,因为是线程。

edit2 : Sorry for lacking of details the first time around. edit2 :抱歉第一次缺少细节。 The device is indeed an embedded device. 该设备确实是嵌入式设备。 Though some suggested some solution, its not really what I want. 尽管有人提出了一些解决方案,但这并不是我真正想要的。 Maybe a snippet of my current implementation will clear some confusion: 也许我目前的实现的一小段代码会清除一些困惑:

unsigned char buffer[255];
unsigned char wr_head = 0;

buffer[wr_head++] = 0x01; // Set message type
buffer[wr_head++] = 0x30; // message length
memcpy(&buffer[wr_head], &some_chararray, sizeof(some_chararray));
wr_head += some_chararray;
buffer[wr_head++] = CalChecksum;
UartSend(&buffer, wr_head); // Send array to stream out from UART

The configuration and setting value is known before hand, provided by the device documentation. 该配置和设置值是设备文档提供的事先已知的信息。 This question is related to what I've asked in here 这个问题与我在这里提出的问题有关

Thanks for the effort so far. 感谢您到目前为止的努力。

A ring buffer is a typical solution for problems like these. 环形缓冲区是解决此类问题的典型解决方案。

I have no idea what kind of device you're on, but I'll just suppose that you're writing for some kind of embedded device. 我不知道您使用的是哪种设备,但我只是假设您正在为某种嵌入式设备编写程序。 Let's assume that there's some interrupt moving data from the ring buffer to the UART. 假设有一些中断将数据从环形缓冲区移至UART。 This interrupt will call getc , other code will call putc and puts . 此中断将调用getc ,其他代码将调用putcputs

class RingBuffer {
private:
    static unsigned BUFSZ = 256;
    volatile unsigned char buf[BUFSZ];
    volatile unsigned char read, write;

public:
    RingBuffer() : read(0), write(0) { }

    // Blocks until space is available
    void putc(unsigned int c) {
        while (((write - read) & (BUFSZ - 1)) == 1)
            sleep();
        buf[write++ & (BUFSZ - 1)] = c;
    }

    // Returns -1 if empty
    int getc() {
        if (read == write)
            return -1;
        return buf[read++ & (BUFSZ - 1)];
    }

    // There are faster ways to write this.
    void puts(char *str) {
        for (; *str; ++str)
            putc(*str);
    }
};

Typically, you don't want to make the buffer dynamically grow for something like this. 通常,您不希望使缓冲区像这样动态增长。 There's lots of room for improvement in the above code, and there are also libraries available for this kind of thing. 上面的代码有很多改进的余地,并且还有一些可用于此类事情的库。

This particular implementation also never lets you fill the buffer completely, but the code is simpler as a result. 这种特定的实现方式也永远不会让您完全填充缓冲区,但是结果是代码更简单。 I probably wouldn't put this code in production, but hopefully it's a step in the right direction. 我可能不会将此代码投入生产,但希望这是朝正确方向迈出的一步。

If UartSend is a blocking function then you can do just this: 如果UartSend是阻止函数,则可以执行以下操作:

void UartSend(byte b) { UartSend(&b, 1); } // sends one byte

UartSend(0x01); // Set message type
UartSend(0x30); // message length
UartSend(some_chararray,sizeof(some_chararray));

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

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