值得推荐的小型 C 语言开源项目:Triggerhappy

news2024/10/2 10:35:17

这几天在知乎上看到了一个好问题:

有哪些值得推荐的小型 C 语言开源项目?

题主很可能是想要一个这样的开源项目:功能小巧、代码质量高,可读性好,以便自己循序渐进地学习 C 语言。

作为一个嵌入式开发人员,这样的开源项目还是接触得挺多的。
 

今天就给大家推荐一个:Triggerhappy。

老吴以前也写过一些关于 Triggerhappy 的文章,和以往不同,今天会以更全局地眼光去拆解这个项目。

开始 Enjoy 吧!

Triggerhappy 是什么?

简单地说,Triggerhappy 是一个监测输入事件的守护进程。

它会根据配置文件的内容,监测 /dev/input/event* 设备,然后执行用户预先配置的命令。

例如你的板子上有一个红外接收器,你可以很轻松地使用 Triggerhappy 来实现响应红外遥控器的按键事件。

Triggerhappy 非常的小巧,大约只有 80K,非常适合嵌入式场景。
 

学习 Triggerhappy 能学到什么?

1、模块化

2、数据结构

3、文本解析

4、单例程序的实现

5、信号的用法

6、IO 多路复用

7、输入设备的访问

8、进程的创建

9、本地 socket 的用法
 

Triggerhappy 的代码特点

Triggerhappy 的整体代码风格和 Linux 设备驱动的代码风格很像,会用一个结构体来描述对象,然后用一个链表将多个对象管理起来。

功能划分很清晰,大约有 7、8个功能模块,每一个模块的实现都非常的干净利索,代码不超过 300 行,而且风格统一。

综合来看,符合 UNIX 的设计哲学:简单实用,且内容丰富,是一个非常适合练习 Linux 应用编程的开源项目。
 

Triggerhappy 怎么用?

Triggerhappy 的用法很简单。

$ thd --dump /dev/input/event2
EV_KEY KEY_A 1 /dev/input/event2
EV_KEY KEY_A 0 /dev/input/event2
EV_KEY KEY_B 1 /dev/input/event2
EV_KEY KEY_B 0 /dev/input/event2

上面的命令会从 /dev/input/event2 中读取输入事件,并打印出来。
 

另外,还可以通过配置文件设置事件处理器:

$ cat /etc/triggerhappy.d/triggerhappy.conf
# <event name> <event value> <command line>
KEY_VOLUMEUP 1  /usr/bin/amixer set Master 5%+
KEY_VOLUMEUP 2  /usr/bin/amixer set Master 5%+
KEY_VOLUMEDOWN 1  /usr/bin/amixer set Master 5%-
KEY_VOLUMEDOWN 2  /usr/bin/amixer set Master 5%-

1 表示 pressing,2 表示 holding。

$ thd --triggers /etc/triggerhappy.d/triggerhappy.conf /dev/input/event*

这样运行后,我们就可以通过 KEY_VOLUMEUP、KEY_VOLUMEDOWN 控制音量了。
 

最后,Triggerhappy 还支持通过 socket 通讯进行命令行控制:

$ thd --socket /var/run/triggerhappy.socket --triggers /etc/triggerhappy.d/ /dev/input/event*

# 动态添加或移除设备
$ th-cmd --socket /var/run/triggerhappy.socket --add /dev/input/event0
th-cmd --socket /var/run/triggerhappy.socket --remove /dev/input/event3

这是一种很实用的设计,工作里,很多时候我发现自己都需要在不重新启动程序的情况动态地通知程序做某些事情。
 

Triggerhappy 怎么实现?

Triggerhappy 大致做了下面这些事情。
 

1、解析配置文件。

根据配置文件创建相应的 trigger,一个 1 trigger 代表一条事件触发规则,trigger 都挂在链表 trigger_list 上:

typedef struct trigger {
 int type;   // 类型
 int code;   // 键码
 int value;  // 键值
    [...]
 char *action; // 事件发生时应执行的命令
 struct trigger *next;
} trigger;

解析过程大致是使用 getline() 读取一行数据,然后用 strdup() 复制出来,最后再用 strtok_r 切割出按键、键值、执行命令。
 

2、创建 socket 通讯、信号处理等辅助设施。

这些都是非核心功能,只是让 Triggerhappy 变得更易用。

int bind_cmdsocket(char *name);
struct command *read_command(int cmd_fd);
int send_command(int cmd_fd, enum command_type type, char *param, int passfd, int exclusive, char *tag);
int connect_cmdsocket(char *name);

Triggherhappy 包含 2 个可执行程序:后台服务程序 thd,命令行工具 thd-cmd。

