news 2026/2/12 6:34:29

基于wiringPi库写的一些代码(二)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于wiringPi库写的一些代码(二)

1. linux的热拔插udev机制

1.1 热拔插:在开机和运行的状态下,可以安全地安装或者转移硬件,不需要关闭电源或者重启。

1.2 udev

udev是一个设备管理工具,udev以守护进程的形式运行,通过侦听内核发出来的event(事件)来管理/dev目录下的设备文件。udev在用户空间运行,而不在内核空间 运行。它能够根据系统中的硬件设备的状态,动态更新设备文件包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。

1.3 例子

例如,在上述的实验中:

手机刚刚插进去开发板之后,应用程序是不能使用手机的(因为adb(应用层)找不到对应usb设备文件(应用层是没有权限使用这个设备文件)),例如执行adb会不成功。

一开始,当有usb设备(手机)接入开发板的时候,是内核先知道usb设备的(这里把设备接入开发板,仅仅只是实现了让内核知道而已,可以使用dmesg可以知道设备的信息,但是在应用层是不认识这个设备的,应用层是没法访问到设备的(没权限),怎样才能认识这个设备并为这个设备创建文件 --> udev机制)。

但是在应用层(应用程序adb)是没法访问到usb设备的,虽然此时在dev目录下还有对应的usb设备文件(找不到对应的手机设备文件),但是在应用层就没法访问到usb设备的(没权限)。怎样可以让应用层认识设备并创建设备文件 -->使用udev规则。

只有当udev检测到内核中有侦听到usb设备接入的信息并且添加了对应的udev规则,才会在/dev/bus/usb/001那里动态创建设备文件(并且这这个文件的权限是0666),之后adb程序(应用层)能访问到usb设备(手机)。

但是前提必须要有下面对应的规则才能配置对应的设备文件,如果没有这条规则,就不会为新接入的设备配置对应的设备文件权限(usb设备)。

当在/etc/udev/rules.d这个目录下创建vivo-android.rules(赋予usb设备可读可写权限)这个文件给 udev服务和使用之后,应用层可以访问usb设备了(可以使用adb去访问了)。

简单说:没有udev规则,udev机制就不知道如何管理设备,没有udev机制,规则就只是一堆文本文件。两者紧密结合,共同实现 Linux 的动态设备管理。

2. 守护进程

2.1 概念:

Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行
某种任务或等待处理某些发生的事件。它不需要用户输入就能运行并且能提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogdweb服务器httpd、邮件服务器sendmail和数据库服务器
mysqld等。守护进程的名称通常以d结尾。
例如:udev守护进程,它能够根据系统中的硬件设备的状态动态来更新设备文件,包括设备文件的创建,删除等。

2.2 基本特点

• 生存周期长[非必须],一般操作系统启动的时候就启动,关闭的时候关闭。
• 守护进程和终端无关联,也就是他们没有控制终端,所以当控制终端退出,也不会导致守护进程退出。
• 守护进程是在后台运行,不会占着终端,终端可以执行其他命令。
• 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出
了,所以它是一个由init继承的孤儿进程。
• 如图:
• ppid = 0:内核进程,跟随系统启动而启动,生命周期贯穿整个系统。
• cmd列名带[]这种,叫内核守护进程。
• 老祖init:也是系统守护进程,它负责启动各运行层次特定的系统服务,所以很多进程的PPIDinit,也负责收养孤儿进程。
• cmd列中名字不带[]的普通守护进程(用户守护进程)。

2.3守护进程开发方式

