如何在不使用线程的情况下在c
中实现非阻塞库API?
简而言之,我有一个我写的库,它通过串行控制器发出一些读/写调用,以便获取库的客户端所需的数据。这些通过专有驱动程序对串行设备的调用是阻塞的,我无法更改它们。
没有在我的库中使用线程,或编写系统服务与我的库共存,有没有办法“包装”我的库API调用,因此它们是非阻塞的(即像python中的协同例程)?期望的最终结果是一个简单的,同步的,非阻塞的API调用,用于查询库的状态,并且涉及的等待时间最短。
谢谢。
简答:不。
您无法更改延迟,因为它是所请求操作固有的(发送数据需要一定的时间),因此您无法缩短呼叫时间。
因此,您可以选择等待呼叫完成或不等待呼叫。
你不能在没有某种线程的情况下等待它,因为这就是处理器一次性暴露它的抽象(即在串口上发送数据并继续使用更多代码)...因此你将需要线程为达到这个。
我认为首先你应该改变你的lib以使所有的呼叫都是非阻塞的。这是很好的解释qazxsw poi
在C语言中python的共同例程最接近的技术是Linux Blocking vs. non Blocking Serial Read。它实现了简单的协作式多任务处理而不使用线程
一般来说,使用线程可能更好。但是,有一种方法可以解决简单应用程序的限制。
请原谅C ++ 11 lambda的使用,我认为这会让事情变得更加清晰。
Protothread
限制:
其他人可能会发现这个成语的其他问题。
我以为我已经在某个地方的namespace
{
sigjmp_buf context;
} // namespace
void nonBlockingCall(int timeoutInSeconds)
{
struct sigaction* oldAction = nullptr;
struct sigaction newAction;
if (sigsetjmp(::context,0) == 0)
{
// install a simple lambda as signal handler for the alarm that
// effectively makes the call time out.
// (e.g. if the call gets stuck inside something like poll() )
newAction.sa_handler = [] (int) {
siglongjmp(::context,1);
};
sigaction(SIGALRM,&newAction,oldAction);
alarm(timeoutInSeconds); //timeout by raising SIGALM
BLOCKING_LIBRARY_CALL
alarm(0); //cancel alarm
//call did not time out
}
else
{
// timer expired during your call (SIGALM was raised)
}
sigaction(SIGALRM,oldAction,nullptr);
}
中看到了这一点,事实上它在信号章节中讨论了它讨论使用alarm()来实现sleep()。