作为线程调用的 C 函数 - Linux 用户层程序
我正在用 C 语言编写一个 Linux 守护进程,它通过 SPI 接口(ioctl)从 ADC 获取值。 SPI(spidev - 用户态)似乎有点不稳定,会随机冻结守护进程。
我需要更好地控制对获取值的函数的调用,我正在考虑将其作为一个线程,我可以等待它完成并获取返回值,如果超时则假设它冻结并杀死它没有这个新线程取消守护进程本身。然后我可以采取一些措施,例如在重新启动之前重置 ADC。这可能吗?
我想要实现的伪示例:
(function int get_adc_value(int adc_channel, float *value) )
- pid = thread( get_adc_value(1,&value); //使线程调用函数
- wait_until_finish (pid, timeout); //等待直到函数完成/超时
- if(timeout) Kill pid, 重新开始 //如果线程没有在给定时间内返回,则杀死它(它被冻结),
- 否则如果返回值正常,则继续 //如果成功,处理返回变量值并继续
感谢您对此事的任何输入,非常感谢示例!
I'm writing a linux daemon in C which gets values from an ADC by SPI interface (ioctl). The SPI (spidev - userland) seems to be a bit unstable and freezes the daemon at random times.
I need to have some better control of the calls to the functions getting the values, and I was thinking of making it as a thread which I could wait for to finish and get the return value and if it times out assume that it froze and kill it without this new thread taking down the daemon itself. Then I could apply measures like resetting the ADC before restarting. Is this possible?
Pseudo example of what I want to achieve:
(function int get_adc_value(int adc_channel, float *value) )
- pid = thread( get_adc_value(1,&value); //makes thread calling the function
- wait_until_finish(pid, timeout); //waits until function finishes/timesout
- if(timeout) kill pid, start over //if thread do not return in given time, kill it (it is frozen)
- else if return value sane, continue //if successful, handle return variable value and continue
Thanks for any input on the matter, examples highly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会尝试使用 pthreads 库。我已经在我的一些 C 项目中使用了它,并取得了很好的成功,它使您可以很好地控制运行的内容和时间。
可以在这里找到一个非常好的教程:
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
I would try looking at using the pthreads library. I have used it for some of my c projects with good success and it gives you pretty good control over what is running and when.
A pretty good tutorial can be found here:
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
在 glib 中,还有一种检查线程的方法,即使用 GCond(在 glib 帮助中查找它)。
在恢复过程中,您应该定期在子线程中设置 GCond,并使用 g_cond_timed_wait 在主线程中检查它。这与 glib 或 pthread 相同。
这是 pthread 的示例:
http://koders.com/c/fidA03D565734AE2AD9F5B42A FC740B9C17D75A33E3.aspx?s =%22pthread_cond_timedwait%22#L46
In glib there is too a way to check the threads, using GCond (look for it in the glib help).
In resume you should periodically set a GCond in the child thread and check it in the main thread with a g_cond_timed_wait. It's the same with the glib or the pthread.
Here is an example with the pthread:
http://koders.com/c/fidA03D565734AE2AD9F5B42AFC740B9C17D75A33E3.aspx?s=%22pthread_cond_timedwait%22#L46
我建议采用不同的方法。
编写一个程序来获取样本并将它们写入标准输出。它只需要在每个样本收集之前有
alarm(TIMEOUT);
,并且如果它挂起,程序将自动退出。编写另一个程序来运行第一个程序。如果退出,它将再次运行。它看起来像这样:
然后在您的其他程序中,使用 FILE*fp=popen("supervise_sampler","r"); 并从
fp
读取示例。更好的是:让程序简单地从 stdin 读取示例,并坚持用户像这样启动您的程序:像这样拆分任务可以更轻松地开发和测试,例如,您可以收集示例并将它们保存到文件中然后在该文件上运行您的程序:
然后,当您对程序进行更改时,您可以简单地一遍又一遍地在相同的数据上再次运行它。
启用数据记录也很简单 - 因此,如果您发现严重问题,可以再次通过程序运行所有数据以查找错误。
I'd recommend a different approach.
Write a program that takes samples and writes them to standard output. It simply need have
alarm(TIMEOUT);
before every sample collection, and should it hang the program will exit automatically.Write another program that runs that first program. If it exits, it runs it again. It looks something like this:
Then in your other program, use
FILE*fp=popen("supervise_sampler","r");
and read the samples fromfp
. Better still: Have the program simply read the samples from stdin and insist users start your program like this:Splitting up the task like this makes it easier to develop and easier to test, for example, you can collect samples and save them to a file and then run your program on that file:
Then, as you make changes to program, you can simply run it again on the same data over and over again.
It's also trivial to enable data logging- so should you find a serious issue you can run all your data through your program again to find the bugs.
当线程执行 ioctl() 时,会发生一些非常有趣的事情,它会进入一种非常特殊的睡眠状态,称为磁盘睡眠,在调用返回之前它不能被中断或终止。这是设计使然,可以防止内核从内到外腐烂。
如果您的守护进程卡在 ioctl() 中,可以想象它可能会永远保持这种状态(至少在 ADC 重置之前)。
我建议在已知有问题的接口上调用
ioctl()
之前删除一些内容,例如带有时间戳的文件。如果您的线程在 xx 秒内没有取消链接该文件,则需要通过其他方式重新启动 ADC。我也同意使用 pthreads,如果您需要示例代码,只需更新您的问题即可。
Something very interesting happens to a thread when it executes an ioctl(), it goes into a very special kind of sleep known as disk sleep where it can not be interrupted or killed until the call returns. This is by design and prevents the kernel from rotting from the inside out.
If your daemon is getting stuck in
ioctl()
, its conceivable that it may stay that way forever (at least till the ADC is re-set).I'd advise dropping something, like a file with a timestamp prior to calling
ioctl()
on a known buggy interface. If your thread does not unlink that file in xx amount of seconds, something else needs to re-start the ADC.I also agree with the use of pthreads, if you need example code, just update your question.