当前位置:网站首页>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;
}
边栏推荐
猜你喜欢
goland控制台显示重叠问题解决方案
No ‘Access-Control-Allow-Origin‘ header is present on the requested resource.
socket编程基础
驱动程序开发:无设备树和有设备树的platform驱动
一个刚入行的测试员怎么样做好功能测试?测试思维真的很重要
使用curl指令发起websocket请求
Take you to an in-depth understanding of the version update of 3.4.2, what does it bring to users?
使用注解实现限流
湖仓一体电商项目(四):项目数据种类与采集
Do you know these basic types of software testing?
随机推荐
互联网公司高频面试题精讲:测试计划和测试方案有什么区别?
flutter 每天一背,需要掌握
小程序导航及导航传参
测试工作管理与规范
从零开始配置 vim(10)——快捷键配置
带你深入理解3.4.2的版本更新,对用户带来了什么?
从零开始配置 vim(9)——初始配置
云程发轫,万里可期 | 云扩科技再次入选Gartner《2022年中国ICT技术成熟度曲线报告》
电话自动拨号在电脑上自动拨打
program internationalization
uniapp 路由与页面跳转
golang gin 框架读取无法用 body 传递的表单参数
数据库学习真难,头大,有偿提问
flutter 创建可增型列表和列表排序
It's almost 35, still "did a little"?What happened to the test workers who had been in the industry for a few years?
清洁环保的小型风电滑环基本介绍
超全面的Android面试题汇总
c语言:通讯录(动态版本)
Kotlin协程:父子协程的绑定与传递
...spread、命名空间、假报错、变化事件、async/await