Linux_TA_Notes.rst 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. 操作系统实习课程助教笔记
  2. ========================
  3. 助教联系方式
  4. ------------
  5. * 地点: 理科一号楼 1817
  6. * 邮箱: vimacs.hacks AT gmail.com
  7. - OpenPGP fingerprint: 9E5B 817B FF33 8DD7 0167 6C27 6DBD 8BFE 8600 BEAA
  8. * 电话: use **printf "%d\n" 0x46131b3be** to get my phone number
  9. * GitHub: https://github.com/mytbk/
  10. * 未名BBS: vimacs
  11. * `Matrix <https://matrix.org>`_: ``@vimacs:matrixim.cc``
  12. * `XMPP <https://xmpp.org>`_: ``vimacs@cnjabber.net``
  13. 第 1 次课
  14. ---------
  15. 第一次课的内容是搭建环境。视频放在 https://lcpu.club/file/media/os-video/
  16. 实习题目:
  17. 1. 在虚拟机中安装 Linux 操作系统(这次课用的是 Ubuntu 16.04 LTS,带Linux 4.4 LTS 内核)
  18. 2. 使用 SSH 访问虚拟机
  19. 3. 学会设置系统软件源
  20. 4. 搭建开发环境
  21. 5. 学会用 `Vim <http://www.vim.org/>`_ 编辑器,用 taglist 插件查看代码中的符号
  22. 6. 学会用共享目录在宿主机和虚拟机之间共享文件
  23. 第 2 次课
  24. ---------
  25. 第二次课讲了如何用 git 获得 Linux 内核源码。
  26. 实习题目:
  27. 1. 建立 GitHub 帐号,fork `torvalds/linux <https://github.com/torvalds/linux>`_ 仓库
  28. 2. 用 git 把 Linux 内核源码以裸库的形式克隆到本地,并 checkout 出一份源码
  29. 得到源码之后,可以用 **git checkout v4.4** 获得 Linux 4.4 版本的源码。
  30. 第 3 次课
  31. ---------
  32. 第三次课讲的是 Linux 系统的启动流程,读了 Linux 内核启动初期的相关源码。
  33. 实习题目:
  34. 1. 使用内核命令行参数 **initcall_debug** (见 Linux 源码 **Documentation/kernel-parameters.txt**) 启动系统
  35. 2. 用 Linux 源码中的 *scripts/bootgraph.pl* 生成一个 SVG 图片
  36. 3. 根据生成的 SVG 图片列出时间最长的10个 initcall,并查阅它们的功能
  37. 第 4 次课
  38. ---------
  39. 这星期讲解了如何构建一个可以运行的内核,内核模块的作用以及代码风格。
  40. 实习题目:
  41. 1. 构建并更新一个内核,LOCALVERSION 为自己名字的缩写,用这个内核启动系统
  42. 2. 阅读 TLDP 上的 `The Linux Kernel Module Programming Guide <http://www.tldp.org/LDP/lkmpg/2.6/html>`_,完成 hello-1.c 到 hello-5.c 这5个模块
  43. 3. 阅读 **Documentation/CodingStyle** 总结内核的代码风格
  44. 4. 用 *scripts/checkpatch.pl* 检查自己写的代码
  45. 作业检查时遇到的问题:
  46. #. **pr_debug()** 输出的信息在 dmesg 中不显示,原因是 **pr_debug** 只有在 **DEBUG** 宏打开或者打开了 **ENABLE_DYNAMIC_DEBUG** 选项时才起作用。 **Documentation/CodingStyle** 中有说明,*include/linux/printk.h* 中也能看到相关宏定义。
  47. #. 自己编译的内核无法启动系统: 如果在 ``make install`` 的时候发现 initramfs-tools 提示 WARNING 说找不到模块,应当先执行 ``make modules_install``.
  48. - ``make install`` 的功能仅仅是调用系统中的 ``/sbin/installkernel``
  49. #. 要在内核版本中显示自定义的名字,可以修改 EXTRAVERSION 和使用 config 中的 LOCALVERSION,其中 EXTRAVERSION 在内核的 Makefile 中修改,LOCALVERSION 在以下位置配置:
  50. ::
  51. General setup --->
  52. () Local version - append to kernel release
  53. 最终在内核版本后显示的字符串是 $(EXTRAVERSION)$(LOCALVERSION)
  54. 第 5 次课
  55. ---------
  56. 本次课讲解抽象层次,内容比较杂,介绍了内核中的分层架构、API 和 ABI 的区别、系统调用和VDSO等。
  57. 实习题目:
  58. #. 修改 LKMPG 8.1 的例子,替换 ``open`` 调用,截获 test 用户的操作。
  59. #. 构建动态链接的 `hello world` 程序,用 ``strace`` 获取其系统调用。这些调用做了什么功能?
  60. 检查作业时遇到的问题:
  61. #. 修改系统调用表的方式:
  62. - 导出 ``sys_call_table`` 后编译内核
  63. - 加载模块前看 ``/proc/kallsyms`` 找 ``sys_call_table`` 的地址,然后让模块知道系统调用表的地址,注意内核可能会在启动时随机化这个地址
  64. - 模块加载时搜索系统调用表,参考 `<https://github.com/leurfete/simple-rootkit/>`_
  65. - 用 ``kallsyms_lookup_name``
  66. #. 注意学会用 ``man`` 查看函数的使用方式,包括系统调用
  67. 第 6 次课
  68. ---------
  69. 这次课讲解 Linux 源码中的头文件。
  70. #. 选择 `lib/` 下的一个源文件,给出它的头文件包含关系图。
  71. #. 用 ``make headerdep`` 检查头文件嵌套包含,并解决一个嵌套包含关系。
  72. 提示:学会使用 ``scripts/headerdep.pl``. 还有,Linux 源码会使用 libgcc 和 glibc 的头文件。
  73. 第 7 次课
  74. ---------
  75. 本次课的名字叫调试之道。
  76. 调试中的概念:
  77. * bug, typo, bug tracking system, Heisenbug
  78. * remote debugging
  79. * post-mortem, coredump
  80. * "wolf fence" debugging using ``git bisect``
  81. 实习题目:
  82. #. 使用 **print_hex_dump** 打印 **boot_command_line** 和 **saved_command_line**
  83. #. 学会使用 Magic SysRq
  84. #. 学会使用 **dump_stack**
  85. #. 学习 `Debugging the kernel using Ftrace <https://lwn.net/Articles/365835/>`_
  86. 课程项目
  87. --------
  88. * 4个小组分别为 RISC-V 32, RISC-V 64, Unicore 32, Unicore 64 构建 QEMU, 内核和 busybox