SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
unsigned, flags, struct sockaddr __user *, addr,
int, addr_len)
{
struct socket *sock;
struct sockaddr_storage address;
int err;
struct msghdr msg;//在bsd 层使用的数据结构封装,在inet层将转换为sk_buff{}
struct iovec iov;
int fput_needed;
goto out;
/*初始化msghdr结构*/
iov.iov_base = buff;
iov.iov_len = len;
msg.msg_name = NULL;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_namelen = 0;
if (addr) {
err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);//实际执行copy_from_user
if (err < 0)
goto out_put;
msg.msg_name = (struct sockaddr *)&address;
msg.msg_namelen = addr_len;
}
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
msg.msg_flags = flags;
err = sock_sendmsg(sock, &msg, len);//-------------------------->所有发送函数都要调用的底层发送函数
out_put:
fput_light(sock->file, fput_needed);
out:
return err;
}
unsigned, flags, struct sockaddr __user *, addr,
int, addr_len)
{
struct socket *sock;
struct sockaddr_storage address;
int err;
struct msghdr msg;//在bsd 层使用的数据结构封装,在inet层将转换为sk_buff{}
struct iovec iov;
int fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed);//通过文件描述符,得到file结构,file结构中的private_data指向sock---这个在建立sock过程中的sock_map_fd实现
if (!sock)goto out;
/*初始化msghdr结构*/
iov.iov_base = buff;
iov.iov_len = len;
msg.msg_name = NULL;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_namelen = 0;
if (addr) {
err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);//实际执行copy_from_user
if (err < 0)
goto out_put;
msg.msg_name = (struct sockaddr *)&address;
msg.msg_namelen = addr_len;
}
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
msg.msg_flags = flags;
err = sock_sendmsg(sock, &msg, len);//-------------------------->所有发送函数都要调用的底层发送函数
out_put:
fput_light(sock->file, fput_needed);
out:
return err;
}