Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,55 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/checktransupdate.rst
:译者: 慕冬亮 Dongliang Mu <dzm91@hust.edu.cn>
检查翻译更新
这个脚本帮助跟踪不同语言的文档翻译状态,即文档是否与对应的英文版本保持更新。
工作原理
------------
它使用 ``git log`` 命令来跟踪翻译提交的最新英文提交(按作者日期排序)和英文文档的
最新提交。如果有任何差异,则该文件被认为是过期的,然后需要更新的提交将被收集并报告。
实现的功能
- 检查特定语言中的所有文件
- 检查单个文件或一组文件
- 提供更改输出格式的选项
- 跟踪没有翻译过的文件的翻译状态
用法
-----
::
tools/docs/checktransupdate.py --help
具体用法请参考参数解析器的输出
示例
- ``tools/docs/checktransupdate.py -l zh_CN``
这将打印 zh_CN 语言中需要更新的所有文件。
- ``tools/docs/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst``
这将只打印指定文件的状态。
然后输出类似如下的内容:
::
Documentation/dev-tools/kfence.rst
No translation in the locale of zh_CN
Documentation/translations/zh_CN/dev-tools/testing-overview.rst
commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs")
1 commits needs resolving in total
待实现的功能
- 文件参数可以是文件夹而不仅仅是单个文件
@@ -0,0 +1,238 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/contributing.rst
:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
如何帮助改进内核文档
====================
在任何软件开发项目中,文档都是重要组成部分。好的文档有助于引入新的开发人员,
并帮助已有的开发人员更有效地工作。如果缺少高质量的文档,大量的时间就会浪费在
代码的逆向工程和犯本可避免的错误上。
不幸的是,内核的文档目前远远不能满足支持如此规模和重要性的项目的需要。
本指南适用于希望帮助改善这种状况的贡献者。内核文档的改进可以由开发者在不同的
技能层级上进行;这也是一条相对简单可以帮助您了解内核过程并在社区中找到一席之
地的路径。下面的大部分内容是文档维护人员列出的最迫切需要完成的任务。
文档待办事项列表
----------------
为了使我们的文档达到应有的水平,需要完成的任务数不胜数。此列表包含许多重要的
项目,但还远远不够详尽;如果您知道改进文档的其他方法,请不要羞于启齿。
消除警告(WARNING)
~~~~~~~~~~~~~~~~~~~
文档构建目前出现了数量惊人的警告。虱子多了不痒,债多了不愁;大伙儿忽略了它们,
他们永远不会注意到他们的工作增加了新的警告。因此,消除警告是文档待办事项列表
中优先级最高的任务之一。这项任务本身相当简单,但必须以正确的方式进行,才能取
得成功。
C代码编译器发出的警告常常会被视为误报,从而导致出现了旨在让编译器闭嘴的补丁。
文档构建中的警告几乎总是指向真正的问题;要消除这些警告,需要理解问题并从源头上
解决问题。因此,修复文档警告的补丁不应在标题中直接写“修复警告”;它们应该指明
真正修复的问题。
另一个重点是,文档警告常常由C代码里kernel-doc注释中的问题引起。虽然文档维护
人员对收到这些修复补丁的副本表示感谢,但是文档树实际上通常并不适合接受这些
补丁;它们应该被交给相关子系统的维护人员。
例如,在一次文档构建中,我几乎是随意选取了一对警告::
./drivers/devfreq/devfreq.c:1818: warning: bad line:
- Resource-managed devfreq_register_notifier()
./drivers/devfreq/devfreq.c:1854: warning: bad line:
- Resource-managed devfreq_unregister_notifier()
(作了断行以便于阅读)
简单看一下上面给出的源文件,会发现几个kernel-doc注释,如下所示::
/**
* devm_devfreq_register_notifier()
- Resource-managed devfreq_register_notifier()
* @dev: The devfreq user device. (parent of devfreq)
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
* @list: DEVFREQ_TRANSITION_NOTIFIER.
*/
问题在于缺了一个“*”,这不符合构建系统对C注释块的格式要求。此问题自2016年注释
被添加以来一直存在——整整四年之久。修复它只需要添加丢失的星号。看一眼该文件的
历史记录以了解主题行的常规格式是什么样,再使用 ``scripts/get_maintainer.pl``
来搞清谁应当收到此补丁。生成的补丁如下所示::
[PATCH] PM / devfreq: Fix two malformed kerneldoc comments
Two kerneldoc comments in devfreq.c fail to adhere to the required format,
resulting in these doc-build warnings:
./drivers/devfreq/devfreq.c:1818: warning: bad line:
- Resource-managed devfreq_register_notifier()
./drivers/devfreq/devfreq.c:1854: warning: bad line:
- Resource-managed devfreq_unregister_notifier()
Add a couple of missing asterisks and make kerneldoc a little happier.
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
---
drivers/devfreq/devfreq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 57f6944d65a6..00c9b80b3d33 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -1814,7 +1814,7 @@ static void devm_devfreq_notifier_release(struct device *dev, void *res)
/**
* devm_devfreq_register_notifier()
- - Resource-managed devfreq_register_notifier()
+ * - Resource-managed devfreq_register_notifier()
* @dev: The devfreq user device. (parent of devfreq)
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
@@ -1850,7 +1850,7 @@ EXPORT_SYMBOL(devm_devfreq_register_notifier);
/**
* devm_devfreq_unregister_notifier()
- - Resource-managed devfreq_unregister_notifier()
+ * - Resource-managed devfreq_unregister_notifier()
* @dev: The devfreq user device. (parent of devfreq)
* @devfreq: The devfreq object.
* @nb: The notifier block to be unregistered.
--
2.24.1
整个过程只花了几分钟。当然,我后来发现有人在另一个树中修复了它,这亮出了另一
个教训:在深入研究问题之前,一定要检查linux-next树,看看问题是否已经修复。
其他修复可能需要更长的时间,尤其是那些与缺少文档的结构体成员或函数参数相关的
修复。这种情况下,需要找出这些成员或参数的作用,并正确描述它们。总之,这种
任务有时会有点乏味,但它非常重要。如果我们真的可以从文档构建中消除警告,那么
我们就可以开始期望开发人员开始注意避免添加新的警告了。
“迷失的”kernel-doc注释
~~~~~~~~~~~~~~~~~~~~~~
开发者被鼓励去为他们的代码写kernel-doc注释,但是许多注释从未被引入文档构建。
这使得这些信息更难找到,例如使Sphinx无法生成指向该文档的链接。将 ``kernel-doc``
指令添加到文档中以引入这些注释可以帮助社区获得为编写注释所做工作的全部价值。
``tools/docs/find-unused-docs.sh`` 工具可以用来找到这些被忽略的评论。
请注意,将导出的函数和数据结构引入文档是最有价值的。许多子系统还具有供内部
使用的kernel-doc注释;除非这些注释放在专门针对相关子系统开发人员的文档中,
否则不应将其引入文档构建中。
修正错字
~~~~~~~~
修复文档中的排版或格式错误是一种快速学习如何创建和发送修补程序的方法,也是
一项有用的服务。我总是愿意接受这样的补丁。这也意味着,一旦你修复了一些这种
错误,请考虑转移到更高级的任务,留下一些拼写错误给下一个初学者解决。
请注意,有些并 **不是** 拼写错误,不应该被“修复”:
- 内核文档中用美式和英式英语拼写皆可,没有必要互相倒换。
- 在内核文档中,没必要讨论句点后面应该跟一个还是两个空格的问题。其他一些有
合理分歧的地方,比如“牛津逗号”,在这也是跑题的。
与对任何项目的任何补丁一样,请考虑您的更改是否真的让事情变得更好。
“上古”文档
~~~~~~~~~~
一些内核文档是最新的、被维护的,并且非常有用,有些文件确并非如此。尘封、陈旧
和不准确的文档可能会误导读者,并对我们的整个文档产生怀疑。任何解决这些问题的
事情都是非常受欢迎的。
无论何时处理文档,请考虑它是否是最新的,是否需要更新,或者是否应该完全删除。
您可以注意以下几个警告标志:
- 对2.x内核的引用
- 指向SourceForge存储库
- 历史记录除了拼写错误啥也没有持续几年
- 讨论Git之前时代的工作流
当然,最好的办法是更新文档,添加所需的任何信息。这样的工作通常需要与熟悉相关
子系统的开发人员合作。当有人善意地询问开发人员,并听取他们的回答然后采取
行动时,开发人员通常更愿意与这些致力于改进文档的人员合作。
有些文档已经没希望了;例如,我们偶尔会发现引用了很久以前从内核中删除的代码的
文档。删除过时的文档会碰见令人惊讶的阻力,但我们无论如何都应该这样做。文档中
多余的粗枝大叶对任何人都没有帮助。
如果一个严重过时的文档中可能有一些有用的信息,而您又无法更新它,那么最好在
开头添加一个警告。建议使用以下文本::
.. warning ::
This document is outdated and in need of attention. Please use
this information with caution, and please consider sending patches
to update it.
这样的话,至少我们长期受苦的读者会得到文件可能会把他们引入歧途的警告。
文档一致性
~~~~~~~~~~
这里的老前辈们会记得上世纪90年代出现在书架上的Linux书籍,它们只是从网上不同
位置搜来的文档文件的集合。在此之后,(大部分)这些书都得到了改进,但是内核的
文档仍然主要是建立在这种模型上。它有数千个文件,几乎每个文件都是与其他文件相
独立编写的。我们没有一个连贯的内核文档;只有数千个独立的文档。
我们一直试图通过编篡一套“书籍”来改善这种情况,以为特定读者提供成套文档。这
包括:
- Documentation/translations/zh_CN/admin-guide/index.rst
- Documentation/core-api/index.rst
- Documentation/driver-api/index.rst
- Documentation/userspace-api/index.rst
以及文档本身这本“书”。
将文档移到适当的书中是一项重要的任务,需要继续进行。不过这项工作还是有一些
挑战性。移动文档会给处理这些文档的人带来短期的痛苦;他们对这些更改无甚热情
也是可以理解的。通常情况下,可以将一个文档移动一下;不过我们真的不想一直移动
它们。
即使所有文件都在正确的位置,我们也只是把一大堆文件变成一群小堆文件。试图将
所有这些文件组合成一个整体的工作尚未开始。如果你对如何在这方面取得进展有好的
想法,我们将很高兴了解。
样式表(Stylesheet)改进
~~~~~~~~~~~~~~~~~~~~~~~~
随着Sphinx的采用,我们得到了比以前更好的HTML输出。但它仍然需要很大的改进;
Donald Knuth和Edward Tufte可能是映像平平的。这需要调整我们的样式表,以创建
更具排版效果、可访问性和可读性的输出。
请注意:如果你承担这个任务,你将进入经典的两难领域。即使是相对明显的变化,
也会有很多意见和讨论。唉,这就是我们生活的世界的本质。
无LaTeX的PDF构建
~~~~~~~~~~~~~~~~
对于拥有大量时间和Python技能的人来说,这绝对是一项不平凡的任务。Sphinx工具链
相对较小且包含良好;很容易添加到开发系统中。但是构建PDF或EPUB输出需要安装
LaTeX,它绝对称不上小或包含良好的。消除Latex将是一件很好的事情。
最初是希望使用 `rst2pdf <https://rst2pdf.org/>`_ 工具来生成PDF,但结果发现
无法胜任这项任务。不过rst2pdf的开发工作最近似乎又有了起色,这是个充满希望的
迹象。如果有开发人员愿意与该项目合作,使rst2pdf可与内核文档构建一起工作,
大家会非常感激。
编写更多文档
~~~~~~~~~~~~
当然,内核中许多部分的文档严重不足。如果您有编写一个特定内核子系统文档的相应
知识并愿意这样做,请不要犹豫,编写并向内核贡献结果吧!数不清的内核开发人员和
用户会感谢你。
@@ -0,0 +1,28 @@
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/index.rst
:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
.. _doc_guide_zh:
================
如何编写内核文档
================
.. toctree::
:maxdepth: 1
sphinx
kernel-doc
parse-headers
contributing
maintainer-profile
checktransupdate
.. only:: subproject and html
目录
====
* :ref:`genindex`
@@ -0,0 +1,499 @@
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/kernel-doc.rst
:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
编写kernel-doc注释
==================
Linux内核源文件可以包含kernel-doc格式的结构化文档注释,用以描述代码的函数、
类型和设计。将文档嵌入源文件更容易保持文档最新。
.. note:: 内核文档格式与javadoc、gtk-doc或Doxygen看似很相似,但由于历史原因,
实际有着明显的不同。内核源包含成千上万个kernel-doc注释。请坚持遵循
此处描述的风格。
.. note:: kernel-doc无法包含Rust代码:请参考 Documentation/rust/general-information.rst 。
从注释中提取kernel-doc结构,并从中生成适当的 `Sphinx C 域`_ 函数和带有锚点的
类型描述。这些注释将被过滤以生成特殊kernel-doc高亮和交叉引用。详见下文。
.. _Sphinx C 域: http://www.sphinx-doc.org/en/stable/domains.html
使用 ``EXPORT_SYMBOL`` 或 ``EXPORT_SYMBOL_GPL`` 导出到可加载模块的每个函数都
应该有一个kernel-doc注释。模块使用的头文件中的函数和数据结构也应该有
kernel-doc注释。
对于其他内核文件(未标记为 ``static`` )中外部可见的函数,提供kernel-doc格式
的文档是一个很好的实践。我们也建议为私有(文件 ``static`` )程序提供kernel-doc
格式的文档,以确保内核源代码布局的一致性。此建议优先级较低,由内核源文件的
维护者自行决定。
如何格式化kernel-doc注释
------------------------
kernel-doc注释用 ``/**`` 作为开始标记。 ``kernel-doc`` 工具将提取以这种方式
标记的注释。注释其余部分的格式类似于一个普通的多行注释,左侧有一列星号,以
``*/`` 行结束。
函数和类型的kernel-doc注释应该放在所描述的函数或类型之前,以便最大限度地提高
更改代码的人同时更改文档的可能性。概述kernel-doc注释可以放在最顶部的任何地方。
用详细模式和不生成实际输出来运行 ``kernel-doc`` 工具,可以验证文档注释的格式
是否正确。例如::
tools/docs/kernel-doc -v -none drivers/foo/bar.c
当请求执行额外的gcc检查时,内核构建将验证文档格式::
make W=n
函数文档
--------
函数和函数式宏的kernel-doc注释的一般格式是::
/**
* 函数名() - 函数简要说明.
* @参数1: 描述第一个参数.
* @参数2: 描述第二个参数.
* 可以为参数提供一段
* 多行描述.
*
* 更详细的描述,进一步讨论函数 函数名(), 这可能对使用或修改它的人有用.
* 以空注释行开始, 内部可以包含空注释行.
*
* 详细描述可以有多个段落.
*
* Context: 描述函数是否可以休眠, 它需要、释放或期望持有什么锁.
* 可以写多行.
* Return: 描述函数返回值.
*
* 返回值描述也可以有多个段落,
* 并且应该放在注释块的末尾.
*/
函数名后面的简短描述可以跨多行,并以参数描述、空注释行或注释块结尾结束。
函数参数
~~~~~~~~
每个函数参数都应该按照顺序描述,紧跟在函数简要说明之后。不要在函数描述和参数
之间,也不要在参数之间留空。
每个 ``@参数:`` 描述可以跨多行。
.. note::
如果 ``@参数`` 描述有多行,则说明的续行应该从上一行的同一列开始::
* @参数: 较长说明
* 的续行
或::
* @参数:
* 较长说明
* 的续行
如果函数的参数数目可变,则需用kernel-doc格式对其进行描述::
* @...: 描述
函数上下文
~~~~~~~~~~
可调用函数的上下文应该在 ``Context`` 节中描述。此节应该包括函数是休眠的还是
可以从中断上下文调用的,以及它需要什么锁、释放什么锁和期望它的调用者持有什么
锁。
例如::
* Context: Any context.
* Context: Any context. Takes and releases the RCU lock.
* Context: Any context. Expects <lock> to be held by caller.
* Context: Process context. May sleep if @gfp flags permit.
* Context: Process context. Takes and releases <mutex>.
* Context: Softirq or process context. Takes and releases <lock>, BH-safe.
* Context: Interrupt context.
返回值
~~~~~~
如有返回值,应在 ``Return`` 节中描述。
.. note::
#) 您提供的多行描述文本 *不会* 识别换行符,因此如果您想将某些文本预格式化,
如::
* Return:
* 0 - OK
* -EINVAL - invalid argument
* -ENOMEM - out of memory
它们在最终文档中变成一行::
Return: 0 - OK -EINVAL - invalid argument -ENOMEM - out of memory
因此,为了在需要的地方换行,您需要使用ReST列表,例如::
* Return:
* * 0 - OK to runtime suspend the device
* * -EBUSY - Device should not be runtime suspended
#) 如果您提供的描述性文本中的行以某个后跟冒号的短语开头,则每一个这种短语
都将被视为新的节标题,可能会产生意料不到的效果。
结构体、共用体、枚举类型文档
----------------------------
结构体(struct)、共用体(union)、枚举(enum)类型kernel-doc注释的一般格式为::
/**
* struct 结构体名 - 简要描述.
* @成员1: 成员1描述.
* @成员2: 成员2描述.
* 可以为成员提供
* 多行描述.
*
* 结构体的描述.
*/
可以用 ``union`` 或 ``enum`` 替换上面示例中的 ``struct`` ,以描述共用体或枚举。
``成员`` 用于表示枚举中的元素或共用体成员。
结构体名称后面的简要说明可以跨多行,并以成员说明、空白注释行或注释块结尾结束。
成员
~~~~
结构体、共用体和枚举的成员应以与函数参数相同的方式记录;它们后紧跟简短的描述,
并且为多行。
在结构体或共用体描述中,可以使用 ``private:`` 和 ``public:`` 注释标签。
``private:`` 域内的字段不会列在生成的文档中。
``private:`` 和 ``public:`` 标签必须紧跟在 ``/*`` 注释标记之后。可以选择是否
在 ``:`` 和 ``*/`` 结束标记之间包含注释。
例子::
/**
* struct 张三 - 简短描述
* @a: 第一个成员
* @b: 第二个成员
* @d: 第三个成员
*
* 详细描述
*/
struct 张三 {
int a;
int b;
/* private: 仅内部使用 */
int c;
/* public: 下一个是公有的 */
int d;
};
嵌套的结构体/共用体
~~~~~~~~~~~~~~~~~~~
嵌套的结构体/共用体可像这样记录::
/**
* struct nested_foobar - a struct with nested unions and structs
* @memb1: first member of anonymous union/anonymous struct
* @memb2: second member of anonymous union/anonymous struct
* @memb3: third member of anonymous union/anonymous struct
* @memb4: fourth member of anonymous union/anonymous struct
* @bar: non-anonymous union
* @bar.st1: struct st1 inside @bar
* @bar.st2: struct st2 inside @bar
* @bar.st1.memb1: first member of struct st1 on union bar
* @bar.st1.memb2: second member of struct st1 on union bar
* @bar.st2.memb1: first member of struct st2 on union bar
* @bar.st2.memb2: second member of struct st2 on union bar
*/
struct nested_foobar {
/* Anonymous union/struct*/
union {
struct {
int memb1;
int memb2;
};
struct {
void *memb3;
int memb4;
};
};
union {
struct {
int memb1;
int memb2;
} st1;
struct {
void *memb1;
int memb2;
} st2;
} bar;
};
.. note::
#) 在记录嵌套结构体或共用体时,如果结构体/共用体 ``张三`` 已命名,则其中
的成员 ``李四`` 应记录为 ``@张三.李四:``
#) 当嵌套结构体/共用体是匿名的时,其中的成员 ``李四`` 应记录为 ``@李四:``
行间注释文档
~~~~~~~~~~~~
结构成员也可在定义时以行间注释形式记录。有两种样式,一种是单行注释,其中开始
``/**`` 和结束 ``*/`` 位于同一行;另一种是多行注释,开头结尾各自位于一行,就
像所有其他核心文档注释一样::
/**
* struct 张三 - 简短描述.
* @张三: 成员张三.
*/
struct 张三 {
int 张三;
/**
* @李四: 成员李四.
*/
int 李四;
/**
* @王五: 成员王五.
*
* 此处,成员描述可以为好几段.
*/
int 王五;
union {
/** @儿子: 单行描述. */
int 儿子;
};
/** @赵六: 描述@张三里面的结构体@赵六 */
struct {
/**
* @赵六.女儿: 描述@张三.赵六里面的@女儿
*/
int 女儿;
} 赵六;
};
Typedef文档
-----------
Typedef的kernel-doc文档注释的一般格式为::
/**
* typedef 类型名称 - 简短描述.
*
* 类型描述.
*/
还可以记录带有函数原型的typedef::
/**
* typedef 类型名称 - 简短描述.
* @参数1: 参数1的描述
* @参数2: 参数2的描述
*
* 类型描述.
*
* Context: 锁(Locking)上下文.
* Return: 返回值的意义.
*/
typedef void (*类型名称)(struct v4l2_ctrl *参数1, void *参数2);
高亮与交叉引用
--------------
在kernel-doc注释的描述文本中可以识别以下特殊模式,并将其转换为正确的
reStructuredText标记和 `Sphinx C 域`_ 引用。
.. attention:: 以下内容 **仅** 在kernel-doc注释中识别, **不会** 在普通的
reStructuredText文档中识别。
``funcname()``
函数引用。
``@parameter``
函数参数的名称(未交叉引用,仅格式化)。
``%CONST``
常量的名称(未交叉引用,仅格式化)。
````literal````
预格式化文本块。输出将使用等距字体。
若你需要使用在kernel-doc脚本或reStructuredText中有特殊含义的字符,则此功能
非常有用。
若你需要在函数描述中使用类似于 ``%ph`` 的东西,这特别有用。
``$ENVVAR``
环境变量名称(未交叉引用,仅格式化)。
``&struct name``
结构体引用。
``&enum name``
枚举引用。
``&typedef name``
Typedef引用。
``&struct_name->member`` or ``&struct_name.member``
结构体或共用体成员引用。交叉引用将链接到结构体或共用体定义,而不是直接到成员。
``&name``
泛类型引用。请首选上面描述的完整引用方式。此法主要是为了可能未描述的注释。
从reStructuredText交叉引用
~~~~~~~~~~~~~~~~~~~~~~~~~~
无需额外的语法来从reStructuredText文档交叉引用kernel-do注释中定义的函数和类型。
只需以 ``()`` 结束函数名,并在类型之前写上 ``struct`` , ``union`` , ``enum``
或 ``typedef`` 。
例如::
See foo().
See struct foo.
See union bar.
See enum baz.
See typedef meh.
若要在交叉引用链接中使用自定义文本,可以通过以下语法进行::
See :c:func:`my custom link text for function foo <foo>`.
See :c:type:`my custom link text for struct bar <bar>`.
有关更多详细信息,请参阅 `Sphinx C 域`_ 文档。
总述性文档注释
--------------
为了促进源代码和注释紧密联合,可以将kernel-doc文档块作为自由形式的注释,而
不是函数、结构、联合、枚举或typedef的绑定kernel-doc。例如,这可以用于解释
驱动程序或库代码的操作理论。
这是通过使用带有节标题的 ``DOC:`` 节关键字来实现的。
总述或高层级文档注释的一般格式为::
/**
* DOC: Theory of Operation
*
* The whizbang foobar is a dilly of a gizmo. It can do whatever you
* want it to do, at any time. It reads your mind. Here's how it works.
*
* foo bar splat
*
* The only drawback to this gizmo is that is can sometimes damage
* hardware, software, or its subject(s).
*/
``DOC:`` 后面的标题用作源文件中的标题,但也用作提取文档注释的标识符。因此,
文件中的标题必须是唯一的。
包含kernel-doc注释
==================
文档注释可以被包含在任何使用专用kernel-doc Sphinx指令扩展的reStructuredText
文档中。
kernel-doc指令的格式如下::
.. kernel-doc:: source
:option:
*source* 是相对于内核源代码树的源文件路径。
支持以下指令选项:
export: *[source-pattern ...]*
包括 *source* 中使用 ``EXPORT_SYMBOL`` 或 ``EXPORT_SYMBOL_GPL`` 导出的所有
函数的文档,无论是在 *source* 中还是在 *source-pattern* 指定的任何文件中。
当kernel-doc注释被放置在头文件中,而 ``EXPORT_SYMBOL`` 和 ``EXPORT_SYMBOL_GPL``
位于函数定义旁边时, *source-pattern* 非常有用。
例子::
.. kernel-doc:: lib/bitmap.c
:export:
.. kernel-doc:: include/net/mac80211.h
:export: net/mac80211/*.c
internal: *[source-pattern ...]*
包括 *source* 中所有在 *source* 或 *source-pattern* 的任何文件中都没有使用
``EXPORT_SYMBOL`` 或 ``EXPORT_SYMBOL_GPL`` 导出的函数和类型的文档。
例子::
.. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
:internal:
identifiers: *[ function/type ...]*
在 *source* 中包含每个 *function* 和 *type* 的文档。如果没有指定 *function* ,
则 *source* 中所有函数和类型的文档都将包含在内。
例子::
.. kernel-doc:: lib/bitmap.c
:identifiers: bitmap_parselist bitmap_parselist_user
.. kernel-doc:: lib/idr.c
:identifiers:
no-identifiers: *[ function/type ...]*
排除 *source* 中所有 *function* 和 *type* 的文档。
例子::
.. kernel-doc:: lib/bitmap.c
:no-identifiers: bitmap_parselist
functions: *[ function/type ...]*
这是“identifiers”指令的别名,已弃用。
doc: *title*
包含 *source* 中由 *title* 标题标识的 ``DOC:`` 文档段落。 *title* 中允许
空格;不要在 *title* 上加引号。 *title* 仅用作段落的标识符,不包含在输出中。
请确保在所附的reStructuredText文档中有适当的标题。
例子::
.. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
:doc: High Definition Audio over HDMI and Display Port
如果没有选项,kernel-doc指令将包含源文件中的所有文档注释。
kernel-doc扩展包含在内核源代码树中,位于 ``Documentation/sphinx/kerneldoc.py`` 。
在内部,它使用 ``tools/docs/kernel-doc`` 脚本从源代码中提取文档注释。
.. _kernel_doc_zh:
如何使用kernel-doc生成手册(man)页
-----------------------------------
如果您只想使用kernel-doc生成手册页,可以从内核git树这样做::
$ tools/docs/kernel-doc -man \
$(git grep -l '/\*\*' -- :^Documentation :^tools) \
| scripts/split-man.pl /tmp/man
一些旧版本的git不支持路径排除语法的某些变体。
以下命令之一可能适用于这些版本::
$ tools/docs/kernel-doc -man \
$(git grep -l '/\*\*' -- . ':!Documentation' ':!tools') \
| scripts/split-man.pl /tmp/man
$ tools/docs/kernel-doc -man \
$(git grep -l '/\*\*' -- . ":(exclude)Documentation" ":(exclude)tools") \
| scripts/split-man.pl /tmp/man
@@ -0,0 +1,43 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/maintainer-profile.rst
:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
文档子系统维护人员条目概述
==========================
文档“子系统”是内核文档和相关基础设施的中心协调点。它涵盖了 Documentation/ 下
的文件层级(Documentation/devicetree 除外)、scripts/ 下的各种实用程序,并且
在某些情况下的也包括 LICENSES/ 。
不过值得注意的是,这个子系统的边界比通常更加模糊。许多其他子系统维护人员需要
保持对 Documentation/ 某些部分的控制,以便于可以更自由地做更改。除此之外,
许多内核文档都以kernel-doc注释的形式出现在源代码中;这些注释通常(但不总是)
由相关的子系统维护人员维护。
文档子系统的邮件列表是<linux-doc@vger.kernel.org>。
补丁应尽量针对docs-next树。
提交检查单补遗
--------------
在进行文档更改时,您应当构建文档以测试,并确保没有引入新的错误或警告。生成
HTML文档并查看结果将有助于避免对文档渲染结果的不必要争执。
开发周期的关键节点
------------------
补丁可以随时发送,但在合并窗口期间,响应将比通常慢。文档树往往在合并窗口打开
之前关闭得比较晚,因为文档补丁导致回归的风险很小。
审阅节奏
--------
我(译注:指Jonathan Corbet <corbet@lwn.net>)是文档子系统的唯一维护者,我在
自己的时间里完成这项工作,所以对补丁的响应有时会很慢。当补丁被合并时(或当我
决定拒绝合并补丁时),我都会发送通知。如果您在发送补丁后一周内没有收到回复,
请不要犹豫,发送提醒就好。
@@ -0,0 +1,187 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/parse-headers.rst
:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
=====================
包含用户空间API头文件
=====================
有时,为了描述用户空间API并在代码和文档之间生成交叉引用,需要包含头文件和示例
C代码。为用户空间API文件添加交叉引用还有一个好处:如果在文档中找不到相应符号,
Sphinx将生成警告。这有助于保持用户空间API文档与内核更改同步。
:ref:`parse_headers.py <parse_headers_zh>` 提供了生成此类交叉引用的一种方法。
在构建文档时,必须通过Makefile调用它。有关如何在内核树中使用它的示例,请参阅
``Documentation/userspace-api/media/Makefile`` 。
.. _parse_headers_zh:
parse_headers.py
----------------
脚本名称
~~~~~~~~
parse_headers.py——解析一个C文件,识别函数、结构体、枚举、定义并对Sphinx文档
创建交叉引用。
用法概要
~~~~~~~~
\ **parse_headers.py**\ [<选项>] <C文件> <输出文件> [<例外文件>]
<选项> 可以是: --debug, --help 或 --usage 。
选项
~~~~
\ **--debug**\
开启脚本详细模式,在调试时很有用。
\ **--usage**\
打印简短的帮助信息并退出。
\ **--help**\
打印更详细的帮助信息并退出。
说明
~~~~
通过C头文件或源文件(<C文件>)中为描述API的文档编写的带交叉引用的 ..预格式化
文本 块将文件转换成重构文本(RST)。它接受一个可选的<例外文件>,其中描述了
哪些元素将被忽略或指向非默认引用。
输出被写入到<输出文件>。
它能够识别定义、函数、结构体、typedef、枚举和枚举符号,并为它们创建交叉引用。
它还能够区分用于指定Linux ioctl的 ``#define`` 。
<例外文件> 包含两种类型的语句: \ **ignore**\ 或 \ **replace**\ .
ignore标记的语法为:
ignore \ **type**\ \ **name**\
The \ **ignore**\ 意味着它不会为类型为 \ **type**\ 的 \ **name**\ 符号生成
交叉引用。
replace标记的语法为:
replace \ **type**\ \ **name**\ \ **new_value**\
The \ **replace**\ 味着它将为 \ **type**\ 类型的 \ **name**\ 符号生成交叉引
用,但是它将使用 \ **new_value**\ 来取代默认的替换规则。
这两种语句中, \ **type**\ 可以是以下任一项:
\ **ioctl**\
ignore 或 replace 语句应用于ioctl定义,如:
#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
\ **define**\
ignore 或 replace 语句应用于在<C文件>中找到的任何其他 ``#define`` 。
\ **typedef**\
ignore 和 replace 语句应用于<C文件>中的typedef语句。
\ **struct**\
ignore 和 replace 语句应用于<C文件>中的结构体名称语句。
\ **enum**\
ignore 和 replace 语句应用于<C文件>中的枚举名称语句。
\ **symbol**\
ignore 和 replace 语句应用于<C文件>中的枚举值名称语句。
replace语句中, \ **new_value**\ 会自动使用 \ **typedef**\ , \ **enum**\
和 \ **struct**\ 类型的 :c:type: 引用;以及 \ **ioctl**\ , \ **define**\ 和
\ **symbol**\ 类型的 :ref: 。引用的类型也可以在replace语句中显式定义。
示例
~~~~
ignore define _VIDEODEV2_H
忽略<C文件>中的 #define _VIDEODEV2_H 。
ignore symbol PRIVATE
如下结构体:
enum foo { BAR1, BAR2, PRIVATE };
不会为 \ **PRIVATE**\ 生成交叉引用。
replace symbol BAR1 :c:type:\`foo\`
replace symbol BAR2 :c:type:\`foo\`
如下结构体:
enum foo { BAR1, BAR2, PRIVATE };
它会让BAR1和BAR2枚举符号交叉引用C域中的foo符号。
缺陷
~~~~
请向Mauro Carvalho Chehab <mchehab@kernel.org>报告有关缺陷。
中文翻译问题请找中文翻译维护者。
版权
~~~~
版权所有 (c) 2016 Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
许可证 GPLv2:GNU GPL version 2 <https://gnu.org/licenses/gpl.html>
这是自由软件:你可以自由地修改和重新发布它。
在法律允许的范围内,**不提供任何保证**。
@@ -0,0 +1,412 @@
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/doc-guide/sphinx.rst
:译者: 吴想成 Wu XiangCheng <bobwxc@email.cn>
.. _sphinxdoc_zh:
简介
====
Linux内核使用 `Sphinx <http://www.sphinx-doc.org/>`_ 来把 ``Documentation``
下的 `reStructuredText <http://docutils.sourceforge.net/rst.html>`_ 文件转
换成漂亮的文档。使用 ``make htmldocs`` 或 ``make pdfdocs`` 命令即可构建HTML
或PDF格式的文档。生成的文档放在 ``Documentation/output`` 文件夹中。
reStructuredText文件可能包含包含来自源文件的结构化文档注释或kernel-doc注释。
通常它们用于描述代码的功能、类型和设计。kernel-doc注释有一些特殊的结构和
格式,但除此之外,它们还被作为reStructuredText处理。
最后,有成千上万的纯文本文档文件散布在 ``Documentation`` 里。随着时间推移,
其中一些可能会转换为reStructuredText,但其中大部分仍保持纯文本。
.. _sphinx_install_zh:
安装Sphinx
==========
Documentation/ 下的ReST文件现在使用sphinx1.7或更高版本构建。
这有一个脚本可以检查Sphinx的依赖项。更多详细信息见
:ref:`sphinx-pre-install_zh` 。
大多数发行版都附带了Sphinx,但是它的工具链比较脆弱,而且在您的机器上升级它
或其他一些Python包导致文档构建中断的情况并不少见。
避免此情况的一种方法是使用与发行版附带的不同的版本。因此,建议使用
``virtualenv-3`` 或 ``virtualenv`` 在虚拟环境中安装Sphinx,具体取决于发行版
如何打包Python3。
.. note::
#) html输出建议使用RTD主题。根据Sphinx版本的不同,它应该用
``pip install sphinx_rtd_theme`` 单独安装。
#) 一些ReST页面包含数学表达式。由于Sphinx的工作方式,这些表达式是使用 LaTeX
编写的。它需要安装amsfonts和amsmath宏包,以便显示。
总之,如您要安装Sphinx 2.4.4版本,应执行::
$ virtualenv sphinx_2.4.4
$ . sphinx_2.4.4/bin/activate
(sphinx_2.4.4) $ pip install -r Documentation/sphinx/requirements.txt
在运行 ``. sphinx_2.4.4/bin/activate`` 之后,提示符将变化,以指示您正在使用新
环境。如果您打开了一个新的shell,那么在构建文档之前,您需要重新运行此命令以再
次进入虚拟环境中。
图片输出
--------
内核文档构建系统包含一个扩展,可以处理GraphViz和SVG格式的图像(参见
:ref:`sphinx_kfigure_zh` )。
为了让它工作,您需要同时安装GraphViz和ImageMagick包。如果没有安装这些软件包,
构建系统仍将构建文档,但不会在输出中包含任何图像。
PDF和LaTeX构建
--------------
目前只有Sphinx 2.4及更高版本才支持这种构建。
对于PDF和LaTeX输出,还需要 ``XeLaTeX`` 3.14159265版本。(译注:此版本号真实
存在)
根据发行版的不同,您可能还需要安装一系列 ``texlive`` 软件包,这些软件包提供了
``XeLaTeX`` 工作所需的最小功能集。
.. _sphinx-pre-install_zh:
检查Sphinx依赖项
----------------
这有一个脚本可以自动检查Sphinx依赖项。如果它认得您的发行版,还会提示您所用发行
版的安装命令::
$ ./tools/docs/sphinx-pre-install
Checking if the needed tools for Fedora release 26 (Twenty Six) are available
Warning: better to also install "texlive-luatex85".
You should run:
sudo dnf install -y texlive-luatex85
/usr/bin/virtualenv sphinx_2.4.4
. sphinx_2.4.4/bin/activate
pip install -r Documentation/sphinx/requirements.txt
Can't build as 1 mandatory dependency is missing at ./tools/docs/sphinx-pre-install line 468.
默认情况下,它会检查html和PDF的所有依赖项,包括图像、数学表达式和LaTeX构建的
需求,并假设将使用虚拟Python环境。html构建所需的依赖项被认为是必需的,其他依
赖项则是可选的。
它支持两个可选参数:
``--no-pdf``
禁用PDF检查;
``--no-virtualenv``
使用Sphinx的系统打包,而不是Python虚拟环境。
Sphinx构建
==========
生成文档的常用方法是运行 ``make htmldocs`` 或 ``make pdfdocs`` 。还有其它可用
的格式:请参阅 ``make help`` 的文档部分。生成的文档放在 ``Documentation/output``
下相应格式的子目录中。
要生成文档,显然必须安装Sphinx( ``sphinx-build`` )。要让HTML输出更漂亮,可以
使用Read the Docs Sphinx主题( ``sphinx_rtd_theme`` )。对于PDF输出,您还需要
``XeLaTeX`` 和来自ImageMagick(https://www.imagemagick.org)的 ``convert(1)`` 。
所有这些软件在大多发行版中都可用或已打包。
要传递额外的选项给Sphinx,可以使用make变量 ``SPHINXOPTS`` 。例如,使用
``make SPHINXOPTS=-v htmldocs`` 获得更详细的输出。
要删除生成的文档,请运行 ``make cleandocs`` 。
编写文档
========
添加新文档很容易,只需:
1. 在 ``Documentation`` 下某处添加一个新的 ``.rst`` 文件。
2. 从 ``Documentation/index.rst`` 中的Sphinx `主目录树`_ 链接到它。
.. _主目录树: http://www.sphinx-doc.org/en/stable/markup/toctree.html
对于简单的文档(比如您现在正在阅读的文档),这通常已经足够好了,但是对于较大
的文档,最好创建一个子目录(或者使用现有的子目录)。例如,图形子系统文档位于
``Documentation/gpu`` 下,拆分为多个 ``.rst`` 文件,并具有从主目录链接来的单
独索引 ``index.rst`` (有自己的目录树 ``toctree`` )。
请参阅 `Sphinx <http://www.sphinx-doc.org/>`_ 和 `reStructuredText
<http://docutils.sourceforge.net/rst.html>`_ 的文档,以了解如何使用它们。
特别是Sphinx `reStructuredText 基础`_ 这是开始学习使用reStructuredText的
好地方。还有一些 `Sphinx 特殊标记结构`_ 。
.. _reStructuredText 基础: http://www.sphinx-doc.org/en/stable/rest.html
.. _Sphinx 特殊标记结构: http://www.sphinx-doc.org/en/stable/markup/index.html
内核文档的具体指南
------------------
这是一些内核文档的具体指南:
* 请不要过于痴迷转换格式到reStructuredText。保持简单。在大多数情况下,文档
应该是纯文本,格式应足够一致,以便可以转换为其他格式。
* 将现有文档转换为reStructuredText时,请尽量减少格式更改。
* 在转换文档时,还要更新内容,而不仅仅是格式。
* 请遵循标题修饰符的顺序:
1. ``=`` 文档标题,要有上线::
========
文档标题
========
2. ``=`` 章::
章标题
======
3. ``-`` 节::
节标题
------
4. ``~`` 小节::
小节标题
~~~~~~~~
尽管RST没有规定具体的顺序(“没有强加一个固定数量和顺序的节标题装饰风格,最终
按照的顺序将是实际遇到的顺序。”),但是拥有一个通用级别的文档更容易遵循。
* 对于插入固定宽度的文本块(用于代码样例、用例等): ``::`` 用于语法高亮意义不
大的内容,尤其是短代码段; ``.. code-block:: <language>`` 用于需要语法高亮的
较长代码块。对于嵌入到文本中的简短代码片段,请使用 \`\` 。
C域
---
**Sphinx C域(Domain)** (name c)适用于C API文档。例如,函数原型:
.. code-block:: rst
.. c:function:: int ioctl( int fd, int request )
内核文档的C域有一些附加特性。例如,您可以使用诸如 ``open`` 或 ``ioctl`` 这样的
通用名称重命名函数的引用名称:
.. code-block:: rst
.. c:function:: int ioctl( int fd, int request )
:name: VIDIOC_LOG_STATUS
函数名称(例如ioctl)仍保留在输出中,但引用名称从 ``ioctl`` 变为
``VIDIOC_LOG_STATUS`` 。此函数的索引项也变为 ``VIDIOC_LOG_STATUS`` 。
请注意,不需要使用 ``c:func:`` 生成函数文档的交叉引用。由于一些Sphinx扩展的
神奇力量,如果给定函数名的索引项存在,文档构建系统会自动将对 ``function()``
的引用转换为交叉引用。如果在内核文档中看到 ``c:func:`` 的用法,请删除它。
列表
----
我们建议使用 *列式表* 格式。 *列式表* 格式是二级列表。与ASCII艺术相比,它们对
文本文件的读者来说可能没有那么舒适。但其优点是易于创建或修改,而且修改的差异
(diff)更有意义,因为差异仅限于修改的内容。
*平铺表* 也是一个二级列表,类似于 *列式表* ,但具有一些额外特性:
* 列范围:使用 ``cspan`` 修饰,可以通过其他列扩展单元格
* 行范围:使用 ``rspan`` 修饰,可以通过其他行扩展单元格
* 自动将表格行最右边的单元格扩展到该行右侧空缺的单元格上。若使用
``:fill-cells:`` 选项,此行为可以从 *自动合并* 更改为 *自动插入* ,自动
插入(空)单元格,而不是扩展合并到最后一个单元格。
选项:
* ``:header-rows:`` [int] 标题行计数
* ``:stub-columns:`` [int] 标题列计数
* ``:widths:`` [[int] [int] ... ] 列宽
* ``:fill-cells:`` 插入缺少的单元格,而不是自动合并缺少的单元格
修饰:
* ``:cspan:`` [int] 扩展列
* ``:rspan:`` [int] 扩展行
下面的例子演示了如何使用这些标记。分级列表的第一级是 *表格行* 。 *表格行* 中
只允许一个标记,即该 *表格行* 中的单元格列表。 *comments* ( ``..`` )和
*targets* 例外(例如引用 ``:ref:`最后一行 <last row_zh>``` / :ref:`最后一行
<last row_zh>` )。
.. code-block:: rst
.. flat-table:: 表格标题
:widths: 2 1 1 3
* - 表头 列1
- 表头 列2
- 表头 列3
- 表头 列4
* - 行1
- 字段1.1
- 字段1.2(自动扩展)
* - 行2
- 字段2.1
- :rspan:`1` :cspan:`1` 字段2.2~3.3
* .. _`last row_zh`:
- 行3
渲染效果:
.. flat-table:: 表格标题
:widths: 2 1 1 3
* - 表头 列1
- 表头 列2
- 表头 列3
- 表头 列4
* - 行1
- 字段1.1
- 字段1.2(自动扩展)
* - 行2
- 字段2.1
- :rspan:`1` :cspan:`1` 字段2.2~3.3
* .. _`last row_zh`:
- 行3
交叉引用
--------
从一页文档到另一页文档的交叉引用可以通过简单地写出文件路径来完成,无特殊格式
要求。路径可以是绝对路径或相对路径。绝对路径从“Documentation/”开始。例如,要
交叉引用此页,以下写法皆可,取决于具体的文档目录(注意 ``.rst`` 扩展名是可选
的)::
参见 Documentation/doc-guide/sphinx.rst 。此法始终可用。
请查看 sphinx.rst ,仅在同级目录中有效。
请阅读 ../sphinx.rst ,上级目录中的文件。
如果要使用相对路径,则需要使用Sphinx的 ``doc`` 修饰。例如,从同一目录引用此页
的操作如下::
参见 :doc:`sphinx文档的自定义链接文本 <sphinx>`.
对于大多数用例,前者是首选,因为它更干净,更适合阅读源文件的人。如果您遇到一
个没有任何特殊作用的 ``:doc:`` 用法,请将其转换为文档路径。
有关交叉引用kernel-doc函数或类型的信息,请参阅
Documentation/doc-guide/kernel-doc.rst 。
.. _sphinx_kfigure_zh:
图形图片
========
如果要添加图片,应该使用 ``kernel-figure`` 和 ``kernel-image`` 指令。例如,
要插入具有可缩放图像格式的图形,请使用SVG(:ref:`svg_image_example_zh` )::
.. kernel-figure:: ../../../doc-guide/svg_image.svg
:alt: 简易 SVG 图片
SVG 图片示例
.. _svg_image_example_zh:
.. kernel-figure:: ../../../doc-guide/svg_image.svg
:alt: 简易 SVG 图片
SVG 图片示例
内核figure(和image)指令支持 DOT 格式文件,请参阅
* DOT:http://graphviz.org/pdf/dotguide.pdf
* Graphviz:http://www.graphviz.org/content/dot-language
一个简单的例子(:ref:`hello_dot_file_zh` )::
.. kernel-figure:: ../../../doc-guide/hello.dot
:alt: 你好,世界
DOT 示例
.. _hello_dot_file_zh:
.. kernel-figure:: ../../../doc-guide/hello.dot
:alt: 你好,世界
DOT 示例
嵌入的渲染标记(或语言),如Graphviz的 **DOT** 由 ``kernel-render`` 指令提供::
.. kernel-render:: DOT
:alt: 有向图
:caption: 嵌入式 **DOT** (Graphviz) 代码
digraph foo {
"五棵松" -> "国贸";
}
如何渲染取决于安装的工具。如果安装了Graphviz,您将看到一个矢量图像。否则,原始
标记将作为 *文字块* 插入(:ref:`hello_dot_render_zh` )。
.. _hello_dot_render_zh:
.. kernel-render:: DOT
:alt: 有向图
:caption: 嵌入式 **DOT** (Graphviz) 代码
digraph foo {
"五棵松" -> "国贸";
}
*render* 指令包含 *figure* 指令中已知的所有选项,以及选项 ``caption`` 。如果
``caption`` 有值,则插入一个 *figure* 节点,若无,则插入一个 *image* 节点。
如果您想引用它,还需要一个 ``caption`` (:ref:`hello_svg_render_zh` )。
嵌入式 **SVG**::
.. kernel-render:: SVG
:caption: 嵌入式 **SVG** 标记
:alt: 右上箭头
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" ...>
...
</svg>
.. _hello_svg_render_zh:
.. kernel-render:: SVG
:caption: 嵌入式 **SVG** 标记
:alt: 右上箭头
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1" baseProfile="full" width="70px" height="40px" viewBox="0 0 700 400">
<line x1="180" y1="370" x2="500" y2="50" stroke="black" stroke-width="15px"/>
<polygon points="585 0 525 25 585 50" transform="rotate(135 525 25)"/>
</svg>