【问题标题】:What is the internal mechanics of socket() function?socket() 函数的内部机制是什么?
【发布时间】:2019-11-30 19:21:29
【问题描述】:

我正在尝试使用 BlueZ HCI 功能:

int hci_open_dev(int dev_id) {...}

它在内部尝试像这样创建一个套接字:

socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);

我试图理解 socket() 的 linux 内核代码,但感到迷茫。

我想知道为给定域 (AF_BLUETOOTH)、数据传输类型 (SOCK_RAW) 和协议 (BTPROTO_HCI) 创建套接字到底意味着什么。

手册页只是声明它接受这些参数,创建一个套接字并返回一个设备描述符。

但我想了解究竟发生了什么以及创建套接字所涉及的确切内核步骤。

【问题讨论】:

  • 如果你想知道确切的内核步骤,那么你必须阅读内核代码。既然你已经尝试过了,我不知道如何回答这个问题。即使要求对该过程进行概述也太宽泛了,因为它涉及到 1) 文件描述符如何工作,2) 协议栈如何工作,以及 3) 设备驱动程序如何工作的讨论。这些主题可以轻松填满一本书,或者一本书中至少 3 个章节。
  • 很公平,但我想在某种抽象层次上理解,socket() 究竟是如何位于进行 socket() 系统调用的用户进程和硬件设备(在这种情况下为蓝牙芯片组)之间的.
  • 我认为您已经阅读了bluetooth/af_bluetooth.c,但由于您没有提及该文件,因此您可能没有。
  • @Cheatah 我在搜索 AF_BLUETOOTH 域定义时查看了该文件。但遗憾的是无法将其中的信息上下文化。
  • 我个人不会因为“太宽泛”而投票结束这个问题。回答它需要相当多的努力,但这是一个关于 Linux 上AF_BLUETOOTH 套接字的特定问题,因此我会说它是可以回答的。我不会付出必要的努力来回答它,但我认为这不是关闭它的足够充分的理由。大概几十行就可以总结出内核中发生的事情。

标签: c linux sockets linux-kernel bluez


【解决方案1】:

这是一个非常广泛的描述(希望有助于理解主要方案)。
内核开发者可能会被吓到……

socket 是许多不同通信方式的通用抽象接口。
它提供了许多通用操作,例如关闭、发送/接收数据、设置/检索选项,几乎可以在任何类型的套接字上使用。

创建套接字意味着指定此通信方式的确切属性。
这有点像实现接口的具体类型的实例化。

这些属性首先由协议族组织;这是socket() 调用的第一个参数。
例如:

  • PF_INET 用于依赖 IPv4 的通信,
  • PF_INET6 用于依赖 IPv6 的通信,
  • PF_LOCAL 用于系统内部的进程间通信(管道的种类),
  • PF_NETLINK 用于与操作系统内核通信,
  • PF_PACKET 用于与网络接口直接通信,
  • ...(其中有很多)

选择协议族后,您必须指定要在该族提供的协议中使用哪个协议;这是socket() 调用的第二个参数。
例如:

  • SOCK_DGRAM 用于 IPv4 或 IPv6 上的 UDP,或 PF_LOCAL 中的不同消息,
  • SOCK_STREAM 用于 TCP over IPv4 或 IPv6,或 PF_LOCAL 中的连续字节流,
  • SOCK_RAW,直接访问的是族中的原始底层协议(如果有)(例如 IPv4 或 IPv6),
  • ...(每个家庭可以提供很多)

一些协议可以接受一些变体或一些限制;这是socket() 调用的第三个参数。
通常0 就足够了,但例如我们可以找到:

  • PF_PACKET、SOCK_RAW、htons(ETH_P_ALL) 用于捕获在网络接口上接收到的任何类型的网络数据包,
  • PF_PACKET、SOCK_RAW、htons(ETH_P_ARP) 仅捕获 ARP 帧,

当我们要求使用这三个参数创建一个套接字时,操作系统会创建一个与将要获取的套接字句柄相关联的内部资源。
当然,此资源的确切结构取决于所选的系列/协议/变体,并且它与特定于它的内核回调相关联。
每次在此套接字上调用一个操作(通过系统调用),都会调用特定的回调。

【讨论】:

  • 谢谢,这是很好的信息。我要重述你最后的声明。 “每次在这个套接字上调用一个操作(通过系统调用),都会调用特定的回调。”
  • 这些回调有什么作用?与硬件交互?用于 IPV4/IPV6 插座的 Wifi 芯片和/或用于蓝牙 HCI 插座的 Broadcomm 芯片?
  • 想真正了解套接字的内部内核调用(如你所说的套接字操作)和输出到芯片组的引脚信号之间的缺失链接。
  • @Ace“与硬件交互”是的,但可能不是直接的。根据具体的上下文,这个抽象和确切的硬件驱动程序之间可能存在多个级别。
  • @Ace 对不起,我没有这么具体的知识。
【解决方案2】:

请看这里:这是对蓝牙堆栈的 BlueZ Linux 实现的一个很好的高级描述:

Linux Without Wires The Basics of Bluetooth。具体来说,它为您提供了对这些 BlueZ 内核驱动程序的一个很好的概述:

  • bluetooth.ko,其中包含 BlueZ 的核心基础架构。它导出蓝牙系列 AF_BLUETOOTH 的套接字。全蓝Z 模块利用它的服务。

  • 蓝牙 HCI 数据包通过 UART 或 USB 传输。对应的 BlueZ HCI 实现是 hci_uart.ko 和 hci_usb.ko。

  • 蓝牙的L2CAP层,负责分段、重组和协议复用,由l2cap.ko实现。

  • 在 bnep.ko 的帮助下,TCP/IP 应用程序可以通过蓝牙运行。这模拟了 L2CAP 层上的以太网端口。这 名为 kbnepd 的内核线程负责 BNEP 连接。

  • rfcomm.ko 负责运行终端等串口应用程序。这在 L2CAP 层上模拟串行端口。这 名为 krfcommd 的内核线程负责 RFCOMM 连接。

  • hidp.ko 实现了 HID(人机接口设备)层。用户模式守护进程 hidd 允许 BlueZ 处理蓝牙等输入设备 老鼠。

  • sco.ko 实现了面向同步连接 (SCO) 层来处理音频。 SCO 连接不指定一个通道来连接 远程主机;仅指定主机地址。

另一个优秀的资源是 BlueZ 项目页面:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-13
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多