Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets unix套接字上的原子写入?_Sockets_Unix_Atomic - Fatal编程技术网

Sockets unix套接字上的原子写入?

Sockets unix套接字上的原子写入?,sockets,unix,atomic,Sockets,Unix,Atomic,我正在尝试为IPC机制在管道和unix套接字之间进行选择。 它们都支持select()和epoll()函数,这非常好 现在,管道有一个4kB(截至今天)的“原子”写入,这是由Linux内核保证的。 对于unix套接字,是否存在这样的功能?我找不到任何明确说明这一点的文件 假设我使用UNIX套接字,从客户端写入x字节的数据。我确定当我的服务器的select()崩溃时,这些x字节会写入套接字的服务器端吗 在同一主题上,使用SOCK_DGRAM是否可以确保写入是原子的(如果这种保证是可能的),因为数据

我正在尝试为IPC机制在管道和unix套接字之间进行选择。
它们都支持
select()
epoll()
函数,这非常好

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

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

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

提前谢谢。

管道 是的,非阻塞容量通常为4KB,但为了实现最大的可移植性,最好使用
PIPE\u BUF
常量。另一种方法是使用非阻塞I/O

man 7管道中了解的信息比您想知道的更多

Unix数据报套接字 在数据报套接字上使用
send
函数系列进行的写入确实保证是原子的。在Linux的情况下,它们也是可靠的,并且保留了顺序。(这使得最近推出的
SOCK_SEQPACKET
让我有点困惑)在
man7unix
中有很多关于这方面的信息

最大数据报大小取决于套接字。可以使用
SO_SNDBUF
上的
getsockopt/setsockopt
访问它。在Linux系统上,它的范围在2048到
wmem_max
之间,默认值为
wmem_default
。例如,在我的系统上,
wmem\u default=wmem\u 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
这里没有统计意义。我的瓶颈可能是读取大文件

假设我使用UNIX套接字并编写x 来自我的客户端的字节数据。我是吗 确保这些x字节将 写在服务器端的 当我的服务器的
select()
裂缝

如果您使用的是
AF\u UNIX
SOCK\u STREAM
socket,则不存在这样的保证,即在一个
write/send()
中写入的数据可能需要接收方进行多个
read/recv()
调用

在同一主题上,使用 SOCK_DGRAM确保写入 原子的(如果这样的保证是有效的) 可能),因为数据报是 应该是定义明确的单个 留言

另一方面,需要使用
AF_UNIX
SOCK_DGRAM
套接字来保留数据报边界并使其可靠。如果
send()
无法以原子方式传输数据报,则会出现EMSGSIZE错误。不确定
write()
会发生什么,因为手册页没有说明它可以报告EMSGSIZE(尽管手册页有时不会列出返回的所有错误)。我会尝试用大数据报溢出接收器的缓冲区,以查看哪些错误准确地
send/write()
report


在管道上使用UNIX套接字的一个优点是缓冲区更大。我不记得pipe内核缓冲区的确切限制是什么,但我记得没有足够的缓冲区,也无法增加缓冲区(它是一个硬编码的内核常量)<由于管道缓冲区大小不足,代码>快速生产者进程|慢速消费者进程
快速生产者进程>文件和文件>慢速消费者进程
慢了几个数量级。

我删除了我的答案,因为我对AF\U UNIX socket系列不太熟悉。当我回答时,我不认为你的意思是“unixsocket==AF_Unix”。报告确实指出,带有Unix套接字的数据报是完全可靠的。所以这可能是你的一个选择。但是由于我没有使用它们,我将把它留给更有知识的人来回答。关于非阻塞容量,请注意非阻塞和原子(OP要求的)是正交的。原子写入并不意味着或导致它是非阻塞的,而非阻塞写入可能是非原子的,这意味着并非所有数据都已写入一个write()调用中,但该调用并未阻塞线程。我希望可以像在中所做的那样包括一些实际的块大小演示,但pv对套接字不起作用,如果我通过它,瓶颈在管道上。哦,好吧。最后一段现在还没有得到证实。@Maxim关于非阻塞性/原子性的区别,你是对的(尽管我觉得我们指的是对原子性稍有不同的解释)。我记得上一次在Linux的源代码中潜水时,它们的相关性比我最初想象的要大。但是由于OP没有真正告诉他想要什么,或者他使用了什么Unix风格,我想我会为clarit编辑