1. 程式人生 > >socket套接字和驅動繫結分析

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。對比於裝置檔案的操作,這裡只是換湯不換藥而已。