如何使用Linux内核API中的函数和宏改进以下代码,使其在类型安全性和字节顺序方面更加健壮?例如,在下面的示例中,src_data
是一个由两个16位有符号整数组成的数组(通常以小端顺序存储),并将通过UART以大端字节顺序发送出去。
s16 src_data[2] = {...}; /* note: this is signed data! */
u8 tx_data[4];
u8* src_data_u8 = (u8*)src_data;
tx_data[0] = src_data_u8[1];
tx_data[1] = src_data_u8[0];
tx_data[2] = src_data_u8[3];
tx_data[3] = src_data_u8[2];
我认为函数cpu_to_be16和cpu_to_be16p应该在执行此转换中发挥作用。尽管我不确定如何才能以一种安全可靠的方式使用它们。
发布于 2018-06-06 16:20:33
我相信以下是对我的问题的最好回答之一。我使用了@0andriy提供的指向内核源代码中现有示例的链接。
转换带符号的16位值以进行传输
s16 src = -5;
u8 dst[2];
__be16 tx_buf;
*(__be16*)dst = cpu_to_be16(src);
转换多个带符号的16位值以进行传输
s16 src[2] = {-5,-2};
u8 dst[4];
s16* psrc = src;
u8* pdst = dst;
int len = sizeof(src);
for ( ; len > 1; len -= 2) {
*(__be16 *)pdst = cpu_to_be16p(psrc++);
pdst += 2;
}
快速声明,我仍然需要检查此代码是否正确/可编译。
总体而言,我对复制和转换多个值的字节顺序的解决方案有点不满意,因为它很容易输入错误,并且可以很容易地实现到宏中。
发布于 2019-12-20 23:12:48
据我所知,两个16位的字,在转换成bigendian格式后,一个接一个地发送。我认为下面的应该是可以的。
s16 src_data[2] = {...}; /* note: this is signed data! */
s16 tx_data[2];
tx_data[0] = cpu_tp_be16(src_data_u8[0]);
tx_data[1] = cpu_to_be16(src_data_u8[1]);
s16 src_data[2] = {...}; /* note: this is signed data! */
s16 tx_data[2];
tx_data[0] = cpu_tp_be16(src_data_u8[0]);
tx_data[1] = cpu_to_be16(src_data_u8[1]);
发布于 2018-05-28 18:15:41
您的安全性问题似乎是htons(x)
函数/宏需要一个无符号整数,但您拥有一个有符号整数。不是问题:
union {
int16_t signed_repr;
uint16_t unsigned_repr;
} data;
data.signed_repr = ...;
u16 unsigned_big_endian_data = htons(data.unsigned_repr);
memcpy(tx_data, &unsigned_big_endian_data,
min(sizeof tx_data, sizeof unsigned_big_endian_data));
PS。通过联合的类型双关语是perfectly well-defined。
https://stackoverflow.com/questions/50563074
复制相似问题