是否读取/recv线程安全(MSG_PEEK)

时间:2022-09-06 21:03:59

I have one thread that is doing a blocking read:

我有一个线程正在做块读:

rec = read(socket, data, size);

I'm curious to know whether it is safe or not for me to have another thread, doing recv(MSG_PEEK) in the background on the same socket:

我很想知道,在同一个插座的背景下,我是否可以有另一个线程,做recv(MSG_PEEK):

while (true)
{
   if (recv(socket, byte, size, MSG_DONTWAIT | MSG_PEEK) > 0)
   {
       printf("peeked %d", byte);
   }
   sleep(1);
}

1 个解决方案

#1


1  

Since syscalls operate in kernel space, they are thread safe (they have to be, otherwise kernel data could get corrupted and bring down your entire system) in the sense that your program won't crash - HOWEVER, as noted by Jeremy Friesner in the comments:

由于syscalls在内核空间中运行,所以它们是线程安全的(它们必须如此,否则内核数据可能会损坏并导致整个系统崩溃),因为您的程序不会崩溃——然而,正如Jeremy Friesner在评论中指出的那样:

  • The order in which your syscalls are executed may not necessarily be guaranteed.

    执行syscalls的顺序不一定得到保证。

  • syscalls take time. This means that a lot of data will slip past in between your calls to recv ().

    由于需要时间。这意味着在对recv()的调用之间会有很多数据被忽略。


However, you could definitely write the bytes into a named FIFO. Open the writing end in the thread doing the read () and the reading end in the thread doing the recv ().

但是,您绝对可以将字节写入一个命名的FIFO。打开在线程中执行read()和在线程中执行recv()的结束。

Now, every time you successfully complete a read (), write the first byte (that's all you wanted, yeah?) into the FIFO. Meanwhile, in the other thread, instead of using sleep () in between the recv (), just use a blocking read of size 1 byte on the FIFO and printf () the result.

现在,每次成功完成read()时,将第一个字节(这就是您想要的,对吗?)写入FIFO。与此同时,在另一个线程中,而不是在recv()之间使用sleep(),而是在FIFO和printf()结果上使用1字节的块读。

This way, the kernel can automatically wake up your recv () thread whenever there is data to be read. You don't waste any CPU time with unnecessary context switches either (which are actually pretty big), so your application's overall performance/speed will go up too.

这样,每当有要读取的数据时,内核就可以自动唤醒您的recv()线程。您不会浪费任何CPU时间来使用不必要的上下文切换(实际上是相当大的),因此您的应用程序的整体性能/速度也会提高。

#1


1  

Since syscalls operate in kernel space, they are thread safe (they have to be, otherwise kernel data could get corrupted and bring down your entire system) in the sense that your program won't crash - HOWEVER, as noted by Jeremy Friesner in the comments:

由于syscalls在内核空间中运行,所以它们是线程安全的(它们必须如此,否则内核数据可能会损坏并导致整个系统崩溃),因为您的程序不会崩溃——然而,正如Jeremy Friesner在评论中指出的那样:

  • The order in which your syscalls are executed may not necessarily be guaranteed.

    执行syscalls的顺序不一定得到保证。

  • syscalls take time. This means that a lot of data will slip past in between your calls to recv ().

    由于需要时间。这意味着在对recv()的调用之间会有很多数据被忽略。


However, you could definitely write the bytes into a named FIFO. Open the writing end in the thread doing the read () and the reading end in the thread doing the recv ().

但是,您绝对可以将字节写入一个命名的FIFO。打开在线程中执行read()和在线程中执行recv()的结束。

Now, every time you successfully complete a read (), write the first byte (that's all you wanted, yeah?) into the FIFO. Meanwhile, in the other thread, instead of using sleep () in between the recv (), just use a blocking read of size 1 byte on the FIFO and printf () the result.

现在,每次成功完成read()时,将第一个字节(这就是您想要的,对吗?)写入FIFO。与此同时,在另一个线程中,而不是在recv()之间使用sleep(),而是在FIFO和printf()结果上使用1字节的块读。

This way, the kernel can automatically wake up your recv () thread whenever there is data to be read. You don't waste any CPU time with unnecessary context switches either (which are actually pretty big), so your application's overall performance/speed will go up too.

这样,每当有要读取的数据时,内核就可以自动唤醒您的recv()线程。您不会浪费任何CPU时间来使用不必要的上下文切换(实际上是相当大的),因此您的应用程序的整体性能/速度也会提高。