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)
{
    //查找监听的sock
	sock = sock_from_file(file, &err);

    //申请并初始化新的socket
	newsock = 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);
}

参考

GitHub - yanfeizhang/coder-kung-fu: 开发内功修炼


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值