简体   繁体   English

C:如何让线程相互通信?

[英]C: How to make threads communicate with each other?

Interesting that this seems to be a basic question, and yet I couldn't find any example of it for the C language (in SO, I found only for Python, C# and C++).有趣的是,这似乎是一个基本问题,但我找不到 C 语言的任何示例(在 SO 中,我只找到了 Python、C# 和 C++)。

The point is: as a Qt programmer, when I need to make some data to be transmitted between different threads, I start a signal-slot connection between then and use the emit signal mechanism to do the work.重点是:作为一个Qt程序员,当我需要做一些数据在不同线程之间传输时,我会在then之间启动一个信号槽连接,并使用emit signal机制来完成这项工作。

But now I'm working in a C application for Embedded Linux where I need to do a similar work, but I don't have Qt's mechanism available.但是现在我正在为嵌入式 Linux 开发一个 C 应用程序,我需要在其中做类似的工作,但是我没有可用的 Qt 机制。 The question is: how can I make two or more threads communicate with each other in C in a manner similar to that of Qt with signals and slots?问题是:如何让两个或多个线程在 C中以类似于 Qt 的信号和插槽的方式相互通信

I know that one of the ways to share data is with global variables with changes protected by mutexes.我知道共享数据的一种方法是使用受互斥锁保护的全局变量。 But even then I would probably be unable to do the system in a asynchronous way: I would have to have a loop that would constantly check if the variable has changed or not.但即便如此,我也可能无法以异步方式执行系统:我必须有一个循环来不断检查变量是否已更改。 But what if I want to execute a specific method of a thread just after another one finished some work (so, in an asynchronous way)?但是如果我想在另一个线程完成一些工作之后执行一个线程的特定方法(所以,以异步方式)怎么办? Then it seems such way fails.那么似乎这样的方式失败了。

Note: although I'm using Embedded Linux and, therefore, mentioning some options that would take POSIX functions and other "Linux-related ways" would be helpful, it would still be better for the community if more time is given to solutions that are not based strictly to one specific platform (if that is possible).注意:虽然我使用的是嵌入式 Linux,因此,提及一些采用 POSIX 函数的选项和其他“与 Linux 相关的方式”会有所帮助,但如果有更多时间用于解决方案并非严格基于某一特定平台(如果可能)。

Read a good tutorial on pthreads .阅读有关 pthreads的好教程 You want to know more about condition variables to be used with mutexes .您想了解更多有关与互斥体一起使用的条件变量的信息

Condition variables and mutexes should probably be enough for your needs.条件变量和互斥体应该足以满足您的需要。

You could also use most traditional inter-process communication mechanisms between threads, eg a pipe(7) (probably with poll(2) ...).您还可以在线程之间使用大多数传统的进程间通信机制,例如pipe(7) (可能使用poll(2) ...)。 So read Advanced Linux Programming and study syscalls(2) and pthreads(7)所以阅读Advanced Linux Programming并学习syscalls(2)pthreads(7)

Avoid using signal(7) -s between threads and be aware of signal-safety(7) .避免在线程之间使用signal(7) -s 并注意signal-safety(7) See however signalfd(2) , eventfd(2) , userfaultfd(2) (you might cleverly handle SIGSEGV with it) and take inspiration from the approach suggested by Calling Qt functions from Unix signal handler .但是请参阅signalfd(2)eventfd(2)userfaultfd(2) (您可能会巧妙地用它处理SIGSEGV )并从Calling Qt functions from Unix signal handler 所建议的方法中获得灵感。

Observe a running multi-threaded Linux process with strace(1) , ltrace(1) , gdb(1) .使用strace(1)ltrace(1)gdb(1)观察正在运行的多线程 Linux进程 You'll understand that several pthreads(7) primitives are using futex(7) .您将了解几个pthreads(7)原语正在使用futex(7)

Both GNU glibc and musl-libc are open source and implement the pthreads specification (and Glib , GTK , Qt or POCO are built above them). GNU glibcmusl-libc都是开源的并实现了 pthreads 规范(并且GlibGTKQtPOCO构建在它们之上)。 I invite you to study their source code.我邀请你研究他们的源代码。

One way is to use message passing between threads via asynchronous queues.一种方法是通过异步队列在线程之间使用消息传递。 This way you can avoid using shared data between threads and only the queues need to be thread-safe.这样您就可以避免在线程之间使用共享数据,并且只有队列需要是线程安全的。

Asynchronous queues can be implemented using different synchronisation primitives:异步队列可以使用不同的同步原语来实现:

  • Pipes or sockets.管道或插座。
  • Queues protected with a mutex and a condition variable.使用互斥锁和条件变量保护的队列。
  • Non-blocking or lock-free queues.非阻塞或无锁队列。

Thread which you want to notify of an event like "data available" can register a callback function which can be trigerred by the notifier thread.您想要通知诸如“可用数据”之类的事件的线程可以注册一个回调函数,该函数可以由通知线程触发。 You can use a function pointer for this.您可以为此使用函数指针。

Ex: Thread 2 registers a callback function for one or more events.例如:线程 2 为一个或多个事件注册一个回调函数。 Thread 1 on occurrence of the condition or event calls the registered function.线程 1 在条件或事件发生时调用注册的函数。

producer and consumer threads should capture each other's tid.生产者和消费者线程应该捕获彼此的 tid。 producer on producing can send: pthread_kill(consumerID, SIGUSR1);生产者可以发送: pthread_kill(consumerID, SIGUSR1); consumer is setup with the signal handler for SIGUSR1, and can retrieve the produced result from the common std::queue saved by pthread_setspecific().消费者使用 SIGUSR1 的信号处理程序设置,并且可以从 pthread_setspecific() 保存的公共 std::queue 中检索生成的结果。 producer and consumer can continue their tasks without being locked by semaphore or cond var/mutex.生产者和消费者可以继续他们的任务,而不会被信号量或 cond var/mutex 锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM