tcp_sendmsg函数实现分析

Tcp_sendmsg主要负责把数据从用户空间拷贝到内核空间,然后根据MSS分段,放入到SKB中,调用tcp_push发送出去。大部分代码都是在找应该把数据复制到哪里去。

int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
		size_t size)
{
	struct iovec *iov;
	struct tcp_sock *tp = tcp_sk(sk);
	struct sk_buff *skb;
	int iovlen, flags;
	int mss_now, size_goal;
	int err, copied;
	long timeo;

	lock_sock(sk);
	TCP_CHECK_TIMER(sk);

	flags = msg->msg_flags;
	timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); /* 如果send_msg是阻塞操作的话,获取阻塞的时间 */

	/* Wait for a connection to finish. */
	if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))/* 发送用户数据应该处于ESTABLISHED状态或者是CLOSE_WAIT状态, 如果不在这两种状态则调用sk_stream_wait_connnect 等连接建立完成,如果超时的话就跳转到out_err*/
		if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
			goto out_err;

	/* This should be in poll */
	clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
/* 获取当前的MSS, 并将MSG_OOB清零,因为OOB带外数据不支持GSO*/
	mss_now = tcp_current_mss(sk, !(flags&MSG_OOB)); 
	
/* 获取SKB的最大长度,这个表示SKB到达网络设备上时的最大长度*/
	size_goal = tp->xmit_size_goal;

	/* Ok commence sending. */
	iovlen = msg->msg_iovlen; /* 待发数据块的块数*/
	iov = msg->msg_iov;  /*待发数据指针,起始地址*/
	copied = 0; /* copied表示有多少个数据块已经从用户空间复制到内核空间,先清零*/

	err = -EPIPE;/* 先把错误谁-EPIPE,EPIPE表示本地已经关闭socket连接了*/
	if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) /* 如果本地socket有错误或者不允许发送数据,那么跳到do_error去处理*/
		goto do_error;

	while (--iovlen >= 0) {/* 如果还有待拷贝的数据块,这个循环用于控制拷贝所有的用户数据块到内核空间*/
	
		int seglen = iov->iov_len;  /*当前要复制的这个数据块的长度*/
		unsigned char __user *from = iov->iov_base; /*当前要复制的这个数据块的起始地址*/

		iov++; /*指向下一个数据块*/

		while (seglen > 0) {/*这个数据块是不是全部都
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值