简体   繁体   English

在C中同时修改链表

[英]Concurrent modification of linked list in C

I've wrote a C application to stress test a DNS server(running on VM), I'm trying to get maximum DNS request rate(throughput) to see how it will behave. 我已经编写了一个C应用程序来对DNS服务器(在VM上运行)进行压力测试,我试图获得最大的DNS请求速率(吞吐量)以查看其行为。
My application runs two threads, sending thread which generates DNS requests(with different query names) and sends them on socket to the server and a receiving thread which receives the DNS responses on the same socket and calculates response time. 我的应用程序运行两个线程,一个发送线程生成DNS请求(具有不同的查询名称),然后将它们通过套接字发送到服务器;另一个接收线程,它在同一套接字上接收DNS响应并计算响应时间。

Now here comes the use of concurrent linked list(I've implemented), sending thread appends query name and send time(to the end of the list) for each sent request. 现在,这里使用并发链接列表(我已经实现),发送线程为每个发送的请求附加查询名称和发送时间(到列表末尾)。 The receiving thread runs each time from the start, looks for the query name with the relevant send time, calculates response time and removes the object from the list, also every object it traverses it checks whether the send time is within the DNS timeout window I set and if it is not I treat this request as unanswered and remove it from the list. 接收线程每次都从头开始运行,查找具有相关发送时间的查询名称,计算响应时间并从列表中删除对象,它遍历的每个对象还会检查发送时间是否在DNS超时窗口内设置,如果不是,则将该请求视为未答复,然后将其从列表中删除。

Now the problem is that I have to lock each time the whole traversing of the list in receiving thread which contains nodes removal as well, it impacts heavily the sending thread which stops sending, waiting a lot of time on the lock to append. 现在的问题是,每次在接收线程中也要删除节点时,列表的整个遍历都必须锁定,这严重影响了发送线程,该线程停止发送,在锁上等待了很多时间才能追加。

Is there a different way you would suggest to implement the locking in my case? 您是否建议以其他方式实施锁定? Or maybe is there something more major I can change? 也许还有其他我可以改变的重大事情?

PS: I've tried to use unix dig in a script and implement the same in python scapy but couldn't reach the rates I'm reaching in C app(sending without locking was up to 10 Mbit), this is why I chose to implement this in C. PS:我试图在脚本中使用unix dig并在python scapy中实现相同的功能,但无法达到我在C应用程序中达到的速率(不锁定发送最高可达10 Mbit),这就是为什么我选择了用C实现

Thank you! 谢谢!

You probably don't need to lock the whole list while the receiving thread scans it. 你也许并不需要,而接收线程扫描它来锁定整个列表。 The sending thread will only ever modify the current last node (to append a new node), and it does not need to examine any other node as long as it maintains a pointer to the current tail. 发送线程只会修改当前的最后一个节点(以追加一个新节点),并且只要保持指向当前尾部的指针,就不需要检查任何其他节点。 For its part, the receiving thread can then remove any node other than the current tail without any impact on the sending thread. 就其本身而言,接收线程然后可以删除除当前尾部以外的任何节点,而不会对发送线程造成任何影响。 Therefore only the tail node needs to be locked. 因此,仅尾节点需要被锁定。

It may be a bit trickier to maintain a moving lock on the current tail, because you need to know which node that is, but I don't think it would be too hard. 在当前尾巴上保持移动锁定可能有点棘手,因为您需要知道是哪个节点,但是我认为这不会太难。 For instance, you might provide a shared atomic pointer to the tail, which the sender updates before sending each request and the receiver reads upon receiving a response. 例如,您可以提供一个指向尾部的共享原子指针,发送方在发送每个请求之前都会更新尾部,接收方在收到响应后会进行读取。 The receiver does not need to consider any subsequent requests (for they had not yet been sent when the current response was received). 接收者不需要考虑任何后续请求(因为在收到当前响应时尚未发送这些请求)。

The receiver may occasionally need to wait for the sender to append at least one request, so that the erstwhile tail can be removed, but I would expect that to be rare. 接收者有时可能需要等待发送者追加至少一个请求,以便可以删除以前的尾巴,但是我希望这种情况很少见。 Otherwise, I don't see how your list can now be getting so long that holding the whole thing locked while scanning it is too time-consuming. 否则,我看不到您的列表现在怎么会这么长,以至于在扫描过程中将整个过程锁定都太耗时。

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

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