thd 会调用 bind_cmdsocket() 创建一个 local socket,thd-cmd 通过 connect_cmdsocket() 连接它。接着 thd-cmd 可以通过 send_command() 发送命令,thd 则通过 read_command() 接收命令。
 

3、根据命令行参数创建 devices。

1 个 device 代表 1 个输入设备,所有的 device 都会挂在链表 device_list 上。

typedef struct device {
 int fd;
 char *devname;
 struct device *next;
} device;
void add_device(char *dev, int fd, int excl, char *tag);
int remove_device(char *dev);
void clear_devices(void);

add_device() 会构造一个 device,并且 open() 设备以得到文件描述符 fd。
 

4、不断循环从所有 devices 中读取数据。

这个步骤是 Triggerhappy 的核心功能,是一个基于 select() 的eventloop。

这个 eventloop 很简单,就是用 select() 检测所有 devices,当有数据可读时,对所有 devices 都调用 read_event() 读取数据:

点击查看大图

读到数据后,会根据键值找到相应的 trigger,并执行 trigger 对应的命令,实现方法就是 fork() + system():

点击查看大图

到此,Triggerhappy 的核心流程就分析完毕了。
 

总结

Triggerhappy 功能划分很清晰,大约有 7、8个功能模块,每一个模块的实现都非常的干净利索,代码都不超过 300 行,且风格和 Linux 设备驱动类似。

综合来看,Triggerhappy 符合 UNIX 的设计哲学。它简单实用,内容丰富,代码清晰,是一个非常嵌入式开发人员练习 Linux 应用编程的开源项目。

 

点击链接加入群聊【C语言/C++编程学习基】:的个人空间_哔哩哔哩_Bilibili,的主页、动态、视频、专栏、频道、收藏、订阅等。哔哩哔哩Bilibili,你感兴趣的视频都在B站。icon-default.png?t=M85Bhttps://space.bilibili.com/1827181878?spm_id_from=333.1007.0.0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

趁年轻,大胆闯

趁年轻&#xff0c;大胆闯如果我是20岁&#xff0c;我会拿出未来的十年&#xff0c;全力已赴的赚钱&#xff0c;折腾&#xff0c;不要任何安全感。 出来创业&#xff0c;就是为100倍以上的赔率来的。

HTTPS

一、HTTPS是什么 HTTPS也是一个应用层协议&#xff0c;是在HTTP协议的基础上引入了一个加密层。 由于HTTP协议内容一般都是本文方式明文传输的&#xff0c;这就导致它在传输过程中会出现被篡改的情况。 经典案例就是万恶的“运营商劫持”&#xff01; 除了运营商可以劫持&a…

如何快速从零开始搭建一个前端项目

2022 年了&#xff0c;如何快速从零开始搭建一个合适的前端项目&#xff1f; 准备工作 首先本地需要安装好 node 环境以及包管理工具&#xff0c;推荐直接使用 pnpm&#xff0c;也可以通过 pnpm 来直接管理 nodejs 版本。 pnpm 安装&#xff1a; # Mac or Linux curl -fsSL…

SpringMVC 环境配置

文章目录引入1、MVC的概念2、Spring MVC基本原理一、导入坐标&#xff08;导包&#xff09;导入Spring MVC所需要的jar包二、新建springmvc-config.xml文件三、配置web.xml四、 创建Controller五、配置SpringMVC配置文件六、配置页面其他引入 Spring Web MVC是一种基于Java的实…

cv算法工程师学习教程

前言一&#xff0c;计算机系统 1.1&#xff0c;计算机系统书籍1.2&#xff0c;设计模式教程 二&#xff0c;编程语言 2.1&#xff0c;C 学习资料2.2&#xff0c;Python 学习资料 三&#xff0c;数据结构与算法 3.1&#xff0c;数据结构与算法课程3.2&#xff0c;算法题解 四&am…

数字信号处理及python实现(三)

数字信号处理及python实现三抽样引起的混叠抽样的频域视图样本重建信号拟合正弦波线性与多项式内插理想低通滤波器这是参考知乎的数字信号处理及matlab实现的python实现版本&#xff0c;参考连接 上一期:数字信号处理及python实现(二) 项目文件结构 test为测试文件&#xff…

【Vue】Vue开发实战之我的笔记(ch18-ch27)--20221115

参考https://blog.csdn.net/yfm120750310/article/details/111353963 18 | 为什么需要Vuex 18.1 为什么需要Vuex provide和inject虽然能够实现层层传递的数据管理&#xff0c;但对于一个大的管理系统而言会显得有些繁琐&#xff0c;我们需要一个大型的状态管理系统。 Vuex不…

甘特图是什么?如何快速搭建?

甘特图是什么&#xff1f; 甘特图是一种条状图&#xff0c;直观展示项目进展随时间的走势及联系。其中&#xff0c;项目时间由横轴表示&#xff0c;项目活动由纵轴表示。整体线条表示整个项目期间内&#xff0c;计划和实际的活动完成情况。甘特图起初用于美国胡佛水坝和美国洲…

