以AF_BLUETOOTH爲例,梳理內核中socket address family的註冊過程。
linux內核啓動之時,會初始化各subsystem(子系統),bluetooth就是這樣的一個子系統之一
bluetooth/af_bluetooth.c
subsys_initcall(bt_init);
subsys_initcall是一個宏定義,在include/linux/init.h中:
#define subsys_initcall(fn) __define_initcall("4",fn,4)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
bluetooth/af_bluetooth.c
static int __init bt_init(void)
bt_sysfs_init();//初始化藍牙虛擬文件系統
sock_register(&bt_sock_family_ops);//註冊藍牙地址協議簇
hci_sock_init();//初始化藍牙地址協議簇
l2cap_init();//初始化邏輯鏈路控制與適配協議,由CONFIG_BT_L2CAP控制
sco_init();//初始化同步定向鏈接協議,有CONFIG_BT_SCO控制
這裏主要關注的是藍牙地址協議族的過程的實現
net/socket.c
int sock_register(const struct net_proto_family *ops)
rcu_assign_pointer(net_families[ops->family], ops);
//rcu(Read-Copy Update),無鎖的賦值方式(下次研究),其實就是把bt_sock_family_ops賦值給net_families[AF_BLUETOOTH]
接下來,看hci_sock_init的實現:
net/bluetooth/hci_sock.c
int __init hci_sock_init(void);//初始化hci_sock
bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);//註冊socket ops回調
bt_proto[proto] = ops;//將hci_sock_family_ops存進bt_proto數組裏面,
bt所有的協議如下:
#define BTPROTO_L2CAP 0
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define BTPROTO_RFCOMM 3
#define BTPROTO_BNEP 4
#define BTPROTO_CMTP 5
#define BTPROTO_HIDP 6
#define BTPROTO_AVDTP 7
在執行系統調用 socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)的時候,會調用到內核net/socket.c的__sock_create方法:
net/socket.c
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
struct socket *sock = sock_alloc();//構造一個socket結構
const struct net_proto_family *pf = rcu_dereference(net_families[family]);//取出AF_BLUETOOTH協議結構體
pf->create(net, sock, protocol, kern); //調用剛剛註冊的net_proto_family,也就是bt_sock_family_ops的create方法,
查看bt_sock_family_ops,知道create是bt_sock_create方法
af_bluetooth.c
static int bt_sock_create(struct net *net, struct socket *sock, int proto,
int kern) //proto=BTPROTO_HCI
bt_proto[proto]->create(net, sock, proto, kern); //調用剛剛註冊的hci_sock_family_ops的create方法,也就是hci_sock_create
hci_sock.c
static int hci_sock_create(struct net *net, struct socket *sock, int protocol,
int kern)
sock->ops = &hci_sock_ops;
到目前爲止,AF_BLUETOOTH註冊完成,socket也創建完了,所有對socket的讀寫操作都能定位到hci_cock.c中。