当前位置:网站首页>UDP协议之《套接口阻塞选项UDP_CORK》
UDP协议之《套接口阻塞选项UDP_CORK》
2022-08-10 03:26:00 【程序员扫地僧】
用户层通过setsockopt设置UDP_CORK选项的值,当其使能的时候,此套接口所有发送的数据将汇聚到一个报文中,当UDP_CORK选项的值禁用后,执行发送操作。此选项为Linux内核自有选项,据此实现的应用程序在其他平台系统上可能无法工作。
一、UDP_CORK配置
内核的处理函数为udp_lib_setsockopt。只要用户层传入的值不为0,置位corkflag变量,意味着CORK功能的使能。当用户层设置零值时,corkflag复位为0,同时发送阻塞的报文,由函数push_pending_frames实现。
int udp_lib_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen, int (*push_pending_frames)(struct sock *))
{
struct udp_sock *up = udp_sk(sk);
switch (optname) {
case UDP_CORK:
if (val != 0) {
up->corkflag = 1;
} else {
up->corkflag = 0;
lock_sock(sk);
push_pending_frames(sk);
release_sock(sk);
}
break;
}
由函数udp_setsockopt可知,函数指针push_pending_frames实际上为UDP函数udp_push_pending_frames。
int udp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
udp_push_pending_frames);
}
int udp_push_pending_frames(struct sock *sk) /* Push out all pending data as one UDP datagram. Socket is locked. */
{
skb = ip_finish_skb(sk, fl4);
err = udp_send_skb(skb, fl4);
out:
up->len = 0;
up->pending = 0;
}
二、UDP数据发送
以下以内核的UDP发送函数udp_sendmsg为例,看下CORK阻塞情况。如上节所述,在使能UDP_CORK之后,corkflag置位。对于非CORK阻塞情况,调用ip_make_skb分配SKB缓存后,直接调用udp_send_skb进行发送。对于使能UDP_CORK的情况,在首次将设置UDP套接口的pending值为AF_INET,调用函数ip_append_data缓存发送数据。
int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
/* Lockless fast path for the non-corking case. */
if (!corkreq) {
skb = ip_make_skb(sk, fl4, getfrag, msg, ulen, sizeof(struct udphdr), &ipc, &rt, msg->msg_flags);
err = PTR_ERR(skb);
if (!IS_ERR_OR_NULL(skb))
err = udp_send_skb(skb, fl4);
goto out;
}
/* Now cork the socket to pend data. */
up->pending = AF_INET;
do_append_data:
up->len += ulen;
err = ip_append_data(sk, fl4, getfrag, msg, ulen, sizeof(struct udphdr), &ipc, &rt,
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
out:
return err;
}
对于UDP的发送函数udp_sendpage而言,其仅检查UDP套接口的pending变量。当pending不为真时,调用以上的udp_sendmsg函数执行发送,由于udp_sendpage设置了MSG_MORE标志,udp_sendmsg函数将阻塞发送,置位pending变量。如果用户层未使能UDP_CORK并且也未设置发送函数send/sendmsg的MSG_MORE标志,内核将发送阻塞的数据,见函数udp_push_pending_frames。
int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags)
{
struct inet_sock *inet = inet_sk(sk);
struct udp_sock *up = udp_sk(sk);
if (!up->pending) {
struct msghdr msg = { .msg_flags = flags|MSG_MORE };
ret = udp_sendmsg(sk, &msg, 0);
}
lock_sock(sk);
up->len += size;
if (!(up->corkflag || (flags&MSG_MORE)))
ret = udp_push_pending_frames(sk);
if (!ret)
ret = size;
}
边栏推荐
- ...spread、命名空间、假报错、变化事件、async/await
- uva1481
- Evaluation and Construction of Enterprise Network Security Capability from the Sliding Ruler Model
- c语言:通讯录(动态版本)
- 如何将 @Transactional 事务注解运用到炉火纯青?
- 10个超赞的C语言开源项目,值得学习
- 当我操作dms客户端的时候,我要操控好几个阿里云账号下的数据库,但是这边每次切换都会把我的登录记录删
- C语言原码,反码,补码与大小端
- 中国人保为德科康材承保产品责任险,为消费者权益保驾护航!
- Mini Program Navigation and Navigation Parameters
猜你喜欢
@Autowired注解 --required a single bean, but 2 were found出现的原因以及解决方法
It's almost 35, still "did a little"?What happened to the test workers who had been in the industry for a few years?
中国人保为德科康材承保产品责任险,为消费者权益保驾护航!
The same is a primary test, why does he pay 5,000 yuan more than me?
超全面的Android面试题汇总
如何让导电滑环信号更好
RoyalScope分析仪:CAN总线波形台阶和信号幅值低的问题
plsql 查询数据库操作历史记录(Ctrl + e)
The so-called software testing ability is actually these 5 points
数据库学习真难,头大,有偿提问
随机推荐
使用 requestAnimationFrame 提升 web 性能
leetcode 283:移动零
Leetcode 47 全排列Ⅱ
...spread、命名空间、假报错、变化事件、async/await
C语言顺序表(源码)
How to quickly become a software test engineer?What skills do testers need for a monthly salary of 15k?
暑假第三周总结博客 - 五种传值方式
文本编辑器vim
超全面的Android面试题汇总
关于JWT 和Token(转)
如何开启热部署Devtools
当我操作dms客户端的时候,我要操控好几个阿里云账号下的数据库,但是这边每次切换都会把我的登录记录删
数据库中数据的正确性和相容性是什么
维度表设计
金融财经翻译的行业前景如何
程序国际化
【科研绘图】琴图 +箱型图混合 matplotlib库和seabsorn库的使用
一个刚入行的测试员怎么样做好功能测试?测试思维真的很重要
笔试题记录
【单调栈】【概念讲解&&模板代码】