news 2026/4/23 13:49:25

基于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/4/23 10:18:26

8%转化率背后的真相:那些被你忽略的“愤怒点击”与“幽灵数据”

第一章&#xff1a;别盯着那8%发愁了&#xff0c;先把“数据地基”刨开看看在线教育这行当&#xff0c;流量贵得跟金子似的。你花大价钱投了流&#xff0c;结果转化率只有8%&#xff0c;这哪是漏斗啊&#xff0c;简直就是个底下穿了孔的破篮子。行业平均线在15%左右&#xff0c…

作者头像 李华
网站建设 2026/4/22 18:23:47

低查重AI教材生成工具来袭,快速编写高质量教材,轻松搞定教学资料!

在编写教材的过程中&#xff0c;进度总是能准确踩到“慢节奏”的雷区。尽管框架和相关资料已经准备好&#xff0c;创作的过程依然卡于内容的撰写。常常是重复推敲一句话半个小时&#xff0c;依旧觉得表述不够恰当&#xff1b;章节之间的衔接更是费尽脑汁也找不到合适的连接语&a…

作者头像 李华
网站建设 2026/4/23 10:18:31

智慧医疗RAG系统构建检索系统避坑

1. 解决"向量嵌入的领域失配"问题 避坑实践&#xff1a; 领域适配嵌入模型选择&#xff1a; class MedicalEmbeddingModel:def __init__(self):# 尝试多个领域专用模型self.models {"sentence-transformers/all-mpnet-base-v2": "通用",&quo…

作者头像 李华
网站建设 2026/4/23 6:53:51

社会网络仿真软件:Pajek_(12).案例分析与应用实践

案例分析与应用实践 在上一节中&#xff0c;我们介绍了Pajek的基本功能和使用方法。本节将通过具体的案例分析和应用实践&#xff0c;帮助读者更好地理解和掌握Pajek在社会网络分析中的应用。我们将从数据准备、网络构建、可视化、分析方法等多个方面进行详细探讨&#xff0c;…

作者头像 李华
网站建设 2026/4/23 10:18:31

2026年2月热点内容趋势:测试从业者的黄金赛道

一、政策赋能&#xff1a;技术服务业补贴的实操指南 2026年一季度多地推出科研技术服务业增产奖励政策&#xff0c;对符合要求的企业按综合发展质效增量的5‰发放现金奖励&#xff08;单企最高20万元&#xff09;。对测试从业者而言&#xff0c;需重点关注三大指标&#xff1a…

作者头像 李华