![自研操作系统:DIM-SUM设计与实现](https://wfqqreader-1252317822.image.myqcloud.com/cover/128/47379128/b_47379128.jpg)
1.5 向DIM-SUM操作系统提交补丁
想修改DIM-SUM的代码,并把它合入DIM-SUM的Git仓库吗?试着给DIM-SUM操作系统提交补丁吧。维护DIM-SUM操作系统的人使用的都是汉语,沟通起来完全没有问题,并且他们都不是外星人,你不用觉得他们凶巴巴的。
1.5.1 心态
Paul 在《深入理解并行编程》一书第 11.1.2 节中说过,验证和测试工作都需要良好的心态。应当以一种破坏性的,甚至带一点仇恨的心态来验证代码,有时也应当考虑到:不少人的生命都和代码的正确性息息相关。总之,心态对事情的成败有重要的影响。
你在向DIM-SUM提交补丁之前,请保持如下正确的心态:
1.撇开DIM-SUM不谈,我们的代码可能会影响不少人的生命,所以为任何项目编写代码,都一定要细心。
2.悲观地说,如果补丁做得不好,会影响自己的声誉,并且得不到足够的关注,最终会导致补丁没有被采纳。
3.乐观地说,DIM-SUM的维护者、开发者一般都比较友好。
4.更进一步乐观地说,你提交的高质量的补丁可能会为你带来良好的声誉、满意的工作。
如果你和我一样,有着近乎自大的自信,想要在操作系统方面做出一些成绩,请仔细阅读后面的章节。
1.5.2 准备工作
跃跃欲试想要提交补丁的读者,一定已经熟悉Linux开发环境了。在此,我假设你已经安装好Linux和Git。
1.配置Git用户名和邮箱
在配置用户名的时候,建议“名在前,姓在后”,并且第一个拼音字母大写。例如,我的用户名是Baoyou Xie。
在配置邮箱时,请使用有意义的邮箱名,而不要使用纯数字邮箱名。
以下是我的配置:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_29_1.jpg?sign=1739474314-x8STJwcREQ9uNgyQ3NwGdDB30dsBIUcy-0-013bc7537804e87b5c714c7ffa2e01ff)
2.配置sendemail
你可以手动修改~/.gitconfig或者Git仓库下的.git/config文件,添加[sendemail]节。该配置用于指定发送补丁时用到的邮件服务器参数。
以下是我的配置,仅供参考:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_29_2.jpg?sign=1739474314-3ahP9IZASW42WF85jbDkBfnPCYj3IrEH-0-9e4e702d62dcf3a6c32951f69fdd5848)
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_1.jpg?sign=1739474314-sORnlz2NNffEq7k63BDNPSMuL6usdMen-0-374bdf1c2270ab8a8a39782a20dbf100)
配置完成后,请用如下命令向自己发送一个测试补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_2.jpg?sign=1739474314-TJlTsLyh3DfC4Wz1TTwh15h4lWpvrG5s-0-e955f260a890bf2c67fd31c2cc0b7500)
3.下载源代码
如果仅仅是为了阅读本书,而不想向 DIM-SUM 提交补丁,那么使用 Git 直接从 DIM-SUM主分支拉取代码就行了。
从Git服务器下载源代码后,可以随时使用如下命令更新主分支代码:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_3.jpg?sign=1739474314-iISSJ4UIdapbjvWz0JXpKdmvnmOu9Ztt-0-654d6d1090a7c18160fb92bca190476d)
但是,如果想参与到DIM-SUM的开发中,那么就需要从多个Git分支拉取代码。这是因为:主分支代码并不一定是最新的,如果基于这个代码制作补丁,很有可能不会顺利地合入维护分支。换句话说,如果你的代码分支没有与维护者的保持一致,那么维护者有时会将补丁发回给你,要求你重新制作。所以,一般情况下,你需要再用以下命令添加其他分支:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_4.jpg?sign=1739474314-DFEhSeb4tWLHEvLOjoHbQqHNaR9lTakf-0-62754866e75d326650a6939eede381b3)
其中,tag-name是你为分支添加的别名,git-url是DIM-SUM分支的URL路径。
随时可以使用如下命令更新分支代码:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_5.jpg?sign=1739474314-nEwHooc6NUM1wksK8foiBNL9hw9HQhka-0-6ca9f0c00ab8c87d007e9d7284358022)
随着DIM-SUM的发展,不同的模块会由不同的维护者来维护。这些维护者会有自己的代码分支。你可以在 DIM-SUM 源代码目录的 MAINTAINERS 文件中找到相应文件的维护者,及其Git地址。
MAINTAINERS文件的格式与Linux中的MAINTAINERS文件的格式类似。例如,在Linux内核中,watchdog模块的信息如下所示:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_6.jpg?sign=1739474314-iJDrrhWu273YgeLRCONi48ujQAq67XvA-0-409f29b6a25fbd88ce9ef90b08da5504)
代码仓库的链接地址也包含在其中。
4.阅读Documentation/SubmittingPatches文件
认真阅读这个文件,对正确制作补丁来说很重要。
5.使用如下命令检出源代码
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_30_7.jpg?sign=1739474314-MXBfqpWIjIEeXuEImytHTJdSFXrhNc5Z-0-6388f083d064c95c1240af5e2f23eb3d)
这个命令表示将remote-branch远程分支作为本地mybranch分支,作为工作的基础。在这个分支上制作补丁,更容易被维护者合入。
使用如下命令切换为本地mybranch分支:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_31_1.jpg?sign=1739474314-sH9da7MtE0xSS3Pbb0AlyQt6qP8J1jiM-0-934172b88836a3775b221dec961f6470)
接下来,就可以修改本地代码,开始制作补丁了。
1.5.3 制作补丁
参与DIM-SUM的开发,可以从简单的事情入手。例如:
1.消除编译警告。
2.整理编码格式,例如注释里面的单词拼写错误、对齐不规范、代码格式不符合社区要求。
Linux社区里面的很多大牛就是从消除Linux内核警告开始参与Linux开发的。下面举一个简单的格式整理例子。
在kernel/sched/core.c的第192~193行,其代码看起来如下所示:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_31_2.jpg?sign=1739474314-ElA8z1M877u9l6M1xugYRQX1HiVPDHwT-0-5a236c3b52b1180ad4d9483b7a8f0ff9)
其中,第193行存在两个问题:
1.该行包含了84个字符,其中每个Tab键占用8个字符空间,代码超过了80个字符的限制。
2.没有与上一行对齐,排版太难看了。
删除该行前面几个Tab键,使其看起来如下所示:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_31_3.jpg?sign=1739474314-sIRFg8w7q417IEsBv9R0HPlvhyOHSoUx-0-3c4b61031c59b1118b7a088e61a149e0)
修改完成后,在控制台输入如下命令将补丁提交到本地Git仓库:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_31_4.jpg?sign=1739474314-mZaVmMfXaFk4r6QY9kqFM4qYa61e1bBX-0-c2790b8e7a6e53276f00841cf8600db2)
然后使用如下命令生成补丁文件:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_31_5.jpg?sign=1739474314-0VrA7Mg96YzZ8UDD2qy0UwbuAP65TNgh-0-2a709d37b33e2348c36eea29ee328e32)
生成的补丁文件内容如下:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_31_6.jpg?sign=1739474314-r0mb7YdDS2H4yIyjSmaVWN4REgBWfr0q-0-59d05b76bdb5f2347ae97d99a6de44a0)
在core.c第193行,代码超过了80个字符,并且与上一行没有正确地对齐,因此应该删除其中多余的Tab键。本补丁删除这些多余的Tab键以满足代码格式规范。
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_1.jpg?sign=1739474314-j4e4jsN5zEuDNGvvznw79igJVXxzrlzK-0-1b981669a36b1e7df02491f367b52107)
* 在什么情况下,二者会相等?
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_2.jpg?sign=1739474314-SKwQswLf77Ve9c1l1H9J3IFDI8N8W1em-0-56a2730f749c42b88ede62d3a2c12167)
难道制作一个补丁就这么简单?现在可以将它发送给维护者了吗?
答案当然是否定的。这个补丁有如下问题:
1.没有彻底解决模块中的同类问题。
2.补丁格式不正确。
首先应当将补丁退回。使用如下命令退回:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_3.jpg?sign=1739474314-cCWhfM2tSJ8ao8BKxBab7hhltHgImyyv-0-3b8410373bec4edec385910d47399d2f)
1.5.4 制作正确的补丁
实际上,在向维护者发送补丁之前,应对补丁进行检查,如下所示:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_4.jpg?sign=1739474314-k8gvhxNE3ydpmrsQa2FolzKjJ0Vqrlva-0-3a96d85ea81e20ba7af58c5c2f196fa3)
对于刚才生成的补丁,会得到如下错误:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_5.jpg?sign=1739474314-xGgoOaoewW97uNik6ZvQS3GZoCJiGpPD-0-dda9c37c85ad36762c3935789d281d59)
在core.c第193行,代码超过了80个字符,并且与上一行没有正确地对齐,因此应该删除其中多余的Tab键。本补丁删除这些多余的Tab键以满足代码格式规范。
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_6.jpg?sign=1739474314-FJDylfPnCsIjQkSYjIrBMuGn0ubsblMP-0-8fe9840b90c6f3b7a6f080ae087e8913)
错误在于:补丁描述行太长了,应当折行,使每一行少于 75 个字符。再次使用如下命令提交补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_32_7.jpg?sign=1739474314-swJL3EQdghcF9dHqAMUthz5sD62uVaZN-0-3354099e95f26d73fbaf5a645eae9a12)
在提交补丁的时候,注意修改补丁描述,使其满足格式规范。反复制作补丁并使用checkpatch.pl检查其正确性,直到消除了所有警告为止。当然,极个别的警告是允许存在的。
使用checkpatch.pl仅仅能检查格式规范方面的错误。但是一个正确的补丁远不止格式正确这么简单,它还应该满足如下要求:
1.在一般情况下,同一个补丁只修改同一个模块的代码。
如果必须同时修改多个模块中的代码,那么应该让所有模块的维护者同意,并确定由其中某一个维护者合入补丁。这种情况仅仅是特例。
但是怎么确定某个文件属于哪一个模块?应当查看MAINTAINERS文件,其中有一个例子:
内核同步与互斥
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_33_1.jpg?sign=1739474314-8qlwxwSKGM3Gn9jXNgr5HGzDgVe9Txp0-0-a4def0448765b936b03032951ae6207d)
可以看出,kernel/locking目录下的所有代码均属于“内核同步与互斥”模块。
2.同一个补丁仅仅解决一个独立的问题。
不要试图在同一个补丁中解决多个问题。例如,既消除一个编译警告,又整理一行代码。
小问题 1.9:但是,消除编译警告和整理代码都仅仅修改了一行代码,并且位于同一个文件之中,这样也不能将它们制作到同一个补丁中吗?如果不能,请告诉我正确的做法。
3.同一个补丁必须完整地解决一个问题。
换句话说,不能将一个问题分拆到多个补丁中去。正如前一个例子所述,需要在一个补丁中将整个模块的格式全部整理完毕。如果补丁太大,可以考虑按照每个文件或者每个功能模块对补丁进行拆分。
4.补丁不要太大,但这不是一个强制要求遵循的规则。
一般来说,一个补丁修改的代码行数不要超过200行。不过此规则比较灵活。如果一个单独的问题确实需要修改超过200行代码,那么就打破这个规则吧。
要制作一个正确的补丁,还有一个问题比较重要:补丁的标题和描述。
补丁第一行是标题,它首先应当是模块名称。
但是要怎么找到kernel/sched/core.c文件属于哪个模块呢?
可以试试下面这个命令,查看kernel/sched/core.c文件的历史补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_33_2.jpg?sign=1739474314-CHl0suqHKch05AGQTnOoMFbM4bZpTZvj-0-3cc860fd8a243262a88f6f52ed5ffb5d)
可以看到,kernel/sched/core.c文件所在的模块名称是“调度”。
其中,第一行是标题,在模块名称后面是补丁标题,应当简单、清楚地表明了补丁的内容。当然,标题可以超过80个字符。
随后的内容是补丁描述符,要清楚地描述:
1.为什么要制作这个补丁。
2.这个补丁是如何实现的。
当然了,模块的维护者可能对补丁描述有额外的要求,你可能也有需要特殊说明的地方,可以将它们都补充在描述中。这有点像写作文,既要求条理清楚,又没有成规。
1.5.5 发送补丁
在发送补丁前,需要用脚本再次检查一下补丁,确保其正确:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_34_1.jpg?sign=1739474314-haA39scG7daDeG1AmJP0KeqgX24JGOQH-0-33587feec2d8f855c8bb4e7f77a0cccf)
如果想要一次性生成并发送多个补丁,可以使用如下命令生成补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_34_2.jpg?sign=1739474314-ei7fbkS1coBAURvBAzMtobA2zY9mAVgn-0-198801aea028b51991a5d3360a66b907)
在我的环境中,上述命令生成了两个补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_34_3.jpg?sign=1739474314-AtRL0JIfgN4DuoBGxTvRoOUOKPFQBu6M-0-b878cbf6f9ebd3936a9a377e0193de6d)
然后用checkpatch.pl检查这两个补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_34_4.jpg?sign=1739474314-pwnpm02iX6jdIg9ZBuMQGpieuIF5opAc-0-c14f6779ef4d0c41d7db22a786d716ac)
一切无误,可以准备将补丁发送给维护者了。
但是应该将补丁发送给谁?这可以用get_maintainer.pl来查看:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_34_5.jpg?sign=1739474314-ORP65PQ7TijNlcVDwad1oEqKeX0zSqSZ-0-ee75f6e6becbc2646f5865662c99da0c)
接下来,可以用git send-email命令发送补丁:
![](https://epubservercos.yuewen.com/C5CFF8/26763698001326206/epubprivate/OEBPS/Images/39186_34_6.jpg?sign=1739474314-maRwNXyOM18horotjsWteTpcWykl0WeJ-0-08d9880830b69cc5b4206efb95d1c941)
需要注意分辨,哪些人应当作为邮件接收者,哪些人应当作为抄送者。在本例中,补丁是属于实验性质的,可以不抄送给邮件列表账户。
提醒:你应当将补丁先发送给自己,检查无误后再发送出去。如果你有朋友在Linux社区有较高的威望,有补丁走查的经验,或者深度参与了DIM-SUM的开发,那么也可以抄送给他,在必要的时候,也许他能给你一些帮助。这有助于将补丁顺利地合入DIM-SUM。
重要提醒:本章讲述的主要是实验性质的补丁,用于让你熟悉提交补丁的流程。真正重要的补丁可能需要经过反复修改后才能合入 DIM-SUM。并且,这需要你反复阅读本书后面章节中对DIM-SUM内核的代码分析。最重要的一点是,需要你熟练掌握DIM-SUM的代码。