> 文档中心 > linux 内核中accept实现

linux 内核中accept实现

目录

accept 系统调用

结构体之间的关系

inet_create

__fd_install


accept 系统调用

SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,int __user *, upeer_addrlen, int, flags){return __sys_accept4(fd, upeer_sockaddr, upeer_addrlen, flags);}

int __sys_accept4_file(struct file *file, unsigned file_flags,struct sockaddr __user *upeer_sockaddr,int __user *upeer_addrlen, int flags,unsigned long nofile){    //查找监听的socksock = sock_from_file(file, &err);    //申请并初始化新的socketnewsock = sock_alloc();newsock->type = sock->type;newsock->ops = sock->ops;    //新申请file,绑定到socket上newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);    //接收链接err = sock->ops->accept(sock, newsock, sock->file->f_flags | file_flags,false);    //添加新文件到当前进程的打开文件列表fd_install(newfd, newfile);    ...}

static const struct file_operations socket_file_ops = {.owner =THIS_MODULE,.llseek =no_llseek,.read_iter =sock_read_iter,.write_iter =sock_write_iter,.poll =sock_poll,};static struct file *alloc_file(const struct path *path, int flags,const struct file_operations *fop){struct file *file;file->f_op = fop;    return file;}struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,const char *name, int flags,const struct file_operations *fops){file = alloc_file(&path, flags, fops);    ...return file;}struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname){struct file *file;    //分配一个文件file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,O_RDWR | (flags & O_NONBLOCK),&socket_file_ops);    sock->file = file;//绑定到socj->file上file->private_data = sock;//sock 又赋值到 file->private ?return file;}

结构体之间的关系

  • struct file 结构体下的 *private_data 赋值为sock
  • accept⾥创建的新 socket ⾥的 file->f_op->poll 函数指向的是 sock_poll
  • sock->ops->accept 对应的⽅法是 inet_accept

inet_create

        在初始化过程中调用sock_init_data,主要sk_data_ready 设置了sock_def_readable在下文中会有调用。

void sock_init_data(struct socket *sock, struct sock *sk){sk->sk_state_change=sock_def_wakeup;sk->sk_data_ready=sock_def_readable;sk->sk_write_space=sock_def_write_space;    ...}

__fd_install

        添加新⽂件到当前进程的打开⽂件列表,file、socket、 sock 等内核对象创建完毕以后,它挂到当前进程的打开⽂件列表中。

void __fd_install(struct files_struct *files, unsigned int fd,struct file *file){fdt = files_fdtable(files);BUG_ON(fdt->fd[fd] != NULL);rcu_assign_pointer(fdt->fd[fd], file);}void fd_install(unsigned int fd, struct file *file){__fd_install(current->files, fd, file);}