socket套接字和驅動繫結分析
阿新 • • 發佈:2018-12-28
1. socket()系統呼叫
socket系統呼叫是哪個:socket()有3個引數,因此搜尋SYSCALL_DEFINE3,然後在檢索socket即可。
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) sock_create(family, type, protocol, &sock); __sock_create sock_alloc struct inode *inode; inode->i_op = &sockfs_inode_ops; struct net_proto_family *pf = rcu_dereference(net_families[family]); //獲取之前註冊的協議的pf pf->create(net, sock, protocol, kern); //建立指定協議的套接字 sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); // net/socket.c 把套接字對映成fd newfile=sock_alloc_file(sock, flags, NULL); //返回一個struct file *newfile; file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &socket_file_ops); //此file的file_operations是全域性socket_file_ops sock->file = file; file->private_data = sock; fd_install(fd, newfile); // net/socket.c 若成功就向用戶空間返回這個fd __fd_install(current->files, fd, file); //fs/files.c 放到當前程序的開啟檔案中 struct fdtable *fdt; fdt = rcu_dereference_sched(files->fdt); //fs/files.c 放到當前程序的fd符號表中。
2. PF_BLUETOOTH協議族的註冊過程
/* ①定義net_proto_family */ static const struct net_proto_family bt_sock_family_ops = { // net/bluetooth/af_bluetooth.c .owner = THIS_MODULE, .family = PF_BLUETOOTH, .create = bt_sock_create, }; bt_sock_create err = bt_proto[proto]->create(net, sock, proto, kern); // 呼叫全域性陣列bt_proto[proto]->create() /* ②呼叫sock_register註冊此協議族 */ sock_register(&bt_sock_family_ops); sock_register(const struct net_proto_family *ops) // net/socket.c rcu_assign_pointer(net_families[ops->family], ops); // 將註冊的協議族放到net_proto_family型別的全域性陣列net_families中
3.PF_BLUETOOTH協議族中的協議的註冊過程
static const struct proto_ops hidp_sock_ops = { .family = PF_BLUETOOTH, .owner = THIS_MODULE, .release = hidp_sock_release, .ioctl = hidp_sock_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = hidp_sock_compat_ioctl, #endif .bind = sock_no_bind, .getname = sock_no_getname, .sendmsg = sock_no_sendmsg, .recvmsg = sock_no_recvmsg, .poll = sock_no_poll, .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .connect = sock_no_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .mmap = sock_no_mmap }; static struct proto hidp_proto = { .name = "HIDP", .owner = THIS_MODULE, .obj_size = sizeof(struct bt_sock) }; /* ①定義net_proto_family */ static const struct net_proto_family hidp_sock_family_ops = { .family = PF_BLUETOOTH, .owner = THIS_MODULE, .create = hidp_sock_create }; hidp_sock_create sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, kern); sock->ops = &hidp_sock_ops; /* ②註冊函式不同 */ bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); bt_sock_register proto_register(&hidp_proto, 0); //將hidp_proto.node掛接在全域性連結串列proto_list中 bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); bt_proto[proto] = &hidp_sock_family_ops; //只是將hidp_sock_family_ops放到全域性陣列bt_proto中
由上可知,當應用程式呼叫:sock_fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);時,驅動先呼叫bt_sock_create(),它再呼叫hidp_sock_create(),從而此sock_fd會繫結到函式集合hidp_sock_ops。對比於裝置檔案的操作,這裡只是換湯不換藥而已。