UNIX域(PF_UNIX、PF_LOCAL或AF_UNIX、AF_LOCAL)套接字为UNIX系统的本地进程间的双向数据通信提供了高效的解决方案。
我们可以认为它是管道的双向通信版本。其中命名(绑定明确的地址)的套接字对应于命名管道(mknod xx p),匿名套接字(socketpair)对应于匿名管道(pipe)。有所不同的是UNIX域套接字除了提供面向流(SOCK_STREAM)的接口,还提供有明确数据边界的面向数据报的(SOCK_DGRAM)接口,Linux在2.6.4之后还提供面向流的有明确数据边界的接口(SOCK_SEQPACKET)。UNIX域的数据报接口不同于以网络域(AF_INET或PF_INET)的数据报接口,因为在本机的缘故,它一般情况下并不发生丢包或者是乱序,可以认为它提供可靠的数据通信服务。
鉴于APUE等经典书目都对UNIX域套接字有较为详尽的论述,本文也将不再赘述。这里主要介绍Linux所支持的UNIX域套接字的抽象名字空间(abstract namespace)。Linux下UNIX域套接字的地址结构定义如下:
#define UNIX_PATH_MAX 108
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
|
对于一般的地址来说,sun_path须是一个合法的文件路径,包含绝对路径和相对路径,只是其总长度不能大于108。man 7 unix的结论是此时sun_path必须以'\0'结尾,Linux系统上的实践表明,这并不是必须的,在Linux系统上,这个路径的最大长度是108而不是107,不知到其它系统如何,用户还是尽量遵守规则的好,不然移植可能会出问题。抽象名字空间是相对于文件系统的名字空间而言的,此地址在文件系统上并没有实际文件与之相对应,这就能避免污染文件系统的名字空间,因为它在相应的文件描述符关闭的时候就会自动消失,没有手动移除套接字文件的麻烦。抽象名字以字符'\0'开始,其后可以跟随任何数据,包括'\0',名字的长度在调用bind、connect和sendto的时候作为地址的长度传入。netstat中path以'@'开始的套接字就属于抽象名字空间。
xiaosuo@gentux test $ netstat --unix Active UNIX domain sockets (w/o servers) Proto RefCnt Flags Type State I-Node Path unix 2 [ ] DGRAM 1078 @/org/kernel/udev/udevd unix 2 [ ] DGRAM 9517 @/org/freedesktop/hal/udev_event
|
对于UNIX域的数据报套接字还有点儿特殊,它不会在connect的时候自动绑定本端到一个抽象名字空间,本地地址必须手工用bind指定,否则它就会匿名发送数据,接收端收到的地址为空,无法向其回送数据,这样的设计在不关心信息来源的情况下应该会提高通信效率。
阅读(3940) | 评论(0) | 转发(0) |