socket() 函数的内部机制是什么?
What is the internal mechanics of socket() function?
我正在尝试使用 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) 创建套接字究竟意味着什么。
手册页只是说明它采用这些参数,创建套接字和 returns 设备描述符。
但我想了解到底发生了什么以及创建套接字所涉及的确切内核步骤。
这里是一个非常广泛的描述(希望有助于理解主要方案)。
内核开发人员可能会被吓坏了...
一个套接字是许多不同通信方式的通用抽象接口。
它提供了许多通用操作,例如关闭、sending/receiving数据、setting/retrieving选项,几乎可以在任何类型的套接字上使用。
创建套接字意味着指定此通信方式的确切属性。
有点像实现接口的具体类型的实例化。
这些属性首先由协议族组织;这是 socket()
调用的第一个参数。
例如:
- PF_INET用于依赖IPv4的通信,
- PF_INET6用于依赖IPv6的通信,
- PF_LOCAL用于inter-process系统内部通信(管道类),
- PF_NETLINK用于与OS内核通信,
- PF_PACKET用于与网络接口直接通信,
- ...(存在很多)
一旦选择了一个协议族,你必须指定,你想在这个族提供的协议中使用哪个协议;这是 socket()
调用的第二个参数。
例如:
- SOCK_DGRAM 用于 IPv4 或 IPv6 上的 UDP,或 PF_LOCAL、
中的不同消息
- SOCK_STREAM用于IPv4或IPv6上的TCP,或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 帧,
当我们请求使用这三个参数创建套接字时,操作系统会创建一个与将要获取的套接字句柄关联的内部资源。
当然,此资源的确切结构取决于所选择的 family/protocol/variant,并且它与特定于它的内核回调相关联。
每次在此套接字上调用操作(通过系统调用)时,都会调用特定的回调。
请看这里:这是对 BlueZ Linux 蓝牙堆栈实现的很好的 high-level 描述:
Linux Without Wires The Basics of Bluetooth。具体来说,它可以让您很好地了解这些 BlueZ 内核驱动程序:
bluetooth.ko, which contains core infrastructure of BlueZ. It exports sockets of the Bluetooth family AF_BLUETOOTH. All BlueZ
modules utilise its services.
Bluetooth HCI packets are transported over UART or USB. The corresponding BlueZ HCI implementation is hci_uart.ko and hci_usb.ko.
The L2CAP layer of Bluetooth, which is responsible for segmentation, reassembly and protocol multiplexing, is implemented by l2cap.ko.
With the help of bnep.ko, TCP/IP applications can run over Bluetooth. This emulates an Ethernet port over the L2CAP layer. The
kernel thread named kbnepd is responsible for BNEP connections.
rfcomm.ko is responsible for running serial port applications like the terminal. This emulates serial ports over the L2CAP layer. The
kernel thread named krfcommd is responsible for RFCOMM connections.
hidp.ko implements the HID (human interface device) layer. The user mode daemon hidd allows BlueZ to handle input devices like Bluetooth
mice.
sco.ko implements the synchronous connection oriented (SCO) layer to handle audio. SCO connections do not specify a channel to connect to a
remote host; only the host address is specified.
另一个优秀的资源是 BlueZ 项目页面:
我正在尝试使用 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) 创建套接字究竟意味着什么。
手册页只是说明它采用这些参数,创建套接字和 returns 设备描述符。
但我想了解到底发生了什么以及创建套接字所涉及的确切内核步骤。
这里是一个非常广泛的描述(希望有助于理解主要方案)。
内核开发人员可能会被吓坏了...
一个套接字是许多不同通信方式的通用抽象接口。
它提供了许多通用操作,例如关闭、sending/receiving数据、setting/retrieving选项,几乎可以在任何类型的套接字上使用。
创建套接字意味着指定此通信方式的确切属性。
有点像实现接口的具体类型的实例化。
这些属性首先由协议族组织;这是 socket()
调用的第一个参数。
例如:
- PF_INET用于依赖IPv4的通信,
- PF_INET6用于依赖IPv6的通信,
- PF_LOCAL用于inter-process系统内部通信(管道类),
- PF_NETLINK用于与OS内核通信,
- PF_PACKET用于与网络接口直接通信,
- ...(存在很多)
一旦选择了一个协议族,你必须指定,你想在这个族提供的协议中使用哪个协议;这是 socket()
调用的第二个参数。
例如:
- SOCK_DGRAM 用于 IPv4 或 IPv6 上的 UDP,或 PF_LOCAL、 中的不同消息
- SOCK_STREAM用于IPv4或IPv6上的TCP,或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 帧,
当我们请求使用这三个参数创建套接字时,操作系统会创建一个与将要获取的套接字句柄关联的内部资源。
当然,此资源的确切结构取决于所选择的 family/protocol/variant,并且它与特定于它的内核回调相关联。
每次在此套接字上调用操作(通过系统调用)时,都会调用特定的回调。
请看这里:这是对 BlueZ Linux 蓝牙堆栈实现的很好的 high-level 描述:
Linux Without Wires The Basics of Bluetooth。具体来说,它可以让您很好地了解这些 BlueZ 内核驱动程序:
bluetooth.ko, which contains core infrastructure of BlueZ. It exports sockets of the Bluetooth family AF_BLUETOOTH. All BlueZ modules utilise its services.
Bluetooth HCI packets are transported over UART or USB. The corresponding BlueZ HCI implementation is hci_uart.ko and hci_usb.ko.
The L2CAP layer of Bluetooth, which is responsible for segmentation, reassembly and protocol multiplexing, is implemented by l2cap.ko.
With the help of bnep.ko, TCP/IP applications can run over Bluetooth. This emulates an Ethernet port over the L2CAP layer. The kernel thread named kbnepd is responsible for BNEP connections.
rfcomm.ko is responsible for running serial port applications like the terminal. This emulates serial ports over the L2CAP layer. The kernel thread named krfcommd is responsible for RFCOMM connections.
hidp.ko implements the HID (human interface device) layer. The user mode daemon hidd allows BlueZ to handle input devices like Bluetooth mice.
sco.ko implements the synchronous connection oriented (SCO) layer to handle audio. SCO connections do not specify a channel to connect to a remote host; only the host address is specified.
另一个优秀的资源是 BlueZ 项目页面: