答案1
与其他平台的兼容性,或与旧版本的兼容性,以避免使用snprintf()
和时出现溢出strncpy()
。
迈克尔·克里克 (Michael Kerrisk) 解释道他的书在第 1165 页- 第 57 章,套接字:Unix 域:
SUSv3 未指定 sun_path 字段的大小。早期的 BSD 实现使用 108 和 104 字节,而一种现代实现 (HP-UX 11) 使用 92 字节。便携式应用程序应编码为这个较低的值,并使用 snprintf() 或 strncpy() 以避免写入此字段时缓冲区溢出。
Docker 的人甚至取笑它,因为有些套接字的长度是 110 个字符:
这就是 LINUX 使用 108 字符套接字的原因。这可以改变吗?当然。这就是为什么首先在旧操作系统上创建此限制的原因:
引用一下答案:
它是为了匹配方便的内核数据结构中的可用空间。
引用 McKusick 等人的《4.4BSD 操作系统的设计与实现》。等人。 (第 369 页):
内存管理设施围绕称为 mbuf 的数据结构。 Mbufs(即内存缓冲区)长 128 字节,其中 100 或 108 字节的空间保留用于数据存储。
其他操作系统(unix 域套接字):
- OpenBSD: 104 个字符
- 自由BSD: 104 个字符
- Mac OS X 10.9: 104 个字符
答案2
关于原因,nwildner 已经写了一篇很好的答案。
这里我只关注如何使用以及相对路径的使用。
在内部,虽然套接字文件也可以通过名称查找(我猜),但它们通常是通过索引节点查找的。在 Linux 中,此查找由unix_find_socket_byinode()
定义在网/unix/af_unix.c。
这可以很容易地检查如下:
- 创建两个目录A/和乙/。
- 在每个目录下,让一个进程侦听具有相同名称的套接字文件。和
socat
您可以使用如下命令:
$ socat UNIX-LISTEN:./my.sock -
- 现在通过移动来交换套接字文件A/my.sock到乙/反之亦然。
- 从现在开始,如果客户端应用程序连接到A/my.sock它将联系服务器乙,如果它连接到B/my.sock它将联系服务器A(但请注意,当通信结束时,服务器进程可以合法地删除它认为是自己的套接字文件的内容)。
我在一些 Unix 系统(Linux Debian、FreeBSD 和 OpenIndiana 以获得一些多样性)上检查了这种行为,因此这种行为即使不是标准的,至少也是广泛传播的。
绝对路径通常用作客户端和服务器进程之间的约定,因为客户端进程可能不知道如何与服务器建立初始通信。
但是,如果这种初始通信不是问题,那么使用相对路径创建套接字文件似乎是安全的,这样可以在套接字文件位置不直接由服务器进程控制时避免路径长度问题。