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
.
使用send
数据报套接字上的函数族写入确实是原子的.在Linux的情况下,它们也是可靠的,并且保留了排序.(这使得最近的介绍SOCK_SEQPACKET
对我来说有点混乱)关于此的大量信息man 7 unix
.
的最大数据包大小是插座依赖.它是使用getsockopt/setsockopt
on 访问的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)
这里没有任何统计意义.我的瓶颈可能是阅读大文件.