• 直接借助damon()函数完成。
#include <unistd.h> /* int daemon(int nochdir, int noclose); 函数参数: nochdir:为0时表示将当前目录更改至“/”,转换工作目录和脱离终端 noclose:为0时表示将标准输入、标准输出、标准错误重定向至“/dev/null” 返回值:成功则返回0,失败返回-1 */ #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> //C 库函数 char *asctime(const struct tm *timeptr) 返回一个指向字符串的指针,它代表了结构 //struct timeptr 的日期和时间。 //C 库函数 struct tm *localtime(const time_t *timer) 使用 timer 的值来填充 tm 结构。 //timer 的值被分解为 tm 结构,并用本地时区表示。 /* struct tm { int tm_sec; 秒,范围从 0 到 59 int tm_min; 分,范围从 0 到 59 int tm_hour; 小时,范围从 0 到 23 int tm_mday; 一月中的第几天,范围从 1 到 31 int tm_mon; 月份,范围从 0 到 11 int tm_year; 自 1900 起的年数 int tm_wday; 一周中的第几天,范围从 0 到 6 int tm_yday; 一年中的第几天,范围从 0 到 365 int tm_isdst; 夏令时 }; */ static bool flag = true; void handler(int sig) { printf("I got a signal %d\nI'm quitting.\n", sig); flag = false; } int main() { time_t t; int fd; //创建守护进程 if(-1 == daemon(0, 0)){ printf("daemon error\n"); exit(1); } //设置信号处理函数 struct sigaction act; act.sa_handler = handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGQUIT, &act, NULL)){ printf("sigaction error.\n"); exit(0); } //进程工作内容 while(flag){ fd = open("/home/orangepi/daemon.log", O_WRONLY | O_CREAT | O_APPEND,0644); if(fd == -1){ printf("open error\n"); } t = time(0);//获取当前时间戳 char *buf = asctime(localtime(&t)); write(fd, buf, strlen(buf)); close(fd); sleep(10); } return 0; } //sudo vi /etc/rc.local 开机自启动,绝对路径加程序名字,一开机就能启动这个守护进程了。

3. 守护进程的应用

3.1守护进程不让控制程序退出

#include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> #include <stdbool.h> static bool flag = true; void handler(int sig){ printf("I got a signal %d\nI'm quitting.\n", sig); flag = false; } int judMent(){ FILE *file; char buffer[128] = {'\0'}; char *cmd = "ps -elf |grep douyinUtils|grep -v grep"; file = popen(cmd, "r"); fgets(buffer, 128, file); if(strstr(buffer, "douyinUtils") != NULL){ return 0; }else{ return -1; } printf("BUFFER:%s\n",buffer); } int main(){ time_t t; int fd; //创建守护进程 if(-1 == daemon(0, 0)){ printf("daemon error\n"); exit(1); } //设置信号处理函数 struct sigaction act; act.sa_handler = handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(sigaction(SIGQUIT, &act, NULL)){ printf("sigaction error.\n"); exit(0); } //进程工作内容 while(flag){ if( judMent() == -1){ system("/home/orangepi/hardwareSoft/douyin/douyinUtils /dev/ttyS5 &"); } sleep(2); } return 0; } //开机启动: // /home/orangepi/hardwareSoft/douyin/douyinUtils /dev/ttyS5 & 添加了&变成后台程序。 // /home/orangepi/hardwareSoft/douyin/shouhuDouyin

3.2守护进程和后台进程的区别

• 守护进程和终端不挂钩,后台进程能往终端上输出东西(和终端挂钩)。
• 守护进程关闭终端时不受影响,守护进程不会随着终端的退出而退出。

4. udev规则的补充

• 规则文件是 udev里最重要的部分,默认是存放在/etc/udev/rule.d/ 下。所有的规则文件必须以 ".rules" 为后缀名。这是一个简单的规则:KERNEL=="sda", NAME="my_root_disk", MODE="0660"

• KERNEL 是匹配键,NAMEMODE是赋值键。这条规则的意思是:如果有一个设备的内核名称为sda,则该条件生效,执行后面的赋值:在/dev下产生一个名为my_root_disk的设备文件,并把设备文件的权限设为 0660
• udevadm info --attribute-walk --name=/dev/设备名字 这个指令可以查设备的所有信息。

4.1 udev匹配键

