【问题标题】:socket descriptor vs file descriptor套接字描述符与文件描述符
【发布时间】:2017-07-17 21:48:34
【问题描述】:

read(2) 和 write(2) 既适用于套接字描述符,也适用于文件描述符。在文件描述符的情况下,用户文件描述符表->文件表,最后到 inode 表,它检查文件类型(常规文件/字符/块),并相应地读取。如果是 char spl 文件,它会根据文件的主设备号从 char 设备开关获取函数指针,并调用为设备注册的适当读/写例程。 类似地,通过从块设备开关获取函数指针,为块特殊文件调用适当的读/写例程。

能否请您告诉我在套接字描述符上调用读/写时会发生什么。如果对socket描述符进行读/写,我们不能用open代替socket来获取描述符吗?

【问题讨论】:

  • 无法确切地告诉您会发生什么(如果您真的想知道,请尝试查看内核源代码),但本质上它会将请求传递给 TCP 驱动程序,它将进一步向下传递网络堆栈,直到它到达网络接口卡的驱动程序。如果您想了解网络堆栈的每一层的一般用途,请查看 OSI 模型。至于opensocket:它们采用不同的参数,因为需要指定的信息根据您是要打开文件还是要打开套接字而有所不同。
  • 我想知道调用 socket() 时分配的数据结构是什么,inode 表中存储了哪些信息,在调用 read/write 时它最终如何到达网络接口卡驱动程序
  • 注意读/写包装系统调用。大部分工作在内核空间中完成。这是一种抽象,或“虚拟化”:只需将块文件、套接字或许多其他东西作为“文件”。文件具有读、写、打开等操作。但是读取套接字或读取磁盘文件的真正实现是在内核中定义的。如果需要,您甚至可以定义从文件中读取的“写入”。

标签: linux


【解决方案1】:

据我所知,在内存中,文件描述符将包含标识此 fd 的文件系统类型的标志。内核将根据文件系统类型调用相应的处理函数。您可以在 linux 内核中看到源 read_write.c。

简而言之,内核做了:

  1. 在read-write.c中有一个file_system_wrapper函数,调用对应的handler函数取决于fd的文件类型(ext2/ext3/socket/..)
  2. 在socket.c中,有一个socket_type_wrapper函数;调用相应的套接字处理函数取决于套接字的类型(ipv4、ipv6、atm 其他)
  3. 在socket_ipv4.c中,有一个protocol_type包装函数;调用对应的协议处理函数依赖于协议tpye(udp/tcp)
  4. 在 tcp_ip4.c;有tcp_sendmsg,写入tcp ipv4类型的FD时会调用该函数。

希望这一点清楚, 谢谢, 后城

【讨论】:

    【解决方案2】:

    套接字描述符也与文件结构相关联,但是用于该结构的一组 file_operations 函数与通常的不同。因此,这些描述符的初始化和使用是不同的。内核级接口的读写部分恰好是完全等价的。

    【讨论】:

    • 我想知道调用 socket() 时分配的数据结构是什么,inode 表中存储了哪些信息,在调用 read/write 时它最终如何到达网络接口卡驱动程序
    • 没有发生,而是故意使之相同
    【解决方案3】:

    读写在某些状态下对某些类型的套接字有效;这一切都取决于内核内部传递的各种结构。

    原则上,open() 可以创建套接字描述符,但 BSD 套接字 API 从来没有这样定义。

    除了 open() 之外,还有一些其他(有点 linux 特定)类型的文件描述符由系统调用打开,例如 epoll_create 或 timerfd_create。这些工作相同。

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 2012-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2012-11-12
      • 2014-04-17
      相关资源
      最近更新 更多