VanTYS 2019-11-11
本周内容为十章的内容的拓展,以实践为主,通过系统调用实现who、od以及ls -l的功能。在这一过程中,我们不仅要利用第十章中的系统I/O函数,还需要用到man帮助文档以及man -k XXX
的查询命令。
要求:
由于Myod在上个学期的时候进行过实现,所以本次实践的关键在于如何使用Linux I/O 系统调用来实现od。要想实现Myod,首先需要将指定文件的内容读入到程序,在了解系统调用之前,我们可以使用fread函数来打开并读取文件中的内容,而结合第十章的内容以及man帮助文档,我们可以使用open以及read的系统调用来实现文件的打开以及读取,从而实现od -tx -tc的功能。由于不能将代码都写入main函数中,且不能只有一个c文件,我将程序分为两部分,并使用gcc main.c myod.c -o myod
进行编译,运行结果如图所示:
在Linux中,who命令可以打印登陆用户以及登陆的时间,要实现who命令,我们可以先使用man who
命令来查看who命令的描述。在who的帮助文档中,我们可以看出who命令使用了一个utmp文件,如图
通过使用man帮助文档查看utmp,我们可以知道utmp是一个系统文件,且里面有一个utmp结构体,里面定义并存储了用户名,终端等信息。我们需要做的就是在程序中打开这个utmp文件,并将utmp结构体读出,再将其中我们需要的值输出。
在前面我们通过man帮助文档找到了utmp文件的路径为/var/run/utmp
通过该路径即可打开utmp文件,在老师提供的who代码中,我注意到老师使用了一个UTMP_FILE的宏定义,通过使用grep -nr UTMP_FILE /usr/include
命令得知,该宏定义定义了utmp文件的路径。
将教师提供的代码编译运行后,发现没有获得期望的输出,经过分析后我发现只需要输出用户信息,于是我使用ut_type对记录类型进行筛选,输出USER_PROCESS类型的记录,并对ut_time进行转换输出,得到的运行结果如下所示:
由于ls命令的作用是输出当前目录下的目录以及文件信息,因此我们可以尝试使用man -k directory | grep read
命令来寻找可以读取目录信息的函数或系统调用。
通过查找后发现readdir函数可能符合我们的要求,通过man帮助文档查看该函数,发现函数返回一个dirent结构体,该结构体中有个d_name数组,里面存储了文件名。有了获得文件名的readdir函数,但输入该函数的参数是我们没有见过的DIR类型,这时我们可以下拉帮助文档,查看其中的相关函数,而相关函数中有一个opendir函数,通过man查看后发现,该函数的返回值正是DIR类型的参数。
到这里我们已经可以在一定程度上实现ls的功能了接着按照相同的方法查询实现排序、分栏、筛选隐藏文件以及长形式输出的功能即可,运行结果如下:
代码托管
本周的实践内容想要实现起来还是比较困难的,有时知道即使是知道需要的功能,却不知道如何确定关键字,而查看帮助文档时,全英文的说明又对阅读造成了一定的困难,在寻找所需要的功能时需要花费一定的时间。