accept源碼邏輯

http://blog.csdn.net/zhangskd/article/details/15340969


SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
int __user *, upeer_addrlen)
{
return sys_accept4(fd, upeer_sockaddr, upeer_addrlen, 0);
}




SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
int __user *, upeer_addrlen, int, flags)

{
struct socket *sock, *newsock;
struct file *newfile;
int err, len, newfd, fput_needed;
struct sockaddr_storage address;


if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
return -EINVAL;


if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;


sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out;


err = -ENFILE;
newsock = sock_alloc();
if (!newsock)
goto out_put;


newsock->type = sock->type;
newsock->ops = sock->ops;


/*
* We don't need try_module_get here, as the listening socket (sock)
* has the protocol module (sock->ops->owner) held.
*/
__module_get(newsock->ops->owner);


newfd = get_unused_fd_flags(flags); --------- 最大文件句柄值。
if (unlikely(newfd < 0)) {
err = newfd;
sock_release(newsock);
goto out_put;
}
newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
if (unlikely(IS_ERR(newfile))) {
err = PTR_ERR(newfile);
put_unused_fd(newfd);
sock_release(newsock);
goto out_put;
}


err = security_socket_accept(sock, newsock);
if (err)
goto out_fd;


err = sock->ops->accept(sock, newsock, sock->file->f_flags);
if (err < 0)
goto out_fd;


if (upeer_sockaddr) {
if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
 &len, 2) < 0) {
err = -ECONNABORTED;
goto out_fd;
}
err = move_addr_to_user(&address,
len, upeer_sockaddr, upeer_addrlen);
if (err < 0)
goto out_fd;
}


/* File flags are not inherited via accept() unlike another OSes. */


fd_install(newfd, newfile);
err = newfd;


out_put:
fput_light(sock->file, fput_needed);
out:
return err;
out_fd:
fput(newfile);
put_unused_fd(newfd);
goto out_put;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章