c - 读取某些内容后立即返回 ReadFile()
问题描述
我想在 Linux 和 Windows 上以一致的方式从串口读取数据。我注意到了这一点,read()
并且ReadFile()
表现得有些不同。考虑以下代码:
// on Linux
int r = read(fd, buf, 256);
// on Windows
ReadFile(handle, buf, 256, &r, NULL);
这两个函数都将永远阻塞,直到数据到达。到目前为止,一切都很好。但是,有一点区别:read()
至少 1 个字节到达时将返回,而ReadFile()
在所有 256 个字节到达之前不会返回。
因此,我想问:有没有办法让ReadFile()
行为像read()
在 Linux 上一样,即即使请求了 256,只要至少有 1 个字节就返回?
解决方案
IMO 最好的方法是实现循环缓冲区,使用您喜欢的函数从缓冲区中的流位置读取 1 个字节,然后调用接收回调函数 - 或者只是轮询循环缓冲区以获取数据存在。
它解决了您的所有问题 - 当数据到达并且不会覆盖缓冲区时,您将收到通知(或者您可以轮询存在的数据)(当然您需要读取数据,否则如果缓冲区已满,您将忽略新数据)
这里有一个非常简单的实现
unsigned char buff[128];
struct
{
unsigned head:8;
unsigned tail:8;
}control = {.head = 0, .tail = 0};
int isFull(void)
{
return (control.head + 1) == control.tail;
}
int isEmpty()
{
return control.head == control.tail;
}
int push(int ch)
{
if(!isFull())
{
buff[control.head++] = ch;
return 0;
}
return -1;
}
int pop(void)
{
if(!isEmpty())
{
return buff[control.tail++];
}
return -1;
}
并且使用简单
void (*rcvcallback)(void);
initReceive(void (*callback)(void))
{
rcvcallback = callback;
}
void receive(void)
{
int r = 0;
#ifdef LINUX
read(fd, &r, 1);
#endif
#ifdef WINDOWS
size_t size;
ReadFile(handle, &r, 1, &size, NULL);
#endif
push(r);
rcvcallback();
}
#ifdef WINDOWS
#define EL "\n\r"
#endif
#ifdef LINUX
#define EL "\n"
#endif
void myRCVcallback(void)
{
printf("Byte received: %d"EL, pop());
}
int main()
{
printf("Starting ......"EL);
while(1)
{
receive();
}
return 0;
}
推荐阅读
- security - 如果我想将我的服务帐户凭据存储到 GCP 的秘密管理器中以供我的应用程序使用怎么办
- html - 不能强制我的浮动 div 始终使用 CSS 在容器内居中(是的,我删除了浮动:左)
- exception - RestSharp - 在部署的应用程序中执行 API 时出现 System.Net.WebException
- java - 运行应用程序时出现 Guice / Play Evolutions / H2 数据库错误
- c# - 例外:指定的演员表无效。v
- vhdl - VHDL - 满足条件时进程不分配位
- javascript - 使用 FormData 从视频上传 base64
- vega - Vega 中的多值工具提示
- javascript - ConnectableObservable - 为什么 Connect 在内部创建一个新订阅?
- reactjs - GoogleAnalytics 不使用 ReactGA 跟踪页面浏览量