cpe(通用平台枚举)命名规范及python CPE库实战

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

一文看懂Linux 页表、大页与透明大页

一、 内存映射与页表 1. 内存映射 我们通常所说的内存容量&#xff0c;指的是物理内存&#xff0c;只有内核才可以直接访问物理内存&#xff0c;进程并不可以。 Linux 内核给每个进程都提供了一个独立的虚拟地址空间&#xff0c;并且这个地址空间是连续的。这样&#xff0c;…

如何用Python 快速搭建HTTP服务器

Python具有语法简单、语句清晰的特点,而且Python的兼容性比较好,可以将其他语言制作的模块联结起来,具有强大且丰富的库,封装后可以轻松调用,因此成为编程语言中的“网红“&#xff0c;甚至被称为非计算机从业者的第一语言。 Python在IT就业市场也是最受欢迎、最热门的技术技能…

SpringBoot整合Redis

SpringBoot整合Redis 文章目录SpringBoot整合Redis一 .简介1. redie是什么&#xff1f;2. redie的使用场景&#xff1f;二 . 使用1. 引入依赖2. 配置文件3. 启动redis4. 创建Redis工具类5. 创建测试类6. 查看效果一 .简介 1. redie是什么&#xff1f; Redis是现在最受欢迎的N…

图解计算机的存储器金字塔

本文已收录到 GitHub AndroidFamily&#xff0c;有 Android 进阶知识体系&#xff0c;欢迎 Star。技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好&#xff0c;我是小彭。 在计算机组成原理中的众多概念中&#xff0c;开发者接触得最…

LeetCode-剑指43-1-n整数中出现1的次数

1、逐位统计 我们统计每一位k上面可能出现1的次数&#xff1a;1、对于每一位k上面的出现的1&#xff0c;我们首先统计其出现(n/10k)10k−1(n/10^k)\times10^{k-1}(n/10k)10k−1次的1&#xff1b;2、考虑到存在余数的情况&#xff0c;我们还需要比较剩余余数中出现1的次数&…

浅谈HTTP缓存与CDN缓存的那点事

HTTP缓存与CDN缓存一直是提升web性能的两大利器&#xff0c;合理的缓存配置可以降低带宽成本、减轻服务器压力、提升用户的体验。而不合理的缓存配置会导致资源界面无法及时更新&#xff0c;从而引发一系列的衍生问题。本文将分别将从HTTP缓存与cdn缓存的规则、流程、配置入手&…

XSS挑战之旅1-10关

文章目录前言第1关第2关第3关第4关第5关第6关第7关第8关第9关第10关前言 漏洞介绍&#xff1a;XSS漏洞 参考文章&#xff1a;XSS挑战之旅 游戏规则&#xff1a;触发alert()弹窗&#xff0c;进入下一关 第1关 进入第一关 随便输入一下&#xff0c;观测输出&#xff0c;看源代…

还在为数据库事务一致性检测而苦恼?让Elle帮帮你,以TDSQL为例我们测测 | DB·洞见#7

数据库用户通常依赖隔离级别来确保数据一致性&#xff0c;但很多数据库却并未达到其所表明的级别。主要原因是&#xff1a;一方面&#xff0c;数据库开发者对各个级别的理解有细微差异&#xff1b;另一方面&#xff0c;实现层面没有达到理论上的要求。 用户在使用或开发者在交…

147. SAP UI5 SmartTable 控件的使用介绍

本文来自笔者 SAP 开发技术交流知识星球内一位朋友的提问: smartfilter bar 有个输入框Cost Element绑定了cds实现value help 请问其对应的suggestion功能是通过cds的注解实现的嘛? 要回答这个问题,我们必须首先掌握 SAP UI5 SmartTable 控件的使用方式,然后才能深入探究 …

【Tensorflow】使用Tensorflow自定义模型和训练

Tensorflow的核心与NumPy非常相似&#xff0c;但具有GPU支持&#xff1b;Tensorflow支持分布式计算&#xff08;跨多个设备和服务器&#xff09;。 像NumPy一样使用TensorFlow 运算符是在Python 3.5 中添加的&#xff0c;用于矩阵乘法&#xff0c;等效于 tf.matmul() 函数。…

C++数据结构迷宫哈希表二叉树

C数据结构迷宫哈希表二叉树 《数据结构》应用系统设计——迷宫问题 问题描述:设计算法求出并显示从入口点到出口点可沿八个方向前进的一条通路&#xff0c;或显示没有通路 难度:易 基本要求: (1)键盘(或文件)输入迷宫行数m和列数n&#xff0c;计算机随机生成迷宫(或从文件读入…