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。对比于设备文件的操作,这里只是换汤不换药而已。