socket()函数的内部机制是什么?

时间:2019-07-22 19:15:03

标签: c linux sockets linux-kernel bluez

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

int hci_open_dev(int dev_id) {...}

内部尝试创建这样的套接字:

socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);

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

Id想知道为给定域(AF_BLUETOOTH),数据传输类型(SOCK_RAW)和协议(BTPROTO_HCI)创建套接字的确切含义。

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

但是id想了解到底发生了什么以及创建套接字所涉及的确切内核步骤。

2 个答案:

答案 0 :(得分:2)

这是一个非常广泛的描述(希望有助于理解主要方案)。
内核开发人员可能会感到恐惧...

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

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

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

  • PF_INET用于依赖IPv4的通信,
  • PF_INET6用于依赖IPv6的通信,
  • PF_LOCAL用于系统内部的进程间通信(管道类型),
  • 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帧,

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

答案 1 :(得分:2)

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

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

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

  •   
  • 蓝牙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项目页面: