是 Unix Internet 套接字文件吗?

use*_*463 25 files socket unix-philosophy

我知道“一切都是文件”是 Unix 的主要概念之一,但是套接字使用内核提供的不同 API(如套接字、sendto、recv 等),而不是像普通的文件系统接口。

“一切都是文件”在这里如何应用?

gol*_*cks 26

套接字使用不同的 API

这并不完全正确。有一些用于套接字的附加功能,但您可以使用,例如,普通read()write()在套接字 fd 上。

“一切都是文件”在这里如何应用?

在涉及文件描述符的意义上。

如果您对“文件”的定义是存储在文件系统中的离散字节序列,那么并非所有内容都是文件。但是,如果您对文件的定义更像是句柄——信息的管道,即 I/O 连接——那么“一切都是文件”开始变得更有意义。这些东西不可避免地涉及字节序列,但它们来自哪里或去哪里可能因上下文而异。

然而,它并不是真正意义上的。一个守护进程是不是一个文件,一个守护进程是一个过程; 但是如果您正在执行IPC,您与另一个进程相关的方法可能会被文件样式实体所缓解。

  • 我会说“一切都是文件”的准确改写应该是“所有接口都通过文件”。您通过文件(stdin/out/err、/proc/$pid 等)与进程交互。您通过文件(套接字/文件描述符)与网络交互。您可以通过文件 (/dev/mouse) 与鼠标交互。 (5认同)

kub*_*zyk 12

“一切都是文件”只是夸大其词。它在 1970 年代新颖,UNIX 的主要区别特征。但这只是一个营销概念,并不是 UNIX 的真正基础,因为这显然不是真的。将所有内容都视为文件是没有好处或不明智的。

CPU是文件吗?您的程序是否读取()CPU 以获取新指令?RAM是文件吗?您的程序是否读取()下一个字节?

那时,有多种操作系统为软盘提供了一个 API,为硬盘提供了不同的 API,为磁带提供了不同的 API,为不同的终端提供了一堆不同的 API,等等。IBM 大型机系统在硬盘上有不同类型的文件,并为每个文件提供了不同的 API,信不信由你!因此,UNIX“它是一个文件”方法,连同“stdin/stdout/stderr”方法,为用户和程序员带来了非常优雅的抽象。

有了网络,这种特殊的抽象就行不通了。没有坏处,只是稍微降低了操作系统的整体优雅和连贯性。但它有效。/dev/myinternetz/www/google/com/tcp/80您今天在系统上的任何地方看到一个被调用的文件吗?你能用漂亮的 HTML 打开()它,写()一个查询,然后读()答案吗?不?这是因为这种“是一个文件”的抽象对于在网络中进行交互不是很方便。在实践中它不会工作得很好。泄漏抽象定律在起作用

  • 有趣的事实:某些版本的 bash 将允许您打开 `/dev/tcp/www.google.com/80`。虽然它不是一个实际的文件 - bash 只是伪造它。 (10认同)
  • 请注意,计划 9 更进一步,实际上,网络协议是通过伪文件系统处理的,以实现您的 /dev/myinternetz/www/google/com/tcp/80 示例(当然有不同的路径)。此外,物理内存实际上与文件非常相似,您将内存映射到虚拟地址空间就像将文件映射到虚拟地址空间一样。( malloc 是根据这个想法实现的)。 (4认同)
  • @immibs:更重要的是,制作一个实际实现它的文件系统是合理的。 (2认同)

Gil*_*il' 8

套接字是文件。您可以在套接字上使用readand write:它们相当于调用recvand sendwith flags=0。你用 关闭它们closedup如果您需要调整文件描述符,您可以和朋友一起移动它们。您可以使用 设置一些标志fcntl,并在调用 后使用 stdio 缓冲fdopen。名单还在继续。非常重要的是,您可以调用selectandpoll任何类型的文件,包括套接字,因此这些函数允许程序阻塞,直到它通过列出文件描述符通过任何方式接收到输入。

某些套接字类型(recvsendshutdown等)有额外的系统调用,就像设备 ( ioctl)有额外的系统调用一样。

并非所有文件都有名称,而在有名称的文件中,它们并不总是存在于目录结构中。创建的管道pipe(例如在外壳管道中)和创建的套接字socketpair没有名称,但它们仍然是文件。创建的套接字socket有一个名称,其语法取决于域。此名称在struct sockaddrtobind和其他函数中传递。对于 Unix ( AF_UNIX) 套接字,名称是 a struct sockaddr_un,它是一个族和一个字符串;根据字符串,这可以是文件名(可以mknod在许多 unix 变体上创建命名套接字)或不是(抽象名称空间)。对于 IPv4 ( AF_INET) 套接字,名称为struct sockaddr_in,包含端口号和 IP 地址,以及protocol来自socket调用的 。


Mic*_*nez 7

如果你stat是一个socket,你会看到它有一个inode号和其他普通文件的特征,所以我会把它归类为文件系统上的一个文件。例子:

# file live
live: socket
# stat live
File: `live'
  Size: 0               Blocks: 0          IO Block: 4096   socket
Device: fc03h/64515d    Inode: 198817      Links: 1
Access: (0660/srw-rw----)  Uid: (23129/  icinga)   Gid: (23130/icinga-cmd)
Access: 2014-11-07 09:27:59.000000000 -0800
Modify: 2014-11-05 09:27:03.000000000 -0800
Change: 2014-11-05 09:27:03.000000000 -0800
Run Code Online (Sandbox Code Playgroud)

11/17。Linux (ext3) 的附加信息:套接字有一个 inode(它是磁盘上的 256 字节块)但没有任何数据块(您可以通过提取 inode 并检查数据块指针来验证这一点;或者通过运行 debugfs 'stat' 显示 Blockcount 为 0)。因此,它具有文件元数据(所有者、组、权限等),但磁盘上没有数据内容。这与touch /tmp/foo块计数为 0的常规空文件 ( ) 相同。在第一种情况下,inode 中的“type”字段显示“socket”;在第二种情况下,它显示“常规文件”。

参考资料:ext2 inode 结构statdumpe2fs、 和debugfs命令。