mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-02 12:47:41 +08:00
Merge tag 'Chinese-doc-6.16-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/alexs/linux into docs-mw
Chinese translation docs for 6.16-rc1 from Alex Shi
This is the Chinese translation subtree for 6.16-rc1. It just
includes few changes:
- MAINTAINERS: Change Yanteng's email address
- docs/zh_CN: Add how-to of Chinese translation
- Add networking translation index
- Docs/zh_CN: Translate msg_zerocopy.rst to Simplified Chinese
Signed-off-by: Alex Shi <alexs@kernel.org>
This commit is contained in:
459
Documentation/translations/zh_CN/how-to.rst
Normal file
459
Documentation/translations/zh_CN/how-to.rst
Normal file
@@ -0,0 +1,459 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================
|
||||
Linux内核中文文档翻译规范
|
||||
=========================
|
||||
|
||||
修订记录:
|
||||
- v1.0 2025年3月28日,司延腾、慕冬亮共同编写了该规范。
|
||||
|
||||
制定规范的背景
|
||||
==============
|
||||
|
||||
过去几年,在广大社区爱好者的友好合作下,Linux 内核中文文档迎来了蓬勃的发
|
||||
展。在翻译的早期,一切都是混乱的,社区对译稿只有一个准确翻译的要求,以鼓
|
||||
励更多的开发者参与进来,这是从0到1的必然过程,所以早期的中文文档目录更加
|
||||
具有多样性,不过好在文档不多,维护上并没有过大的压力。
|
||||
|
||||
然而,世事变幻,不觉有年,现在内核中文文档在前进的道路上越走越远,很多潜
|
||||
在的问题逐渐浮出水面,而且随着中文文档数量的增加,翻译更多的文档与提高中
|
||||
文文档可维护性之间的矛盾愈发尖锐。由于文档翻译的特殊性,很多开发者并不会
|
||||
一直更新文档,如果中文文档落后英文文档太多,文档更新的工作量会远大于重新
|
||||
翻译。而且邮件列表中陆续有新的面孔出现,他们那股热情,就像燃烧的火焰,能
|
||||
瞬间点燃整个空间,可是他们的补丁往往具有个性,这会给审阅带来了很大的困难,
|
||||
reviewer 们只能耐心地指导他们如何与社区更好地合作,但是这项工作具有重复
|
||||
性,长此以往,会渐渐浇灭 reviewer 审阅的热情。
|
||||
|
||||
虽然内核文档中已经有了类似的贡献指南,但是缺乏专门针对于中文翻译的,尤其
|
||||
是对于新手来说,浏览大量的文档反而更加迷惑,该文档就是为了缓解这一问题而
|
||||
编写,目的是为提供给新手一个快速翻译指南。
|
||||
|
||||
详细的贡献指南:Documentation/translations/zh_CN/process/index.rst。
|
||||
|
||||
环境搭建
|
||||
========
|
||||
|
||||
工欲善其事必先利其器,如果您目前对内核文档翻译满怀热情,并且会独立地安装
|
||||
linux 发行版和简单地使用 linux 命令行,那么可以迅速开始了。若您尚不具备该
|
||||
能力,很多网站上会有详细的手把手教程,最多一个上午,您应该就能掌握对应技
|
||||
能。您需要注意的一点是,请不要使用 root 用户进行后续步骤和文档翻译。
|
||||
|
||||
拉取开发树
|
||||
----------
|
||||
|
||||
中文文档翻译工作目前独立于 linux-doc 开发树开展,所以您需要拉取该开发树,
|
||||
打开终端命令行执行::
|
||||
|
||||
git clone git://git.kernel.org/pub/scm/linux/kernel/git/alexs/linux.git
|
||||
|
||||
如果您遇到网络连接问题,也可以执行以下命令::
|
||||
|
||||
git clone https://mirrors.hust.edu.cn/git/kernel-doc-zh.git linux
|
||||
|
||||
这是 Alex 开发树的镜像库,每两个小时同步一次上游。如果您了解到更快的 mirror,
|
||||
请随时 **添加** 。
|
||||
|
||||
命令执行完毕后,您会在当前目录下得到一个 linux 目录,该目录就是您之后的工作
|
||||
仓库,请把它放在一个稳妥的位置。
|
||||
|
||||
安装文档构建环境
|
||||
----------------
|
||||
|
||||
内核仓库里面提供了一个半自动化脚本,执行该脚本,会检测您的发行版中需要安
|
||||
装哪些软件包,请按照命令行提示进行安装,通常您只需要复制命令并执行就行。
|
||||
::
|
||||
|
||||
cd linux
|
||||
./scripts/sphinx-pre-install
|
||||
|
||||
以Fedora为例,它的输出是这样的::
|
||||
|
||||
You should run:
|
||||
|
||||
sudo dnf install -y dejavu-sans-fonts dejavu-sans-mono-fonts dejavu-serif-fonts google-noto-sans-cjk-fonts graphviz-gd latexmk librsvg2-tools texlive-anyfontsize texlive-capt-of texlive-collection-fontsrecommended texlive-ctex texlive-eqparbox texlive-fncychap texlive-framed texlive-luatex85 texlive-multirow texlive-needspace texlive-tabulary texlive-threeparttable texlive-upquote texlive-wrapfig texlive-xecjk
|
||||
|
||||
Sphinx needs to be installed either:
|
||||
1) via pip/pypi with:
|
||||
|
||||
/usr/bin/python3 -m venv sphinx_latest
|
||||
. sphinx_latest/bin/activate
|
||||
pip install -r ./Documentation/sphinx/requirements.txt
|
||||
|
||||
If you want to exit the virtualenv, you can use:
|
||||
deactivate
|
||||
|
||||
2) As a package with:
|
||||
|
||||
sudo dnf install -y python3-sphinx
|
||||
|
||||
Please note that Sphinx >= 3.0 will currently produce false-positive
|
||||
warning when the same name is used for more than one type (functions,
|
||||
structs, enums,...). This is known Sphinx bug. For more details, see:
|
||||
https://github.com/sphinx-doc/sphinx/pull/8313
|
||||
|
||||
请您按照提示复制打印的命令到命令行执行,您必须具备 root 权限才能执行 sudo
|
||||
开头的命令。
|
||||
|
||||
如果您处于一个多用户环境中,为了避免对其他人造成影响,建议您配置单用户
|
||||
sphinx 虚拟环境,即只需要执行::
|
||||
|
||||
/usr/bin/python3 -m venv sphinx_latest
|
||||
. sphinx_latest/bin/activate
|
||||
pip install -r ./Documentation/sphinx/requirements.txt
|
||||
|
||||
最后执行以下命令退出虚拟环境::
|
||||
|
||||
deactivate
|
||||
|
||||
您可以在任何需要的时候再次执行以下命令进入虚拟环境::
|
||||
|
||||
. sphinx_latest/bin/activate
|
||||
|
||||
进行第一次文档编译
|
||||
------------------
|
||||
|
||||
进入开发树目录::
|
||||
|
||||
cd linux
|
||||
|
||||
这是一个标准的编译和调试流程,请每次构建时都严格执行::
|
||||
|
||||
. sphinx_latest/bin/activate
|
||||
make cleandocs
|
||||
make htmldocs
|
||||
deactivate
|
||||
|
||||
检查编译结果
|
||||
------------
|
||||
|
||||
编译输出在Documentation/output/目录下,请用浏览器打开该目录下对应
|
||||
的文件进行检查。
|
||||
|
||||
git和邮箱配置
|
||||
-------------
|
||||
|
||||
打开命令行执行::
|
||||
|
||||
sudo dnf install git-email
|
||||
vim ~/.gitconfig
|
||||
|
||||
这里是我的一个配置文件示范,请根据您的邮箱域名服务商提供的手册替换到对
|
||||
应的字段。
|
||||
::
|
||||
|
||||
[user]
|
||||
name = Yanteng Si # 这会出现在您的补丁头部签名栏
|
||||
email = si.yanteng@linux.dev # 这会出现在您的补丁头部签名栏
|
||||
|
||||
[sendemail]
|
||||
from = Yanteng Si <si.yanteng@linux.dev> # 这会出现在您的补丁头部
|
||||
smtpencryption = ssl
|
||||
smtpserver = smtp.migadu.com
|
||||
smtpuser = si.yanteng@linux.dev
|
||||
smtppass = <passwd> # 建议使用第三方客户端专用密码
|
||||
chainreplyto = false
|
||||
smtpserverport = 465
|
||||
|
||||
关于邮件客户端的配置,请查阅Documentation/translations/zh_CN/process/email-clients.rst。
|
||||
|
||||
开始翻译文档
|
||||
============
|
||||
|
||||
文档索引结构
|
||||
------------
|
||||
|
||||
目前中文文档是在Documentation/translations/zh_CN/目录下进行,该
|
||||
目录结构最终会与Documentation/结构一致,所以您只需要将您感兴趣的英文
|
||||
文档文件和对应的 index.rst 复制到 zh_CN 目录下对应的位置,然后修改更
|
||||
上一级的 index 即可开始您的翻译。
|
||||
|
||||
为了保证翻译的文档补丁被顺利合并,不建议多人同时翻译一个目录,因为这会
|
||||
造成补丁之间互相依赖,往往会导致一部分补丁被合并,另一部分产生冲突。
|
||||
|
||||
如果实在无法避免两个人同时对一个目录进行翻译的情况,请将补丁制作进一个补
|
||||
丁集。但是不推荐刚开始就这么做,因为经过实践,在没有指导的情况下,新手很
|
||||
难一次处理好这个补丁集。
|
||||
|
||||
请执行以下命令,新建开发分支::
|
||||
|
||||
git checkout docs-next
|
||||
git branch my-trans
|
||||
git checkout my-trans
|
||||
|
||||
译文格式要求
|
||||
------------
|
||||
|
||||
- 每行长度最多不超过40个字符
|
||||
- 每行长度请保持一致
|
||||
- 标题的下划线长度请按照一个英文一个字符、一个中文两个字符与标题对齐
|
||||
- 其它的修饰符请与英文文档保持一致
|
||||
|
||||
此外在译文的头部,您需要插入以下内容::
|
||||
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: ../disclaimer-zh_CN.rst #您需要了解该文件的路径,根
|
||||
据您实际翻译的文档灵活调整
|
||||
|
||||
:Original: Documentation/xxx/xxx.rst #替换为您翻译的英文文档路径
|
||||
|
||||
:翻译:
|
||||
|
||||
司延腾 Yanteng Si <si.yanteng@linux.dev> #替换为您自己的联系方式
|
||||
|
||||
翻译技巧
|
||||
--------
|
||||
|
||||
中文文档有每行40字符限制,因为一个中文字符等于2个英文字符。但是社区并没有
|
||||
那么严格,一个诀窍是将您的翻译的内容与英文原文的每行长度对齐即可,这样,
|
||||
您也不必总是检查有没有超限。
|
||||
|
||||
如果您的英文阅读能力有限,可以考虑使用辅助翻译工具,例如 deepseek 。但是您
|
||||
必须仔细地打磨,使译文达到“信达雅”的标准。
|
||||
|
||||
**请注意** 社区不接受纯机器翻译的文档,社区工作建立在信任的基础上,请认真对待。
|
||||
|
||||
编译和检查
|
||||
----------
|
||||
|
||||
请执行::
|
||||
|
||||
. sphinx_latest/bin/activate
|
||||
make cleandocs
|
||||
make htmldocs
|
||||
|
||||
解决与您翻译的文档相关的 warning 和 error,然后执行::
|
||||
|
||||
make cleandocs #该步骤不能省略,否则可能不会再次输出真实存在的警告
|
||||
make htmldocs
|
||||
deactivate
|
||||
|
||||
进入 output 目录用浏览器打开您翻译的文档,检查渲染的页面是否正常,如果正常,
|
||||
继续进行后续步骤,否则请尝试解决。
|
||||
|
||||
制作补丁
|
||||
========
|
||||
|
||||
提交改动
|
||||
--------
|
||||
|
||||
执行以下命令,在弹出的交互式页面中填写必要的信息。
|
||||
::
|
||||
|
||||
git add .
|
||||
git commit -s -v
|
||||
|
||||
请参考以下信息进行输入::
|
||||
|
||||
docs/zh_CN: Add self-protection index Chinese translation
|
||||
|
||||
Translate .../security/self-protection.rst into Chinese.
|
||||
|
||||
Update the translation through commit b080e52110ea #请执行git log <您翻译的英文文档路径> 复制最顶部第一个补丁的sha值的前12位,替换掉12位sha值。
|
||||
("docs: update self-protection __ro_after_init status")
|
||||
|
||||
Signed-off-by: Yanteng Si <si.yanteng@linux.dev> #如果您前面的步骤正确执行,该行会自动显示,否则请检查gitconfig文件。
|
||||
|
||||
保存并退出。
|
||||
|
||||
**请注意** 以上四行,缺少任何一行,您都将会在第一轮审阅后返工,如果您需要一个更加明确的示例,请对 zh_CN 目录执行 git log。
|
||||
|
||||
导出补丁和制作封面
|
||||
------------------
|
||||
|
||||
这个时候,可以导出补丁,做发送邮件列表最后的准备了。命令行执行::
|
||||
|
||||
git format-patch -N
|
||||
|
||||
然后命令行会输出类似下面的内容::
|
||||
|
||||
0001-docs-zh_CN-add-xxxxxxxx.patch
|
||||
0002-docs-zh_CN-add-xxxxxxxx.patch
|
||||
……
|
||||
|
||||
测试补丁
|
||||
--------
|
||||
|
||||
内核提供了一个补丁检测脚本,请执行::
|
||||
|
||||
./scripts/checkpatch.pl *.patch
|
||||
|
||||
参考脚本输出,解决掉所有的 error 和 warning,通常情况下,只有下面这个
|
||||
warning 不需要解决::
|
||||
|
||||
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
|
||||
|
||||
一个简单的解决方法是一次只检查一个补丁,然后打上该补丁,直接对译文进行修改,
|
||||
然后执行以下命令为补丁追加更改::
|
||||
|
||||
git checkout docs-next
|
||||
git branch test-trans
|
||||
git am 0001-xxxxx.patch
|
||||
./scripts/checkpatch.pl 0001-xxxxx.patch
|
||||
直接修改您的翻译
|
||||
git add .
|
||||
git am --amend
|
||||
保存退出
|
||||
git am 0002-xxxxx.patch
|
||||
……
|
||||
|
||||
重新导出再次检测,重复这个过程,直到处理完所有的补丁。
|
||||
|
||||
最后,如果检测时没有 warning 和 error 需要被处理或者您只有一个补丁,请跳
|
||||
过下面这个步骤,否则请重新导出补丁制作封面::
|
||||
|
||||
git format-patch -N --cover-letter --thread=shallow #N为您的补丁数量,N一般要大于1。
|
||||
|
||||
然后命令行会输出类似下面的内容::
|
||||
|
||||
0000-cover-letter.patch
|
||||
0001-docs-zh_CN-add-xxxxxxxx.patch
|
||||
0002-docs-zh_CN-add-xxxxxxxx.patch
|
||||
|
||||
您需要用编辑器打开0号补丁,修改两处内容::
|
||||
|
||||
vim 0000-cover-letter.patch
|
||||
|
||||
...
|
||||
Subject: [PATCH 0/1] *** SUBJECT HERE *** #修改该字段,概括您的补丁集都做了哪些事情
|
||||
|
||||
*** BLURB HERE *** #修改该字段,详细描述您的补丁集做了哪些事情
|
||||
|
||||
Yanteng Si (1):
|
||||
docs/zh_CN: add xxxxx
|
||||
...
|
||||
|
||||
如果您只有一个补丁,则可以不制作封面,即0号补丁,只需要执行::
|
||||
|
||||
git format-patch -1
|
||||
|
||||
把补丁提交到邮件列表
|
||||
====================
|
||||
|
||||
恭喜您,您的文档翻译现在可以提交到邮件列表了。
|
||||
|
||||
获取维护者和审阅者邮箱以及邮件列表地址
|
||||
--------------------------------------
|
||||
|
||||
内核提供了一个自动化脚本工具,请执行::
|
||||
|
||||
./scripts/get_maintainer.pl *.patch
|
||||
|
||||
将输出的邮箱地址保存下来。
|
||||
|
||||
将补丁提交到邮件列表
|
||||
--------------------
|
||||
|
||||
打开上面您保存的邮件地址,执行::
|
||||
|
||||
git send-email *.patch --to <maintainer email addr> --cc <others addr> #一个to对应一个地址,一个cc对应一个地址,有几个就写几个。
|
||||
|
||||
执行该命令时,请确保网络通常,邮件发送成功一般会返回250。
|
||||
|
||||
您可以先发送给自己,尝试发出的 patch 是否可以用 'git am' 工具正常打上。
|
||||
如果检查正常, 您就可以放心的发送到社区评审了。
|
||||
|
||||
如果该步骤被中断,您可以检查一下,继续用上条命令发送失败的补丁,一定不要再
|
||||
次发送已经发送成功的补丁。
|
||||
|
||||
积极参与审阅过程并迭代补丁
|
||||
==========================
|
||||
|
||||
补丁提交到邮件列表并不代表万事大吉,您还需要积极回复 maintainer 和
|
||||
reviewer 的评论,做到每条都有回复,每个回复都落实到位。
|
||||
|
||||
如何回复评论
|
||||
------------
|
||||
|
||||
- 请先将您的邮箱客户端信件回复修改为 **纯文本** 格式,并去除所有签名,尤其是
|
||||
企业邮箱。
|
||||
- 然后点击回复按钮,并将要回复的邮件带入,
|
||||
- 在第一条评论行尾换行,输入您的回复
|
||||
- 在第二条评论行尾换行,输入您的回复
|
||||
- 直到处理完最后一条评论,换行空两行输入问候语和署名
|
||||
|
||||
注意,信件回复请尽量使用英文。
|
||||
|
||||
迭代补丁
|
||||
--------
|
||||
|
||||
建议您每回复一条评论,就修改一处翻译。然后重新生成补丁,相信您现在已经具
|
||||
备了灵活使用 git am --amend 的能力。
|
||||
|
||||
每次迭代一个补丁,不要一次多个::
|
||||
|
||||
git am <您要修改的补丁>
|
||||
直接对文件进行您的修改
|
||||
git add .
|
||||
git commit --amend
|
||||
|
||||
当您将所有的评论落实到位后,导出第二版补丁,并修改封面::
|
||||
|
||||
git format-patch -N -v 2 --cover-letter --thread=shallow
|
||||
|
||||
打开0号补丁,在 BLURB HERE 处编写相较于上个版本,您做了哪些改动。
|
||||
|
||||
然后执行::
|
||||
|
||||
git send-email v2* --to <maintainer email addr> --cc <others addr>
|
||||
|
||||
这样,新的一版补丁就又发送到邮件列表等待审阅,之后就是重复这个过程。
|
||||
|
||||
审阅周期
|
||||
--------
|
||||
|
||||
因为有时邮件列表比较繁忙,您的邮件可能会被淹没,如果超过两周没有得到任何
|
||||
回复,请自己回复自己,回复的内容为 Ping.
|
||||
|
||||
最终,如果您落实好了所有的评论,并且一段时间后没有最新的评论,您的补丁将
|
||||
会先进入 Alex 的开发树,然后进入 linux-doc 开发树,最终在下个窗口打开
|
||||
时合并进 mainline 仓库。
|
||||
|
||||
紧急处理
|
||||
--------
|
||||
|
||||
如果您发送到邮件列表之后。发现发错了补丁集,尤其是在多个版本迭代的过程中;
|
||||
自己发现了一些不妥的翻译;发送错了邮件列表……
|
||||
|
||||
git email默认会抄送给您一份,所以您可以切换为审阅者的角色审查自己的补丁,
|
||||
并留下评论,描述有何不妥,将在下个版本怎么改,并付诸行动,重新提交,但是
|
||||
注意频率,每天提交的次数不要超过两次。
|
||||
|
||||
新手任务
|
||||
--------
|
||||
对于首次参与 Linux 内核中文文档翻译的新手,建议您在 linux 目录中运行以下命令:
|
||||
::
|
||||
|
||||
./script/checktransupdate.py -l zh_CN``
|
||||
|
||||
该命令会列出需要翻译或更新的英文文档。
|
||||
|
||||
关于详细操作说明,请参考: Documentation/translations/zh_CN/doc-guide/checktransupdate.rst\
|
||||
|
||||
进阶
|
||||
----
|
||||
|
||||
希望您不只是单纯的翻译内核文档,在熟悉了一起与社区工作之后,您可以审阅其他
|
||||
开发者的翻译,或者提出具有建设性的主张。与此同时,与文档对应的代码更加有趣,
|
||||
而且需要完善的地方还有很多,勇敢地去探索,然后提交你的想法吧。
|
||||
|
||||
常见的问题
|
||||
==========
|
||||
|
||||
Maintainer回复补丁不能正常apply
|
||||
-------------------------------
|
||||
|
||||
这通常是因为您的补丁与邮件列表其他人的补丁产生了冲突,别人的补丁先被 apply 了,
|
||||
您的补丁集就无法成功 apply 了,这需要您更新本地分支,在本地解决完冲突后再次提交。
|
||||
|
||||
请尽量避免冲突,不要多个人同时翻译一个目录。翻译之前可以通过 git log 查看您感
|
||||
兴趣的目录近期有没有其他人翻译,如果有,请提前私信联系对方,请求其代为发送您
|
||||
的补丁。如果对方未来一个月内没有提交新补丁的打算,您可以独自发送。
|
||||
|
||||
回信被邮件列表拒收
|
||||
------------------
|
||||
|
||||
大部分情况下,是由于您发送了非纯文本格式的信件,请尽量避免使用 webmail,推荐
|
||||
使用邮件客户端,比如 thunderbird,记得在设置中的回信配置那改为纯文本发送。
|
||||
|
||||
如果超过了24小时,您依旧没有在<https://lore.kernel.org/linux-doc/>发现您的邮
|
||||
件,请联系您的网络管理员帮忙解决。
|
||||
@@ -21,18 +21,18 @@
|
||||
这是中文内核文档树的顶级目录。内核文档,就像内核本身一样,在很大程度上是一
|
||||
项正在进行的工作;当我们努力将许多分散的文件整合成一个连贯的整体时尤其如此。
|
||||
另外,随时欢迎您对内核文档进行改进;如果您想提供帮助,请加入vger.kernel.org
|
||||
上的linux-doc邮件列表。
|
||||
上的linux-doc邮件列表,并按照Documentation/translations/zh_CN/how-to.rst的
|
||||
指引提交补丁。提交补丁之前请确保执行"make htmldocs”后无与翻译有关的异常输出。
|
||||
|
||||
顺便说下,中文文档也需要遵守内核编码风格,风格中中文和英文的主要不同就是中文
|
||||
的字符标点占用两个英文字符宽度,所以,当英文要求不要超过每行100个字符时,
|
||||
中文就不要超过50个字符。另外,也要注意'-','='等符号与相关标题的对齐。在将
|
||||
补丁提交到社区之前,一定要进行必要的 ``checkpatch.pl`` 检查和编译测试,确保
|
||||
在 ``make htmldocs/pdfdocs`` 中不增加新的告警,最后,安装检查你生成的
|
||||
html/pdf 文件,确认它们看起来是正常的。
|
||||
如何翻译内核文档
|
||||
----------------
|
||||
|
||||
提交之前请确认你的补丁可以正常提交到中文文档维护库:
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/alexs/linux.git/
|
||||
如果你的补丁依赖于其他人的补丁, 可以与其他人商量后由某一个人合并提交。
|
||||
翻译文档本身是一件很简单的事情,但是提交补丁需要注意一些细节,为了保证内核中文文档的高质量可持续发展,提供了一份翻译指南。
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
how-to.rst
|
||||
|
||||
与Linux 内核社区一起工作
|
||||
------------------------
|
||||
|
||||
160
Documentation/translations/zh_CN/networking/index.rst
Normal file
160
Documentation/translations/zh_CN/networking/index.rst
Normal file
@@ -0,0 +1,160 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/index.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
王亚鑫 Wang Yaxin <wang.yaxin@zte.com.cn>
|
||||
|
||||
:校译:
|
||||
|
||||
网络
|
||||
====
|
||||
|
||||
有关网络设备(netdev)开发过程的详细指南,请参考::ref:`netdev-FAQ`
|
||||
|
||||
目录:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
msg_zerocopy
|
||||
|
||||
Todolist:
|
||||
|
||||
* af_xdp
|
||||
* bareudp
|
||||
* batman-adv
|
||||
* can
|
||||
* can_ucan_protocol
|
||||
* device_drivers/index
|
||||
* diagnostic/index
|
||||
* dsa/index
|
||||
* devlink/index
|
||||
* caif/index
|
||||
* ethtool-netlink
|
||||
* ieee802154
|
||||
* iso15765-2
|
||||
* j1939
|
||||
* kapi
|
||||
* failover
|
||||
* net_dim
|
||||
* net_failover
|
||||
* page_pool
|
||||
* phy
|
||||
* sfp-phylink
|
||||
* alias
|
||||
* bridge
|
||||
* snmp_counter
|
||||
* checksum-offloads
|
||||
* segmentation-offloads
|
||||
* scaling
|
||||
* tls
|
||||
* tls-offload
|
||||
* tls-handshake
|
||||
* nfc
|
||||
* 6lowpan
|
||||
* 6pack
|
||||
* arcnet-hardware
|
||||
* arcnet
|
||||
* atm
|
||||
* ax25
|
||||
* bonding
|
||||
* cdc_mbim
|
||||
* dccp
|
||||
* dctcp
|
||||
* devmem
|
||||
* dns_resolver
|
||||
* driver
|
||||
* eql
|
||||
* fib_trie
|
||||
* filter
|
||||
* generic-hdlc
|
||||
* generic_netlink
|
||||
* netlink_spec/index
|
||||
* gen_stats
|
||||
* gtp
|
||||
* ila
|
||||
* ioam6-sysctl
|
||||
* ip_dynaddr
|
||||
* ipsec
|
||||
* ip-sysctl
|
||||
* ipv6
|
||||
* ipvlan
|
||||
* ipvs-sysctl
|
||||
* kcm
|
||||
* l2tp
|
||||
* lapb-module
|
||||
* mac80211-injection
|
||||
* mctp
|
||||
* mpls-sysctl
|
||||
* mptcp
|
||||
* mptcp-sysctl
|
||||
* multiqueue
|
||||
* multi-pf-netdev
|
||||
* napi
|
||||
* net_cachelines/index
|
||||
* netconsole
|
||||
* netdev-features
|
||||
* netdevices
|
||||
* netfilter-sysctl
|
||||
* netif-msg
|
||||
* netmem
|
||||
* nexthop-group-resilient
|
||||
* nf_conntrack-sysctl
|
||||
* nf_flowtable
|
||||
* oa-tc6-framework
|
||||
* openvswitch
|
||||
* operstates
|
||||
* packet_mmap
|
||||
* phonet
|
||||
* phy-link-topology
|
||||
* pktgen
|
||||
* plip
|
||||
* ppp_generic
|
||||
* proc_net_tcp
|
||||
* pse-pd/index
|
||||
* radiotap-headers
|
||||
* rds
|
||||
* regulatory
|
||||
* representors
|
||||
* rxrpc
|
||||
* sctp
|
||||
* secid
|
||||
* seg6-sysctl
|
||||
* skbuff
|
||||
* smc-sysctl
|
||||
* sriov
|
||||
* statistics
|
||||
* strparser
|
||||
* switchdev
|
||||
* sysfs-tagging
|
||||
* tc-actions-env-rules
|
||||
* tc-queue-filters
|
||||
* tcp_ao
|
||||
* tcp-thin
|
||||
* team
|
||||
* timestamping
|
||||
* tipc
|
||||
* tproxy
|
||||
* tuntap
|
||||
* udplite
|
||||
* vrf
|
||||
* vxlan
|
||||
* x25
|
||||
* x25-iface
|
||||
* xfrm_device
|
||||
* xfrm_proc
|
||||
* xfrm_sync
|
||||
* xfrm_sysctl
|
||||
* xdp-rx-metadata
|
||||
* xsk-tx-metadata
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
||||
223
Documentation/translations/zh_CN/networking/msg_zerocopy.rst
Normal file
223
Documentation/translations/zh_CN/networking/msg_zerocopy.rst
Normal file
@@ -0,0 +1,223 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. include:: ../disclaimer-zh_CN.rst
|
||||
|
||||
:Original: Documentation/networking/msg_zerocopy.rst
|
||||
|
||||
:翻译:
|
||||
|
||||
王亚鑫 Wang Yaxin <wang.yaxin@zte.com.cn>
|
||||
|
||||
:校译:
|
||||
|
||||
- 徐鑫 xu xin <xu.xin16@zte.com.cn>
|
||||
- 何配林 He Peilin <he.peilin@zte.com.cn>
|
||||
|
||||
============
|
||||
MSG_ZEROCOPY
|
||||
============
|
||||
|
||||
简介
|
||||
====
|
||||
|
||||
MSG_ZEROCOPY 标志用于启用套接字发送调用的免拷贝功能。该功能目前适用于 TCP、UDP 和 VSOCK
|
||||
(使用 virtio 传输)套接字。
|
||||
|
||||
机遇与注意事项
|
||||
--------------
|
||||
|
||||
在用户进程与内核之间拷贝大型缓冲区可能会消耗大量资源。Linux 支持多种免拷贝的接口,如sendfile
|
||||
和 splice。MSG_ZEROCOPY 标志将底层的拷贝避免机制扩展到了常见的套接字发送调用中。
|
||||
|
||||
免拷贝并非毫无代价。在实现上,它通过页面固定(page pinning)将按字节拷贝的成本替换为页面统计
|
||||
(page accounting)和完成通知的开销。因此,MSG_ZEROCOPY 通常仅在写入量超过大约 10 KB 时
|
||||
才有效。
|
||||
|
||||
页面固定还会改变系统调用的语义。它会暂时在进程和网络堆栈之间共享缓冲区。与拷贝不同,进程在系统
|
||||
调用返回后不能立即覆盖缓冲区,否则可能会修改正在传输中的数据。内核的完整性不会受到影响,但有缺
|
||||
陷的程序可能会破坏自己的数据流。
|
||||
|
||||
当内核返回数据可以安全修改的通知时,进程才可以修改数据。因此,将现有应用程序转换为使用
|
||||
MSG_ZEROCOPY 并非总是像简单地传递该标志那样容易。
|
||||
|
||||
更多信息
|
||||
--------
|
||||
|
||||
本文档的大部分内容是来自于 netdev 2.1 上发表的一篇长篇论文。如需更深入的信息,请参阅该论文和
|
||||
演讲,或者浏览 LWN.net 上的精彩报道,也可以直接阅读源码。
|
||||
|
||||
论文、幻灯片、视频:
|
||||
https://netdevconf.org/2.1/session.html?debruijn
|
||||
|
||||
LWN 文章:
|
||||
https://lwn.net/Articles/726917/
|
||||
|
||||
补丁集:
|
||||
[PATCH net-next v4 0/9] socket sendmsg MSG_ZEROCOPY
|
||||
https://lore.kernel.org/netdev/20170803202945.70750-1-willemdebruijn.kernel@gmail.com
|
||||
|
||||
接口
|
||||
====
|
||||
|
||||
传递 MSG_ZEROCOPY 标志是启用免拷贝功能的最明显步骤,但并非唯一的步骤。
|
||||
|
||||
套接字设置
|
||||
----------
|
||||
|
||||
当应用程序向 send 系统调用传递未定义的标志时,内核通常会宽容对待。默认情况下,它会简单地忽略
|
||||
这些标志。为了避免为那些偶然传递此标志的遗留进程启用免拷贝模式,进程必须首先通过设置套接字选项
|
||||
来表明意图:
|
||||
|
||||
::
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &one, sizeof(one)))
|
||||
error(1, errno, "setsockopt zerocopy");
|
||||
|
||||
传输
|
||||
----
|
||||
|
||||
对 send(或 sendto、sendmsg、sendmmsg)本身的改动非常简单。只需传递新的标志即可。
|
||||
|
||||
::
|
||||
|
||||
ret = send(fd, buf, sizeof(buf), MSG_ZEROCOPY);
|
||||
|
||||
如果零拷贝操作失败,将返回 -1,并设置 errno 为 ENOBUFS。这种情况可能发生在套接字超出其
|
||||
optmem 限制,或者用户超出其锁定页面的 ulimit 时。
|
||||
|
||||
混合使用免拷贝和拷贝
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
许多工作负载同时包含大型和小型缓冲区。由于对于小数据包来说,免拷贝的成本高于拷贝,因此该
|
||||
功能是通过标志实现的。带有标志的调用和没有标志的调用可以安全地混合使用。
|
||||
|
||||
通知
|
||||
----
|
||||
|
||||
当内核认为可以安全地重用之前传递的缓冲区时,它必须通知进程。完成通知在套接字的错误队列上
|
||||
排队,类似于传输时间戳接口。
|
||||
|
||||
通知本身是一个简单的标量值。每个套接字都维护一个内部的无符号 32 位计数器。每次带有
|
||||
MSG_ZEROCOPY 标志的 send 调用成功发送数据时,计数器都会增加。如果调用失败或长度为零,
|
||||
则计数器不会增加。该计数器统计系统调用的调用次数,而不是字节数。在 UINT_MAX 次调用后,
|
||||
计数器会循环。
|
||||
|
||||
通知接收
|
||||
~~~~~~~~
|
||||
|
||||
下面的代码片段展示了 API 的使用。在最简单的情况下,每次 send 系统调用后,都会对错误队列
|
||||
进行轮询和 recvmsg 调用。
|
||||
|
||||
从错误队列读取始终是一个非阻塞操作。poll 调用用于阻塞,直到出现错误。它会在其输出标志中
|
||||
设置 POLLERR。该标志不需要在 events 字段中设置。错误会无条件地发出信号。
|
||||
|
||||
::
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = 0;
|
||||
if (poll(&pfd, 1, -1) != 1 || pfd.revents & POLLERR == 0)
|
||||
error(1, errno, "poll");
|
||||
|
||||
ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
|
||||
if (ret == -1)
|
||||
error(1, errno, "recvmsg");
|
||||
|
||||
read_notification(msg);
|
||||
|
||||
|
||||
这个示例仅用于演示目的。在实际应用中,不等待通知,而是每隔几次 send 调用就进行一次非阻塞
|
||||
读取会更高效。
|
||||
|
||||
零拷贝通知可以与其他套接字操作乱序处理。通常,拥有错误队列套接字会阻塞其他操作,直到错误
|
||||
被读取。然而,零拷贝通知具有零错误代码,因此不会阻塞 send 和 recv 调用。
|
||||
|
||||
通知批处理
|
||||
~~~~~~~~~~~~
|
||||
|
||||
可以使用 recvmmsg 调用来一次性读取多个未决的数据包。这通常不是必需的。在每条消息中,内核
|
||||
返回的不是一个单一的值,而是一个范围。当错误队列上有一个通知正在等待接收时,它会将连续的通
|
||||
知合并起来。
|
||||
|
||||
当一个新的通知即将被排队时,它会检查队列尾部的通知的范围是否可以扩展以包含新的值。如果是这
|
||||
样,它会丢弃新的通知数据包,并增大未处理通知的范围上限值。
|
||||
|
||||
对于按顺序确认数据的协议(如 TCP),每个通知都可以合并到前一个通知中,因此在任何时候在等待
|
||||
的通知都不会超过一个。
|
||||
|
||||
有序交付是常见的情况,但不能保证。在重传和套接字拆除时,通知可能会乱序到达。
|
||||
|
||||
通知解析
|
||||
~~~~~~~~
|
||||
|
||||
下面的代码片段演示了如何解析控制消息:前面代码片段中的 read_notification() 调用。通知
|
||||
以标准错误格式 sock_extended_err 编码。
|
||||
|
||||
控制数据中的级别和类型字段是协议族特定的,对于 TCP 或 UDP 套接字,分别为 IP_RECVERR 或
|
||||
IPV6_RECVERR。对于 VSOCK 套接字,cmsg_level 为 SOL_VSOCK,cmsg_type 为 VSOCK_RECVERR。
|
||||
|
||||
错误来源是新的类型 SO_EE_ORIGIN_ZEROCOPY。如前所述,ee_errno 为零,以避免在套接字上
|
||||
阻塞地读取和写入系统调用。
|
||||
|
||||
32 位通知范围编码为 [ee_info, ee_data]。这个范围是包含边界值的。除了下面讨论的 ee_code
|
||||
字段外,结构中的其他字段应被视为未定义的。
|
||||
|
||||
::
|
||||
|
||||
struct sock_extended_err *serr;
|
||||
struct cmsghdr *cm;
|
||||
|
||||
cm = CMSG_FIRSTHDR(msg);
|
||||
if (cm->cmsg_level != SOL_IP &&
|
||||
cm->cmsg_type != IP_RECVERR)
|
||||
error(1, 0, "cmsg");
|
||||
|
||||
serr = (void *) CMSG_DATA(cm);
|
||||
if (serr->ee_errno != 0 ||
|
||||
serr->ee_origin != SO_EE_ORIGIN_ZEROCOPY)
|
||||
error(1, 0, "serr");
|
||||
|
||||
printf("completed: %u..%u\n", serr->ee_info, serr->ee_data);
|
||||
|
||||
|
||||
延迟拷贝
|
||||
~~~~~~~~
|
||||
|
||||
传递标志 MSG_ZEROCOPY 是向内核发出的一个提示,让内核采用免拷贝的策略,同时也是一种约
|
||||
定,即内核会对完成通知进行排队处理。但这并不保证拷贝操作一定会被省略。
|
||||
|
||||
拷贝避免不总是适用的。不支持分散/聚集 I/O 的设备无法发送由内核生成的协议头加上零拷贝用户
|
||||
数据组成的数据包。数据包可能需要在协议栈底层转换为一份私有数据副本,例如用于计算校验和。
|
||||
|
||||
在所有这些情况下,当内核释放对共享页面的持有权时,它会返回一个完成通知。该通知可能在(已
|
||||
拷贝)数据完全传输之前到达。因此。零拷贝完成通知并不是传输完成通知。
|
||||
|
||||
如果数据不在缓存中,延迟拷贝可能会比立即在系统调用中拷贝开销更大。进程还会因通知处理而产
|
||||
生成本,但却没有带来任何好处。因此,内核会在返回时通过在 ee_code 字段中设置标志
|
||||
SO_EE_CODE_ZEROCOPY_COPIED 来指示数据是否以拷贝的方式完成。进程可以利用这个信号,在
|
||||
同一套接字上后续的请求中停止传递 MSG_ZEROCOPY 标志。
|
||||
|
||||
实现
|
||||
====
|
||||
|
||||
环回
|
||||
----
|
||||
|
||||
对于 TCP 和 UDP:
|
||||
如果接收进程不读取其套接字,发送到本地套接字的数据可能会无限期排队。无限期的通知延迟是不
|
||||
可接受的。因此,所有使用 MSG_ZEROCOPY 生成并环回到本地套接字的数据包都将产生延迟拷贝。
|
||||
这包括环回到数据包套接字(例如,tcpdump)和 tun 设备。
|
||||
|
||||
对于 VSOCK:
|
||||
发送到本地套接字的数据路径与非本地套接字相同。
|
||||
|
||||
测试
|
||||
====
|
||||
|
||||
更具体的示例代码可以在内核源码的 tools/testing/selftests/net/msg_zerocopy.c 中找到。
|
||||
|
||||
要留意环回约束问题。该测试可以在一对主机之间进行。但如果是在本地的一对进程之间运行,例如当使用
|
||||
msg_zerocopy.sh 脚本在跨命名空间的虚拟以太网(veth)对之间运行时,测试将不会显示出任何性能
|
||||
提升。为了便于测试,可以通过让 skb_orphan_frags_rx 与 skb_orphan_frags 相同,来暂时放宽
|
||||
环回限制。
|
||||
|
||||
对于 VSOCK 类型套接字的示例可以在 tools/testing/vsock/vsock_test_zerocopy.c 中找到。
|
||||
@@ -5502,7 +5502,7 @@ F: Documentation/dev-tools/checkpatch.rst
|
||||
|
||||
CHINESE DOCUMENTATION
|
||||
M: Alex Shi <alexs@kernel.org>
|
||||
M: Yanteng Si <siyanteng@loongson.cn>
|
||||
M: Yanteng Si <si.yanteng@linux.dev>
|
||||
R: Dongliang Mu <dzm91@hust.edu.cn>
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/alexs/linux.git
|
||||
S: Maintained
|
||||
|
||||
Reference in New Issue
Block a user