Skip to main content
 首页 » DevOps

socket套接字和驱动绑定分析

2022年07月19日56mq0036

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


本文参考链接:https://www.cnblogs.com/hellokitty2/p/10188376.html