ACTION:事件(uevent)的行为,例如:add(添加设备)、remove(删除设备); KERNEL:内核设备名称,例如:sda,cdrom; DEVPATH:设备的 devpath 路径; SUBSYSTEM:设备的子系统名称,例如:sda 的系统为 block; BUS:设备在 devpath 里的总线名称,例如:usb; DRIVER:设备在 devpath 的设备驱动名称,例如:ide-cdrom; ID:设备在 devpath 里的识别号; SYSFS{filename}:设备的 devpath 路径下,设备的属性文件 "filename" 里的内容; ENV{key}:环境变量。在一条规则中,可以设定最多五条环境变量的 匹配键; PROGRAM:调用外部命令; RESULT:外部命令 PROGRAM 的返回结果。
• 例如,自动挂载U盘的规则:
ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", RUN{program}+="/bin/mkdir
/media/%k" ,RUN{program}+="/usr/bin/systemd-mount --no-block --collect $devnode
/media/%k
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/10 21:50:58

低查重AI教材编写攻略,掌握这些工具轻松搞定教材生成!

谁没有面对过教材框架编写的困惑呢&#xff1f; 坐在电脑前盯着空白的文档&#xff0c;思绪如潮水般涌来&#xff0c;却又不知从何下手——是先解释概念&#xff0c;还是先引用实例呢&#xff1f;章节划分是按照逻辑走&#xff0c;还是按课程的时间来安排&#xff1f;修改的大…

作者头像 李华
网站建设 2026/2/8 20:18:31

寒潮中的测试韧性:2026二月热点下的合规升级与协作实战

一、极端天气场景&#xff1a;稳定性测试的实战启示 2月初冷空气席卷中东部&#xff0c;多地交通系统面临严峻考验。这恰似高并发场景下的系统压力测试——湖北冻雨中的"除冰保畅应急班"通宵作业&#xff0c;正是对测试工程师的生动启示&#xff1a; 容灾设计验证&a…

作者头像 李华
网站建设 2026/2/6 10:44:14

震撼!低查重AI教材生成,让AI写教材成为高效创作新选择

AI写教材&#xff1a;变革传统&#xff0c;提升效率与质量 撰写教材需要大量资料&#xff0c;但传统的资料整合方式已无法满足快速变化的需求。过去&#xff0c;我们常常需要从不同渠道&#xff0c;如课标文件、学术论文和教学案例中寻找信息&#xff0c;这样一来&#xff0c;…

作者头像 李华
网站建设 2026/2/11 6:36:44

智慧医疗RAG系统构建数据准备与预处理

1. 解决"文档分块的简单粗暴化"问题 原始问题&#xff1a;直接使用LangChain的RecursiveCharacterTextSplitter&#xff0c;固定512字符分块。 避坑实践&#xff1a; 多策略分块器设计&#xff1a; class MedicalDocumentChunker:def __init__(self):# 针对不同文…

作者头像 李华
网站建设 2026/2/12 14:59:02

重新定义直播音频:obs-vst插件的零成本专业音效解决方案

重新定义直播音频&#xff1a;obs-vst插件的零成本专业音效解决方案 【免费下载链接】obs-vst Use VST plugins in OBS 项目地址: https://gitcode.com/gh_mirrors/ob/obs-vst 在直播创作的世界里&#xff0c;声音的质量往往决定了观众的去留。你是否也曾经历过这样的尴…

作者头像 李华
网站建设 2026/2/7 3:04:47

DeepSeek辅助总结postgresql wiki提供的数独求解器

原文地址&#xff1a;https://wiki.postgresql.org/wiki/Sudoku_solver 数独求解器 兼容的 PostgreSQL 版本 9.0 编写语言 SQL 依赖项 无 这是我编写的一个不算特别快的数独求解器。输入格式为&#xff1a;‘_’ 代表空单元格&#xff0c;而 ‘b’ 到 ‘j’ 代表数字 1…9。…

作者头像 李华