socket套接字和驱动绑定分析

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

 

posted on 2018-12-28 00:55  Hello-World3  阅读(1370)  评论(0编辑  收藏  举报

导航