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);}