Linux系统编程 / 分析开源软件Triggerhappy (2)

哈喽,我是老吴,继续记录我的学习心得。

一、构建思维组块

构建组块(chunking):

  • 就是利用一些概念,组合起信息碎片,这是一种心智上的飞跃。

构建组块的方法:

  • 把注意力集中在需要组块的信息上 。思维就像章鱼触手,一旦分心就无法抓紧。

  • 把基本概念打包成组块,然后理解这个基本概念。专注和发散模式的交替思考,总能理清头绪,把握概念。

  • 获取背景信息,不仅是知道如何进行组块,还要知道何时何地如何使用该组块。

学习活动包括 “以上至下、从下至上” 两个方向:

  • 从上至下的宏观学习,和从下至上的组块活动,两个过程对熟练掌握知识都有重要作用。

应用到软件开发上:

  • 大多数编程书里是教授的都是大量的细微的知识点,我们需要先把这些非常小的知识点体系化,形成多个组块,这是从下至上的组块活动。观察现有的优秀软件 (一般是开源软件) 是如何使用组块的,这是从上至下的宏观学习。

  • 另外,学习软件开发要学会抽象,写代码是抽象再组合,而读代码则是分解出一个个小的组块。


二、..Linux系统编程 / 分析开源软件 Triggerhappy / (2) 把握核心流程

正文目录:

1. 分解 thd.c / start_readers()
1.1 thd.c / start_readers() 的作用
1.2 thd.c / start_readers() 的内容
    1) 根据命令行参数,判断是否需要打开 socket
    2) 将命令行中指定的输入设备添加到设备链表中
    3) 根据命令行参数,决定是否成为守护进程 (daemon)
    4) 根据命令行参数,决定是否创建 pidfile
    5) 真正开始监控设备并处理事件

写作目的:

  • 通过分析开源软件 Triggerhappy,练习 Linux 系统编程。

测试环境:

  • Ubuntu 16.04

  • Gcc 5.4.0

1. 分解 thd.c / start_readers()

1.1 thd.c / start_readers() 的作用

1) 作用:

  • 启动读进程,虽然该程序是单进程的,复数 readers 可能是作者觉得有机会使用多线程吧。

2) 使用者:

  • 私有函数,只有 thd.c / main() 会调用。

1.2 thd.c / start_readers() 的内容

1) 根据命令行参数,判断是否需要打开 socket:

/* open command pipe */
if (cmd_file) {
 cmd_fd = bind_cmdsocket(cmd_file);
 if (cmd_fd < 0) {
  return 1;
 }
}

cmd_file 对应参数 -s:

$ man thd
--socket file
    Open a unix domain socket at file; this socket can be used to send commands to the running daemon (by
    using the program th-cmd), e.g. for adding or removing devices.
  • 这里的 socket 类型是 UNIX domain socket (AF_UNIX),该 socket 允许位于同一主机系统上的进程之间相互通信的

  • bind_cmdsocket() 的实现位于 cmdsocket.c,thd 和 thd-cmd 会共用 cmdsocket.c 来通过 socket 通讯以动态地增减要监控的输入设备.

  • 后续再来细看 cmdsocket.c 的内容,分析该文件可以学习 UNIX domain socket 相关的知识

2) 将命令行中指定的输入设备添加到设备链表中:

/* add every device file supplied on command line */
for (i=start; i<argc; i++)
    add_device( dev, -1, grab_dev, tag_dev );
  • thd 要监控的设备可以从2个地方指定:1. 命令行参数,2. glob device,这里处理的是情况1。

  • add_device() 的实现位于 devices.c, 该文件通过链表 (device *device_list) 来管理所有要监控的输入设备,肯定会有这些操作:增加 (add_device)、删除 ( remove_device )、遍历 (for_each_device)。

  • 后续再来细看 devices.c 的内容,分析该文件可以学习到数据结构链表相关的知识

2) 将 glob device 指定的输入设备添加到设备链表中:

/* check device glob */
glob_t globbuf;
glob(dev_glob, GLOB_NOSORT, NULL, &globbuf);
for (i=0; i<globbuf.gl_pathc; i++)
    add_device(globbuf.gl_pathv[i], -1, grab_dev, tag_dev);

glob device 是什么?

$ man thd
--deviceglob pattern
    Open device files matching the glob pattern.
  • glob 库函数用于 Linux 文件系统中路径名称的模式匹配, 看来是用来处理类似 /dev/input/event* 的情况。

3) 根据命令行参数,决定是否成为守护进程 (daemon):

if (run_as_daemon)
    daemon(0,0);

什么是 daemon?

  • daemon 运行在后台,不与任何控制终端相关联。守护进程通常在系统启动时就运行,它们以 root 用户或者其他特殊的用户运行,并处理一些系统级的任务。

  • daemon 的两个基本要求:1. 必须作为 init 进程的子进程运行,2. 不与任何控制终端交互。

GNU C库提供了一个非标准的 daemon()函数,它将调用者变成一个 daemon,thd 就使用了该函数。

4) 根据命令行参数,决定是否创建 pidfile

if (pidfile)
    write_pidfile( pidfile );
  • write_pidfile() 是 thd.c 的私有函数。

  • pidfile 为文本文件,一般内容只有一行, 记录了该进程的 PID。

  • 它的作用是防止进程启动多个副本。

5) 真正开始监控设备并处理事件:

process_events(); 
  • process_events() 是 thd.c 的私有函数。

  • 接下来需要重点分析该函数

鉴于大多数人的注意力无法在一篇文章里上集中太久,更多的内容请大家先自行去阅读吧,不是自己理解到的东西是消化不了的。有机会的话我会把更多的分析心得放在后面的文章。

总结一下,接下来需要跟进的事情:

  1. 分析 thd.c / process_events();

  2. 分析 thd.c / reload_triggerfile()

这么看来,目前的任务还比较轻松。


三、思考技术,也要思考人生

学习技术,更要学习如何生活

你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。


嵌入式系统 (Linux、RTOS、OpenWrt、Android) 和 开源软件 感兴趣,想和更多人互相交流学习,请关注公众号:嵌入式Hacker,一起来学习吧。

无论是关注或转发,还是打赏,都是对作者莫大的支持。觉得文章对你有价值的话,不妨点个 在看和点赞 哦。

ps:
欢迎加入我的微信群:加我,我拉你进群,暗号(加群)。

祝各位工作顺利,家庭幸福,财源滚滚~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值