在Ubuntu环境下载、查看和修改源代码
在Ubuntu环境下,下载 ls 命令的软件包,阅读并尝试修改其源代码,同时测试对 ls 命令功能的修改。
在Ubuntu环境下载、查看和修改源代码
目录
简介
本实验想要实现的目的如下:
(1)下载并查看 “ls” 命令的源代码;
(2)对命令的源代码进行小的修改并尝试运行;
(3)将修改的源代码安装到系统上。
本博文是记录课程作业实现过程而撰写的实验报告,为后面复习或者给有需要的人提供一点帮助而发布。
实验过程
1、先在下载中勾选源代码处的选项,并更新源
在设置中找到下载的相关选项,勾选“源代码”(默认没有勾选)
更新源
sudo apt update
操作如下
2、用 which 命令查找 ls 命令所在的位置,并用 dpkg 命令查看命令所在的软件包
(1)发现没有相匹配的路径
(2)尝试加上 -a 查看所有的匹配项,发现有两个路径
(3)在根目录下查看,发现 /bin 目录其实是一个链接
(4)对 /bin 链接下的 ls 用 dpkg 命令查找,可以得到对应的软件包(coreutils)
后来发现原因是 20.04 版本的 Ubuntu(本人用的版本)与 18.04 版本的文件系统不太一样,而大部分 Linux 系统默认使用的文件系统与 18.04 版本一样,因此采用 /bin 目录下的 ls。
3、通过apt命令获取源代码
apt source coreutils
运行 apt 命令之后源代码即下载到当前目录下。
4、运行./configure配置文件并编译
(1)查看 ./configure 配置文件
进入源代码所在的目录,用 “ll” 命令查看配置文件 configure
右上角的 ‘*’ 表示为可执行文件
(2)运行 ./configure 配置文件并用 make 编译
./configure && make
(3)运行一段时间之后出现报错,显示的是make的错误
提示 ‘aclocal-1.15’ 不存在于系统中,运行多次仍然出现下面的报错。
(4)由于并不理解该报错信息,于是将其在网络上查找,找到这篇博文。大概是由于版本问题,根据其提示运行代码:
autoreconf -f -i
发现需要额外安装包autoconf,根据要求,操作如下:
(5)安装之后继续运行命令,发现仍然报错,提示没有找到相关文件,借助这篇博文的帮助,提示还需要再安装一个软件包 autopoint ,运行如下代码:
sudo apt install -y autopoint
如下:
(6)安装之后,autoreconf -f -i 代码即可正常运行,如下:
(7)由于之前配置文件已经运行,直接用 make 编译即可
编译成功,可以在 /src 目录下看到新增了一系列可执行文件,截图如下:
调用本地的./ls可执行文件也可以成功运行,部分截图如下:
5、对 ls 命令的源代码进行修改
(1)修改目标
将 ls 的 ‘-l’ 选项修改为 ‘-z’ 。
没有改变实际功能,只是单纯的修改输入的命令选项,即改用 “ls -z” 命令来实现 “ls -l” 的功能,列出当前目录下所有文件的详细信息。
(2)进入 ls 命令源代码所在的 src 文件夹。经过查看,ls 命令的源代码主要写在 ls.c 文件中,于是进入该文件寻找目标代码。
(3)由于想要修改的命令和 ‘-l’ 相关,因此用vim的查找功能直接查找 ‘-l’ 。经过逐个筛选,锁定到了如下的一行注释中:该注释对应的是一个C语言中的枚举 enum,其中’-l’所在的注释对应的是第一个元素 “long_format” 。
(3)查找的关键词的选择
由上述的查询结果可见 “long_format” 是一个重要的关键词。
由于ls命令的每个选项前都有 ‘-’(如 ‘-l’、‘-a’ 等),因此程序在对输入的’ls’命令后面的选项进行识别的过程中对’-'字符进行判别的概率较小,而若单单使用一个单词 ’l’ 来查找则很容易查到许多无关的匹配项(可能许多单词包含’l’字母),因此改用 “long_format” 关键词来查找很有利于提高查找效率。
(4)于是利用vim查找 “long_format” 。又经过不断的筛选,在几千行代码中找到了一片非常有结构性的代码块——switch-case 语句,由于ls命令有许多的选项,很容易让人联想到可以用 switch-case 语句来实现,如下:
仔细一看,果然再次发现了关键词—— ‘l’
(5)直接将其改为我们想要的选项—— ’z’,如下:
(6)回到上一级目录,再用make编译一下
(7)回到 ls.c 文件所在的目录下运行./ls -l和./ls -z,发现都无法实现,如下:
(8)问题分析
./ls -l 无法运行说明之前所作的修改的位置正确,而 ./ls -z 无法运行说明选项的修改不完全,还有其他地方需要修改。
而且发现运行 ./ls -l 命令时只是提示通过 help 来获取帮助,而运行 ./ls -z 时还提示 ls 并没有 -z 的选项,说明各个选项可能还存放在某个类似于数组的数据结构中,用于判断输入的选项是否合法。
由于之前只在 switch_case 结构中修改了输出的标志 long_format(猜测),并没有在哪个数组中将其删去,而修改为 -z 时并没有将 -z 添加到所谓的数组中,因此导致运行时出现如上的 -z 为不适用的选项的提示。(几千行的代码怎么可能没有其他的依赖,只需要修改一个地方)
(9)经过不断的查找,在 switch_case 结构的前几十行找到了下面的代码,刚开始并没有太多的注意,但是后来发现如下的字符串中的字符可能是按某种顺序进行排列,而且并不是连续的字典序abcde…
于是重新翻到 switch_case 结构处。如下(截取片段),发现 switch_case 结构中选项的顺序恰好与上述的字符串的子串相匹配。
于是大胆猜测该段字符串就是之前假设的所谓的存储选项的数组,于是将字符串中的 ‘l’ 改为 ‘z’ ,如下:
(10)再返回上级目录进行编译,并尝试运行
使用./ls -z命令可以正常使用,如下:
而./ls -l命令已经不能使用了
成功!!!目标达成
6、将修改的源代码安装到系统上
运行代码
make install
由于安装后会修改系统上的程序,为了防止存在的存在隐藏的BUG,本人没有尝试运行安装程序。
总结
对于系统命令源代码的修改,原本个人想法是想修改ls命令本身的一些功能,比如添加一个选项,使ls能都递归地进行调用,遍历当前目录及以下的所有文件并显示出来。但是当我打开 ls.c 文件之后我的这种幻想被打破了,我从头往后翻,发现几百行的代码全是enum、struct等的定义,而全部代码足足有上千行。由于较大的修改需要先读懂大部分的代码,想想还是放弃了。
原本以为改个选项名称会容易一点,后面发现在几千行代码中进行关键词的筛选也不是一件容易的事儿。
通过本次实验,大致掌握了软件包的编译下载,通过对系统命令源代码的阅读使得对代码的开发有了一定的了解,同时也意识到关键词查找的必要性和便捷性,即使本次实验的实现在开发上并没有实际性的意义。
更多推荐
所有评论(0)