在unix套接字上写入原子?

Gui*_*i13 10 unix sockets atomic

我正在尝试在IPC机制的管道unix套接字之间进行选择.
两者都支持select()epoll()伟大的功能.

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

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

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

提前致谢.

JB.*_*JB. 11

管道

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

比您想知道的更多信息man 7 pipe.

Unix数据报套接字

使用send数据报套接字上的函数族写入确实是原子的.在Linux的情况下,它们也是可靠的,并且保留了排序.(这使得最近的介绍SOCK_SEQPACKET对我来说有点混乱)关于此的大量信息man 7 unix.

最大数据包大小是插座依赖.它是使用getsockopt/setsockopton 访问的SO_SNDBUF.在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
Run Code Online (Sandbox Code Playgroud)

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