C中没有线程的非阻塞库API

问题描述 投票:2回答:3

如何在不使用线程的情况下在c中实现非阻塞库API?

简而言之,我有一个我写的库,它通过串行控制器发出一些读/写调用,以便获取库的客户端所需的数据。这些通过专有驱动程序对串行设备的调用是阻塞的,我无法更改它们。

没有在我的库中使用线程,或编写系统服务与我的库共存,有没有办法“包装”我的库API调用,因此它们是非阻塞的(即像python中的协同例程)?期望的最终结果是一个简单的,同步的,非阻塞的API调用,用于查询库的状态,并且涉及的等待时间最短。

谢谢。

c linux multithreading nonblocking synchronous
3个回答
4
投票

简答:不。

您无法更改延迟,因为它是所请求操作固有的(发送数据需要一定的时间),因此您无法缩短呼叫时间。

因此,您可以选择等待呼叫完成或不等待呼叫。

你不能在没有某种线程的情况下等待它,因为这就是处理器一次性暴露它的抽象(即在串口上发送数据并继续使用更多代码)...因此你将需要线程为达到这个。


1
投票

我认为首先你应该改变你的lib以使所有的呼叫都是非阻塞的。这是很好的解释qazxsw poi

在C语言中python的共同例程最接近的技术是Linux Blocking vs. non Blocking Serial Read。它实现了简单的协作式多任务处理而不使用线程


0
投票

一般来说,使用线程可能更好。但是,有一种方法可以解决简单应用程序的限制。

请原谅C ++ 11 lambda的使用,我认为这会让事情变得更加清晰。

Protothread

限制:

  • 这对于多线程代码来说是不安全的。如果您有多线程代码,最好将计时器放在监视线程中,然后终止被阻塞的线程。
  • 定时器和来自其他地方的信号可能会干扰
  • 除非BLOCKING_LIBRARY_CALL非常好地记录其行为,否则您可能处于未定义的行为状态。 如果中断,它将无法正常释放资源。 它可能会安装信号处理程序或掩码或自行提升信号。
  • 如果在C ++而不是C中使用这个习惯用法,则不得允许在setjmp和longjmp之间构造或销毁任何对象。

其他人可能会发现这个成语的其他问题。

我以为我已经在某个地方的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()。

© www.soinside.com 2019 - 2024. All rights reserved.