多线程C程序设计帮助
我在多线程方面没有太多经验,我正在编写 ac 程序,我相信它适合在两个线程中运行。该程序将侦听串行端口上的数据,在新数据可用时读取并处理新数据,并通过第三方将最新处理的数据发布到其他(不相关)模块 IPC api(它的名称很容易混淆 IPC)(在请求时)。
为了通过IPC接收发布数据的请求,程序必须调用IPC_listenwait(wait_time);。然后,如果在“监听等待”时收到发布请求,则会调用处理程序来发布最新数据。
一种选择是在一个线程中执行此操作,如下所示:
for(;;) {
read_serial(inputBuffer);
process_data(inputBuffer, processedData); //Process and store
IPC_listenwait(wait_time); //If a request to publish is received during this,
} //then a handler will be invoked and the newest piece of
//processedData will be published to other modules
publishRequestHandler() { //Invoked when a message is received during IPC_listenwait
IPC_publish(newest(processedData));
}
这可行,但对于应用程序来说,程序对发布新数据的请求非常敏感,并且发布的数据是最新的可用数据,这一点很重要。这些目标并不满足上述目标,因为数据可能在进程开始监听等待之后且在接收到发布消息的请求之前到达。或者,当传入发布消息的请求时,进程可能正在读取/处理,但在下一次 IPC_listenwait 调用之前无法为其提供服务。
我能想到的唯一设计是有一个线程可以读取,它只会执行以下操作:
readThread() {
for(;;) { //pseudocode
select();
read(inputBuffer);
process(inputBuffer, processedData);
}
}
并且让主线程仅侦听传入消息:
mainThread() {
IPC_listenwait(forever);
}
publishRequestHandler() { //Invoked when a message is received during IPC_listenwait
IPC_publish(newest(processedData));
}
这是您会使用的设计吗?如果是这样,我在访问或写入processedData时是否需要使用信号量?
这会给我带来良好的响应能力吗?
谢谢
I don't have much experience with multithreading and I'm writing a c program which I believe is suited to running in two threads. The program will listen on the serial port for data, read and process new data when it's available, and publish the newest processed data to other (irrelevant) modules via a third party IPC api (it's confusingly named IPC) when requested.
In order to receive the request to publish data via IPC, the program must call IPC_listenwait(wait_time);. Then if a request to publish is received while "listenwaiting" a handler is invoked to publish the newest data.
One option is to do this in one thread like:
for(;;) {
read_serial(inputBuffer);
process_data(inputBuffer, processedData); //Process and store
IPC_listenwait(wait_time); //If a request to publish is received during this,
} //then a handler will be invoked and the newest piece of
//processedData will be published to other modules
publishRequestHandler() { //Invoked when a message is received during IPC_listenwait
IPC_publish(newest(processedData));
}
And this works, but for the application it is important that the program is very responsive to the request to publish new data, and that the data published is the newest available. These goals are not satisfied with the above because data may arrive after the process begins listenwaiting and before a request to publish message is received. Or the process may be reading/processing when a request to publish message is incoming, but won't be able to service it until the next IPC_listenwait call.
The only design I can think of is to have one thread to read, which will just do something like:
readThread() {
for(;;) { //pseudocode
select();
read(inputBuffer);
process(inputBuffer, processedData);
}
}
And have the main thread just listening for incoming messages:
mainThread() {
IPC_listenwait(forever);
}
publishRequestHandler() { //Invoked when a message is received during IPC_listenwait
IPC_publish(newest(processedData));
}
Is this the design you would use? If so, will I need to use a semaphore when accessing or writing processedData?
Will this give me good responsiveness?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你基本上走在正确的轨道上。
您必须注意的一件事是对可发布数据的并发访问,因为您不希望一个线程在另一个线程尝试读取它时破坏它。为了防止这种情况,请使用一对缓冲区和一个受互斥锁保护的指针,指向被认为是当前的缓冲区。当 process_data() 准备就绪时,它应该将其结果转储到非当前缓冲区中,锁定指针互斥锁,将指针重新指向包含新数据的缓冲区,然后释放互斥锁。类似地,发布者应该在读取当前数据时锁定指针互斥锁,这将迫使任何可能想要破坏它的东西等待。这比使用单个受互斥锁保护的缓冲区要复杂一些,但可以确保在准备新数据时始终有最新的内容可以发布。
如果您的处理步骤花费的时间足够长,以至于您可以读取多组数据,那么您可以将读取/处理线程分成两个,并让读者确保处理器只获取最新和最好的数据,这样您就不会结束处理你永远不会发布的东西。
顺便说一句,第一个问题非常好。投个赞成票吧
You're mostly on the right track.
The one thing you have to watch out for is concurrent access to the publishable data, because you don't want one thread clobbering it while another is trying to read it. To prevent that, use a pair of buffers and a mutex-protected pointer to whichever one is considered current. When
process_data()
has something ready, it should dump its results in the non-current buffer, lock the pointer mutex, repoint the pointer to the buffer containing the new data and then release the mutex. Similarly, the publisher should lock the pointer mutex while it reads the current data, which will force anything that might want to clobber it to wait. This is a bit more complex than having a single, mutex-protected buffer but will assure that you always have something current to publish while new data is being prepared.If your processing step takes long enough that you could get multiple sets of data to read, you might split the read/process thread into two and let the reader make sure the processor only ever gets the latest and greatest so you don't end up processing stuff you won't ever publish.
Excellent first question, by the way. Have an upvote.