LWN:kernel中如何更好地处理字符串!

关注了就能看到更多这么棒的文章哦~

Better string handling for the kernel

By Jonathan Corbet
October 26, 2023
ChatGPT translation
https://lwn.net/Articles/948408/

C 语言中有很多功能在当时看起来是个好主意(甚至可能在那时确实是好主意),但现在已经过时了。大多数人可能会同意,字符串处理和使用以 NUL 结尾的字符串就是其中一个例子。多年来,内核开发人员一直在试图改进字符串处理,以弥补由这方面的错误导致的 bug 和漏洞的不断出现。现在有一个早期讨论是想要在内核的许多地方摆脱以 NUL 结尾的字符串。

以 NUL 结尾的字符串最大的问题在于它们未带有关于它的相关缓冲区大小的信息;这就很容易发生缓冲区溢出。多年来,为解决这个问题,已经创建了许多 API,添加了像 strncpy(), strlcpy(), 和 strscpy() 这样的函数,每个函数都声称比之前的版本更好。然而,它们都没有改变以 NUL 结尾的字符串的核心概念,并且没有一个能让每个人都满意。

多年来,内核已经看到了一系列演变,有很多 patch 都是从一个字符串函数改到另一个字符串函数。有时这些转换引入了自己特有的 bug,维护者并不总是对这项工作感到满意。最近,对于将 strncpy() 调用转换为 strscpy() 的补丁,Christoph Hellwig 质疑了这些更改的价值:

我们不能再继续假装这种直接操作以 NUL 结尾的字符串是个好主意了。我怀疑用一个更好,也许稍微好一点的辅助函数替换另一个的这种改动可能引入的错误比它修复的错误还多。

他说,真正解决这个问题需要使用比 NUL 结尾的字符串更好的方案。他将 "seq_buf" API 描述为在这个方向上的 "一个良好的开始"。

Seq_buf 是在 2014 年为 3.19 内核版本引入的,作为构建跟踪子系统中字符串的一种改进方法。它是围绕这个结构组织:

struct seq_buf {
    char *buffer;
    size_t size;
    size_t len;
    loff_t readpos;
};

这里没有什么革命性的东西。`buffer` 指向字符串分配的内存,`size` 是该缓冲区的大小。存储在 `buffer` 中的字符串的长度保存在 `len` 中;`readpos` 字段用于在字符串中进行读取。用户必须单独分配 `buffer` 并通过调用以下函数将其附加到 `seq_buf`:

void seq_buf_init(struct seq_buf *s, char *buf, unsigned int size);

有一整套用于处理这个结构的函数,其中大多数函数的含义都相当直白了:

void seq_buf_clear(struct seq_buf *s);
int seq_buf_printf(struct seq_buf *s, const char *fmt, ...);
int seq_buf_puts(struct seq_buf *s, const char *str);
/* ... */

还有很多其他函数;请参阅 include/linux/seq_buf.h 以获取完整的列表。

对 seq_buf 的操作不会出现溢出缓冲区的情况;如果试图存储太多数据,将记录这个事实(`len` 设置为大于 `size` 的值),并且未来的操作将失败。调用 `seq_buf_has_overflowed()` 将返回一个布尔值,告诉是否 `seq_buf` 处于良好状态。该 API 允许进行一系列的字符串操作,只需要在最后进行一次 `seq_buf_has_overflowed()` 检查,以确保一切正常;这显著简化了错误处理代码。

没有访问字符串本身的访问器函数;用户可以直接访问结构中的 `buffer` 字段。该字符串保持以 NUL 结尾,因此可以传递给期望这样的字符串的函数—当然,它们不应直接修改缓冲区。

`readpos` 字段仅在跟踪代码中使用。为了减少总体上使用 `struct seq_buf` 的内存,Matthew Wilcox 最近发布了 一项补丁,删除了该字段并将读取位置的概念推入使用它的代码。这个补丁似乎可能会被接受,因此 `readpos` 将来可能不会成为这个结构的一部分。

Kent Overstreet 最近发布了 seq_buf 的替代品,名为 "printbuf",采用了稍微不同的方法。在该补丁集的讨论中,他被 建议 改进 seq_buf,但他拒绝了这一建议。因此,printbuf 仍然存在于内核之外,但它似乎出现在 linux-next 中,作为预计将在 6.7 中合并的 bcachefs 系列的一部分。printbuf 是否会被视为 seq_buf 的替代品还不清楚,但社区不太可能希望在长期内维护两种相似的字符串抽象。

内核是否会在长期内大规模使用 seq_buf(或 printbuf)?很难判断这种转变可能会走多远。Kees Cook 说,虽然 seq_buf "表现出色" 用于复杂的字符串操作,但对于简单的情况而言,它带来的麻烦大于它的价值,可以在使用更简单的 API 的代码中轻松验证为正确。然而,Willy Tarreau 表示,具有显式长度计数器的字符串更容易处理,可以得到更简单的代码,并且还可能带来更好的性能。与此同时,Linus Torvalds 似乎主要关心 摆脱内核中剩余的 strlcpy() 调用,对于改变内核对字符串的处理方式并没有表达意见。

这场讨论可能会鼓励一些开发人员开始在以 NUL 结尾的 C 字符串的位置使用 seq_buf。然而,这种转变可能会相对缓慢地开始。如果随着时间的推移,这种方法开始显示出好处,可能最终会推动在更广泛的范围进行转换。但是,无论如何,内核似乎有可能在很长一段时间内管理大量以 NUL 结尾的字符串。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

format,png

以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值