标题:GNU的tail源码阅读笔记 出处:Felix021 时间:Thu, 29 Oct 2009 12:52:10 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1748 内容: ---# GNU的tail源码阅读笔记 ---++ 获取源码 tail和head等原本是属于textutils软件包的,后来被统一合并到coreutils软件包中了。coreutils的主页是:http://www.gnu.org/software/coreutils/,可以从这里下载到所有的源码。如果你使用的是Ubuntu系统,还可以直接运行命令 apt-get source coreutils 直接从源中获取代码。 ---++ 编译 先编译一下。跟其他开源软件基本上一致,先./configure一下,没有问题的话就make之。make结束以后,生成的可执行文件就在src目录下面 ---++ 阅读 为了方便阅读,先ctags -R一下,生成tags;然后vim src/tail.c就打开了源码。代码比较细碎,零零散散2000多行,花了两三个小时才看完,大致读懂了代码的主干流程,这里记录一下。 * 初始化,有些乱七八糟的initialize_main/set_program_name/setlocale/bingtextdomain/textdomain都可以忽略,没做什么实事。atexit还算有点用,设置了退出的时候要把stdout关闭。 * 解析命令行参数。先上了个obsolete_parse_option(option都不加个复数s),貌似是为了兼容以前的命令行参数方式(posix2_version在200112这个版本以前的)。然后又来一个parse_options,这个就是按照man里面的格式来解析参数了。具体的参数man tail就可以看到,不多说。 * 判断一下输入是不是源于stdin,如果是的话,修改一下file和n_files。 * 然后给文件结构体分配空间,填进去每个文件的名字,然后是一个循环,调用tail_file来输出每个文件(传入结构体F[i]的指针)的内容 看看tail_file: * 打开文件,失败的话当然就over了,return * 看看要不要输出文件名(可以在命令后参数指定-q, -v) * 调用tail函数输出需要输出的内容。tail函数根据是要输出行还是输出字符(命令行参数-c)来决定调用tail_lines还是tail_bytes。 * tail_lines: 如果是输出末尾n行,就调用file_lines函数,从文件的末尾开始,往前找到要开始输出的位置,调用dump_remainder输出;如果要输出第n行以后的内容,就调用start_lines跳过前n行,也是调用dump_remainder输出。 * tail_bytes和tail_lines的结构基本相同,不过那个函数是start_bytes了。 * 如果有-f参数(follow, 不断输出文件中新增加的内容), 检查一下文件的状态;否则就可以关闭了 * 如果指定了-f参数,那么执行if(forever && n_viable)这一段。其中n_viable是可以继续tail的文件的数量。 * 如果linux内核支持inotify特性(监控文件的变化,并发出通知),那么调用tail_forever_inotify函数来跟踪文件的变化(添加inotify的watch,然后用select来处理)。 * 否则使用tail_forever函数,做法是循环输出每个文件新增加的内容(上次读取的时候记录一下读取的位置),然后nanosleep一段时间(默认是1.0s)。 Generated by Bo-blog 2.1.0