sockets - unix 套接字上的原子写入?

标签 sockets unix atomic

我正在尝试在管道unix套接字之间选择IPC机制。
两者都支持 select()epoll() 函数,这非常棒。

现在,管 Prop 有 4kB(截至今天)的“原子”写入,这是由 Linux 内核保证的。
unix 套接字是否存在这样的功能?我找不到任何文件明确说明这一点。

假设我使用 UNIX 套接字并从客户端写入 x 字节的数据。我确定当我的服务器的 select() 崩溃时,这些 x 字节将被写入套接字的服务器端吗?

对于同一主题,使用 SOCK_DGRAM 是否可以确保写入是原子的(如果可能的话),因为数据报应该单个明确定义的消息?
那么使用 SOCK_STREAM 作为传输模式会有什么区别呢?

提前致谢。

最佳答案

管道

是的,非阻塞容量通常为 4KB,但为了获得最大的可移植性,您最好使用 PIPE_BUF 常量。另一种方法是使用非阻塞 I/O。

man 7 pipeline 中提供的信息比您想了解的更多。

Unix 数据报套接字

在数据报套接字上使用send系列函数进行写入确实保证是原子的。对于 Linux,它们也很可靠,并且保留顺序。 (这使得最近引入的 SOCK_SEQPACKET 让我有点困惑)man 7 unix 中有很多关于此的信息。

最大数据报大小取决于套接字。它可以使用 SO_SNDBUF 上的 getsockopt/setsockopt 进行访问。在 Linux 系统上,它的范围介于 2048 和 wmem_max 之间,默认值为 wmem_default。例如,在我的系统上,wmem_default = wmem_max = 112640。 (您可以从 /proc/sys/net/core 中阅读它们)有关此内容的最相关文档位于 man 7 socket 中的 SO_SNDBUF 选项。我建议您自己阅读它,因为它描述的容量加倍行为一开始可能会有点令人困惑。

流和数据报之间的实际差异

流套接字仅在连接状态下工作。这主要意味着他们一次只能与一个同伴通信。作为流,它们不能保证保留“消息边界”。

数据报套接字已断开连接。他们(理论上)可以同时与多个对等方进行通信。它们保留消息边界。

[我认为新的 SOCK_SEQPACKET 介于:连接和边界保留之间。]

在 Linux 上,两者都是可靠的并且保留消息顺序。如果您使用它们来传输流数据,它们的性能往往相似。因此,只需使用与您的流程相匹配的那个,并让内核为您处理缓冲。

比较流、数据报和管道的粗略基准:

# unix stream 0:05.67
socat UNIX-LISTEN:u OPEN:/dev/null &
until [[ -S u ]]; do :;done
time socat OPEN:large-file UNIX-CONNECT:u

# unix datagram 0:05.12
socat UNIX-RECV:u OPEN:/dev/null &
until [[ -S u ]]; do :;done
time socat OPEN:large-file UNIX-SENDTO:u

# pipe 0:05.44
socat PIPE:p,rdonly=1 OPEN:/dev/null &
until [[ -p p ]]; do :;done
time socat OPEN:large-file PIPE:p

这里没有任何统计意义。我的瓶颈可能是读取大文件。

关于sockets - unix 套接字上的原子写入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4669710/

相关文章:

c - 从客户端到服务器的文件传输

linux - 在unix中使用循环重命名文件

c++ - 发生在同一线程中的关系之前

c++ - CUDA 原子添加失败

java - 了解如何在读取套接字数据(InputStream)时检测断开连接

php - 套接字损坏且无法使用 Laravel 登录 MySQL

java - 如何让此代码等待线程池中的线程可用?

c - 父进程跟踪子进程的终止状态

python - 将 os.popen 命令转换为 subprocess.Popen 实例

ios - 在 iOS 上复制原始类型是原子的吗?