posix C write() 和线程安全

发布于 2024-10-09 22:43:10 字数 125 浏览 0 评论 0原文

有一种方法可以序列化 C write() ,以便我可以在套接字上写入字节,在 k 线程之间共享,而不会丢失数据?我想这个问题的解决方案包括用户空间锁定,那么可扩展性又如何呢?先感谢您。

There is a way to serialize the C write() so that I can write bytes on a socket, shared between k-threads, with no data-loss? I imagine that a solution to this problem includes user-space locking, and what about scalability? Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

段念尘 2024-10-16 22:43:10

我认为正确的答案取决于您的线程是否需要同步等待响应。如果他们只需要向套接字写入一些消息而不等待对等方响应,我认为最好的答案是有一个线程专门用于从其他线程放置消息的队列中写入消息。这样,工作线程可以简单地将它们的消息放入队列中并继续执行其他操作。

当然,队列必须受到互斥体的保护,但任何一个线程只需在操作队列时保持锁定(保证相当短的时间)。更明显的替代方案是让每个线程直接写入套接字,要求每个线程在完成写入操作时保持锁定。这总是比仅仅将一个项目添加到队列中要长得多,因为 write 是一个系统调用,并且可能会阻塞很长一段时间。

即使您的线程需要对其消息进行响应,执行类似的操作仍然可能是值得的。您的套接字服务线程变得更加复杂,因为您必须执行类似 select() 的操作 在套接字上进行读取和写入以阻止其阻塞,您还需要一种将消息与响应相匹配的方法,以及一种在线程响应到达时通知线程的方法。

I think the right answer depends on whether your threads need to synchronously wait for a response or not. If they just need to write some message to a socket and not wait for the peer to respond, I think the best answer is to have a single thread that is dedicated to writing messages from a queue that the other threads place messages on. That way, the worker threads can simply place their messages on the queue and get on with doing something else.

Of course, the queue has to be protected by a mutex but any one thread only has to hold the lock for as long as it is manipulating the queue (guaranteed to be quite a short time). The more obvious alternative of letting every thread write directly to the socket requires each thread to hold the lock for as long as it takes the write operation to complete. This will always be much longer than just adding an item to a queue since write is a system call and potentially, it could block for a long period.

Even if your threads need a response to their messages, it may still pay to do something similar. Your socket servicing thread becomes more complex because you'll have to do something like select() on the socket for reads and writes to stop it from blocking and you'll also need a way to match up messages to responses and a way to inform the threads when their responses have arrived.

腻橙味 2024-10-16 22:43:10

由于 POSIX 似乎没有指定 send(2) 的原子性保证,因此您可能必须使用互斥体。当然,这种序列化会导致可扩展性下降。

Since POSIX does not seem to specify atomicity guarantees on send(2), you will likely have to use a mutex. Scalability of course goes down the drain with this sort of serialization.

遥远的绿洲 2024-10-16 22:43:10

一种可能的方法是使用锁定机制。每个线程在向套接字写入任何内容之前都应该等待锁,并且一旦完成就应该释放锁。
如果您的所有线程都发送完全相同类型的消息,则接收端在读取数据时不会有任何问题,但如果不同的线程可以发送具有可能不同信息的不同类型的数据,则您应该有一个关联的唯一消息ID对于每种数据,最好也发送线程 ID(虽然不是必需的,但可能会帮助您调试小问题)。

您可以采用如下结构:

typedef struct my_socket_data_st
{
int msg_id;
#ifdef __debug_build__
    int thread_id;
#endif
size_t data_size_in_bytes;
.... Followed by your data ....
} my_socket_data_t

可扩展性取决于很多因素,包括运行应用程序的硬件资源。由于它是一个网络应用程序,因此您还必须考虑网络带宽。虽然操作系统对通过套接字发送/接收数据没有限制(有一些,但我认为您现在可以在您的应用程序中忽略它们),但您必须考虑进行 send 根据您的要求同步或异步。另外,由于您正在获取锁,因此您还必须考虑锁拥塞问题。如果其他线程无法轻松使用该锁,则会极大地降低性能。

One possible approach would be to use the locking mechanism. Every thread should wait for a lock before writing any thing on the socket and should release the lock, once it is done.
If all of your threads are sending exactly the same kind of messages, the receiver end would not have any problem in reading the data, but if different threads can send different kind of data with possible different info, you should have an unique message id associated with each kind of data and its better to send the thread id as well (although not necessary, but might help you in debugging small issues).

You can have a structure like:

typedef struct my_socket_data_st
{
int msg_id;
#ifdef __debug_build__
    int thread_id;
#endif
size_t data_size_in_bytes;
.... Followed by your data ....
} my_socket_data_t

Scalability depends on a lot things including the hardware resources on which your application would be running. Since it is a network application, you will have to think about the network bandwidth as well. Although there is no (there are a few, but I think you can ignore them for now for your application) limitation from OS on sending/receiving data over a socket, but you will have to consider about making the send synchronous or asynchronous based on your requirement. Also since, you are taking a lock, you will have to think about lock congestion as well. If the lock is not available easily for other threads, that will degrade the performance by a huge factor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文