Linux的UDEV机制


udev 机制引入:

 手机接入Linux热拔插相关
a. 把手机接入开发板
b. 安装adb工具,在终端输入adb安装指令: sudo apt-get install adb
c. dmeg能查看到手机接入的信息,但是输入adb devices会出现提醒
dinsufficient permissions for device: user in plugdev group; are your udev
rules wrong?
d. 配置文件,以支持USB设备的热拔插,支持UDEV的机制
在/etc/udev/rules.d 文件夹下创建规则文件
cd /etc/udev/rules.d/
sudo vim 51-android.rules
在文件中添加内容 SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"
e. 在手机开发者选项中,打开USB调试,重新

udev 概念引入: 

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


------------------------------------------------


图形理解: 

下面是一张linux 架构图: 

Linux 下面 一切都是文件  -- open 来打开

调用过程: 

我们在应用层 调用  open 函数(存放在库函数中)  -->  库函数中的open 系统调用 sys_open
 --> 系统调用的 sys_read  再调用内核的 kernel_open  -->  内核的kernal_open 负责调用硬件的寄存器处理 


-------------------------------------

查看进程基础与技巧: 

一般形式:

ps -elf | grep a.out  

#unix标准风格组合,其中-e 代表列出所有进程,-l 代表长格式,-f 代表完整的格式

消除grep干扰

在平时查看进程得到时候一般都会 多出一个 grep 进程---> 影响判断

比如下图 中的第二个进程  grep: 


我们可以这样

忽略 grep进程:   ps -elf | grep a.out | grep -v grep  

       //检索 a.out 的进程,同时忽略 grep 进程

& -- 指定进程后台运行


./a.out &    // 后台进程 a.out

//  普通程序 依托 于终端,终端关闭就结束

init -- 进程 pid  - 1 

显示行号

    显示行号:末行模式下输入 **set number** 或 **set nu** 回车
    关闭行号:末行模式下输入 **set nonumber** 或 **set nonu** 回车

守护进程:

概念

Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行
某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个
系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。

常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。守护进程的名称通常以d结尾

UDEV守护进程,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。


基本特点


1)生存周期长[非必须],一般操作系统启动的时候就启动,关闭的时候关闭。
2)守护进程和终端无关联,也就是他们没有控制终端,所以当控制终端退出,也不会导致守护进程退出
3)守护进程是在后台运行,不会占着终端,终端可以执行其他命令

4)一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程
linux操作系统本身是有很多的守护进程在默默执行,维持着系统的日常活动。大概30-50个

普通守护进程   和 内核适合进程

ppid = 0:内核进程,跟随系统启动而启动,生命周期贯穿整个系统。
cmd列名带[]这种,叫内核守护进程
老祖init:也是系统守护进程,它负责启动各运行层次特定的系统服务;所以很多进程的PPID是init,也负责收养孤儿进程。
cmd列中名字不带[]的普通守护进程(用户集守护进程)

图解如下:

======================================================

守护进程的开发: 

daemon()函数


直接借助daemon()函数完成。 daemon  -- 守护进程

头文件: 

#include <unistd.h>

函数原型: 
int daemon(int nochdir, int noclose);
函数参数:
nochdir:为0时表示将当前目录更改至“/”
noclose:为0时表示将标准输入、标准输出、标准错误重定向至“/dev/null”
返回值:
成功则返回0,失败返回-1

守护进程 和 后台进程区别

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

额外补充:

//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; 夏令时
};

----------------------------------------------------------
注: bool  类型变量linux C不认识,需要包含 一个头文件: <stdbool.h>

exit(0),exit(1) 和 exit(-1)的区别

exit(0)表示程序正常退出;除了0之外,其他参数均代表程序异常退出,如:exit(1),exit(-1)。
exit(1)和exit(-1)是分别返回1和-1到主调程序。
exit(0)则是返回0。exit(0)表示程序正常退出,非0表示非正常退出。

log文件是记录系统活动信息的几个文件,通过它可以帮助快速定位问题,常见的有

----------------------------------------------------------


验证程序:

case1:  创建一个守护进程 , 创建/打开~目录下的daemon.log文件,每10s 写入一次系统时间到文件中

#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) // 收到信号 后就 把 flag =false ---> 进入 main 里面的判断 -- 需要退出了
{
printf("I got a signal %d\nI'm quitting.\n", sig);
flag = false;
}

int main()
{
time_t t;
int fd;
//创建守护进程 int daemon(int nochdir, int noclose); -- 返回值 成功0 ,失败-1
// 第一个参数 -- nochdir:为0时表示将当前目录更改至“/”
// 第二个参数 -- noclose:为0时表示将标准输入、标准输出、标准错误重定向至“/dev/null”
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)) // if 这个进程收到 SIGQUIT 信号,退出进程 exit(0) -正常退出
{
printf("sigaction error.\n");
exit(0);
}

//进程工作内容
while(flag) // flag  没收到退出信号的时候一直在执行 以下工作
{
fd = open("/home/orangepi/daemon.log", O_WRONLY | O_CREAT | O_APPEND,0644); // 在我们的~目录下创建daemon.log文件
if(fd == -1)
{
printf("open error\n");
}
t = time(0);
// asctime -- 把系统默认的时间类型 数据转换为 字符串类型的   localtime 拿到本地时间
char *buf = asctime(localtime(&t));
write(fd, buf, strlen(buf)); // 将获得时间数据写入文件
close(fd);
sleep(10);  // 每10s写入一次
}
return 0;
}

-------------------------------------------------------

 
 

 开机启动守护进程: 


sudo vi /etc/rc.local

里面添加我们创建的守护进程的 可执行文件 tdaemon , 不要用a.out, 使用 -o 改个名

/home/orangepi/hardwareSoft/udev/tdaemon

注意:  这里一定要用绝对路径,不要用相对路径,因为我们的守护进程会调到根目录,相对路径不一定能访问到

/home/orangepi/douyin/douyin /dev/ttyS5
/home/orangepi/douyin/shouhuDouyin

===================================================

需求:要求语音刷手机的程序一直保持运行,防止应用程序崩溃意外,先实现case2


case2 : 编写判断某进程是否在运行的程序:

  1 #include<stdio.h>
  2 #include<string.h>
  3
  4 int main()
  5 {
  6
  7     FILE *file;
  8     char buf[128]={'\0'};
  9     char *cmd="ps -elf | grep douyin | grep -v grep "; // 通过指令查看
 10     file = popen(cmd,"r");
 11     fgets(buf,128,file);
 12
 13     printf("buf: %s\n",buf);
 14     if(strstr(buf,"douyin")!=NULL){ // 子串没有进程名字,什么进程不运行
 15     puts("douyinPro is running");
 16     }
 17     else {
 18     puts("douyinPro is exited");
 19     }
 20
 21
 22     return 0;
 23 }


----------------------------------------
以popen的 方式去运行 cmd
同时,能把指令执行的结果拿到手

---------------------------------------------------------------------


case 3 :  守护进程实现 关不掉是 声控刷抖音

声控刷抖音代码参考这篇:串口小项目 - 声控刷抖音-CSDN博客

/home/orangepi/douyin

注意:  守护进程会默认把 路口切换到根目录,执行cmd 的时候要给绝对路径

效果图: 

这里kill 程序,模拟程序崩溃

可以看到 我们的抖音进程 一直杀不死, 因为守护进程 一直在后台执行着
只要抖音程序一被关掉就会马上重新创建一个新的的进程

#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>


int  judMent() // 这就是case2的 判断进程是否运行函数
{
    FILE *file;
    char buf[128]={'\0'};
    char *cmd="ps -elf | grep douynUnit | grep -v grep ";
    file = popen(cmd,"r");
    fgets(buf,128,file);

    printf("buf: %s\n",buf);
    if(strstr(buf,"douyin")!=NULL){
    return 0;
    }
    else {
    return -1;
    }

}


static bool flag = true; // 初始化为true -- 让main 中while一直执行


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)) //收到信号SIGQUIT,执行act -这个槽(处理)函数
    {
        printf("sigaction error.\n");
        exit(0);
    }
    //进程工作内容
    while(flag)
    {
        if(judMent() == -1)//进程被杀死后再打开 -- 杀不死的进程
            fd = system("/home/orangepi/douyin/douyinUnit /dev/ttyS5 &");
       sleep(2);
    }
    return 0;
}

--------------------------------------------------------------------------------

UDEV 配置文件:

规则文件是 udev 里最重要的部分,默认是存放在 /etc/udev/rule.d/ 下。所有的规则文件必须以 ".rules"为后缀名


简单的规则举例:


KERNEL=="sda", NAME="my_root_disk", MODE="0660"


KERNEL 是匹配键,NAME 和 MODE 是赋值键。这条规则的意思是:如果有一个设备的内核名称为sda,则该条件生效,执行后面的赋值:在 /dev 下产生一个名为my_root_disk 的设备文件,并把设备文件的权限设为 0660。

查看设备详细信息

udevadm info --attribute-walk --name=/dev/设备名字

比如我的手机在这里:   /dev/bus/usb/001/003       -- 只需要把 = 后的改为这串即可

udevadm info --attribute-walk --name=/dev/bus/usb/001/003

查询到的信息可以写入设备的规则文件中,比如: 
    ATTRS{idProduct}=="0002"
    ATTRS{idVendor}=="1d6b"

//多乐两天匹配键 -- 来判断设备

如下: 


==================


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盘的自动挂载:

一般情况:(手动挂载)

一般U盘插入orangepi 需要挂载才能查看里面内容

// 将 u 盘挂载到 mnt 下,才能查看里面内容
sudo mount /dev/sda  /mnt/

然后 就可以 cd/mnt  去查看我们的 U盘 内容了

要取消挂载: sudo umount /mnt

也可以通过上面的指令来详细查看U盘数据: udevadm info --attribute-walk --name=/dev/设备名字
比如: U盘的匹配条件:

    KERNELS=="sdb"
    SUBSYSTEMS=="block"

配置规则文件, 实现自动挂载U盘


 在规则文件下(比如我们在/etc/udev/rule.d/下创建 usbBlock.rules ),加入:
支持挂载多个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"


 然后重启udev 服务即可:
sudo service udev restart

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

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

相关文章

【Java】HashMap、HashTable和ConcurrentHashMap的区别

文章目录 区别一、HashMap1.1基本定义与特性1.2工作原理与实现1.3常用方法1.4性能与优化 二、HashTable三、ConcurrentHashMap3.1基本特点3.2实现原理3.3常用方法3.4适用场景3.5性能优化 HashTable、HashMap和ConcurrentHashMap之间的区别主要体现在线程安全、继承关系与实现接…

kaggle 泰坦尼克号2 得分0.7799

流程 导入所要使用的包引入kaggle的数据集csv文件查看数据集有无空值填充这些空值提取特征分离训练集和测试集调用模型 导入需要的包 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarni…

从C到JAVA之学习JAVA的第一周笔记

文章目录 java语言概述JDK与JRE编写执行过程第一份java代码解读编写编译运行其他 注释三种注释方法 java API文档关键字标识符数据类型基本数据类型自动类型提升规则引用数据类型 string概述String与基本数据类型的变量间的运算 运算符键盘录入运行控制语句数组定义与静态初始化…

springboot no mapping for.....解决办法

这个问题是由于没有加入对应的GET,POST注解&#xff0c;导致映射失败&#xff0c;加入对应注解就ok了

JDK 11下载、安装、配置

下载 到Oracle管网下载JDK 11&#xff0c;下载前需要登录&#xff0c;否则直接点下载会出现502 bad gateway。 下载页面链接 https://www.oracle.com/hk/java/technologies/downloads/#java11-windows 登录 有些人可能没有Oracle账号&#xff0c;注册也比较慢&#xff0c;有需…

随笔05 我的创作纪念日(512天)

机缘 机缘这事儿&#xff0c;我在随笔系列博文里已经翻来覆去说了不少&#xff0c;这次就不再唠叨了&#xff0c;省得被小伙伴嫌弃成祥林嫂~&#x1f61c; &#x1f338;随笔01 我的创作纪念日&#xff08;128天&#xff09;_newmitbbs-CSDN博客 收获 我这一小片自留地&…

JavaEE 初阶篇-深入了解 File 文件操作(实现文件搜索、非空文件夹删除)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 File 文件概述 2.0 创建 File 类对象的方法 2.1 判断文件类型、获取文件信息的方法 2.2 创建文件、删除文件的方法 2.3 遍历文件夹的方法 3.0 文件搜索与删除 3.1…

WebSocket 快速入门 - springboo聊天功能

目录 一、概述 1、HTTP&#xff08;超文本传输协议&#xff09; 2、轮询和长轮询 3、WebSocket 二、WebSocket快速使用 1、基于Java注解实现WebSocket服务器端 2、JS前端测试 三、WebSocket进阶使用 1、如何获取当前用户信息 2、 后端聊天功能实现 一、概述 HTTP…

PVE grub resue错误修复 lvmid BUG

服务器断电后启动不起来&#xff0c;显示grub resue 找了半天没有找到修复方法。看官方文档有一处Recovering from grub “disk not found” error when booting from LVM 极为类似。https://pve.proxmox.com/wiki/Recover_From_Grub_Failure 下面是处理过程。 使用PVE 6.4启…

Leetcode算法训练日记 | day33

专题九 贪心算法 一、跳跃游戏 1.题目 Leetcode&#xff1a;第 55 题 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 …

机器学习(二)之监督学习

前言&#xff1a; 上一节大概讲解了几种学习方式&#xff0c;下面几张就具体来讲讲监督学习的几种算法。 以下示例中和都是权重的意思&#xff01;&#xff01;&#xff01; 注&#xff1a;本文如有错误之处&#xff0c;还请读者指出&#xff0c;欢迎评论区探讨&#xff01; 1…

MATLAB实现图片栅格化

MATLAB实现图片栅格化 1.读取图片&#xff1a;首先&#xff0c;你需要使用imread函数读取要栅格化的图片。 2.设置栅格大小&#xff1a;确定你希望将图片划分成的栅格大小&#xff0c;即每个栅格的宽度和高度。 3.计算栅格数量&#xff1a;根据图片的总尺寸和栅格大小&#…

Compose 布局

文章目录 Compose 布局ColumnColumn属性使用 RowRow属性使用 BoxBox属性使用 ConstraintLayoutLazyColumnLazyColumn属性使用使用多类型使用粘性标题回到顶部 LazyRowLazyRow属性使用 LazyVerticalGridLazyVerticalGrid属性使用 Compose 布局 Column Compose中的”垂直线性布…

F-logic DataCube3 SQL注入漏洞复现(CVE-2024-31750)

0x01 产品简介 F-logic DataCube3是一款用于光伏发电系统的紧凑型终端测量系统。 0x02 漏洞概述 F-logic DataCube3 /admin/pr_monitor/getting_index_data.php 接口处存在SQL注入漏洞,未经身份验证的攻击者可通过该漏洞获取数据库敏感信息,深入利用可控制整个web服务器。 …

计算机图形学:直线生成算法—DDA

DDA&#xff08;Digital Differential Analyzer&#xff0c;数字差分分析器&#xff09;算法是一种基本的直线生成算法&#xff0c;通常用于计算机图形学中。它通过将直线划分为若干个等间隔的小线段&#xff0c;然后在每个小线段中选择一个像素点进行绘制&#xff0c;从而近似…

产品原型图概念

产品原型图概念 产品原型图作用 如下图&#xff1a; 产品原型图的三种分类 线框图 通过【线段色块文字】描述产品页面。优点&#xff1a;制作快速。 缺点&#xff1a;传递信息容易遗漏。 应用&#xff1a;早期方案讨论&#xff0c;需要快速输出的场景&#xff0c;团队配合…

Learn ComputeShader 01 First Computer Shader

使用Unity版本&#xff1a;2019.4.12f1 整体流程&#xff1a; 1添加一个quad object并添加一个无光照材质 2.相机投影模式设置为正交 3.调整quad使其完全显示在相机内 4.创建脚本并且使用计算着色器覆盖quad的纹理 5.创建一个compute shader 前三步完成以后结果应该是这…

网络基础先导

前言&#xff1a;最好在牢固前面几大件&#xff08;编程语言、数据结构、操作系统&#xff09;&#xff0c;并且您有一个服务器的基础上&#xff08;我使用的是腾讯云中配置最低的服务器&#xff09;再来学习本系列的网络知识。 1.网络发展简要 下面就是简单提及一些概念而已&…

二叉树之AVL树

文章目录 1. AVL树的概念&#xff08;logN)1.1背景1.2规则 2.AVL树节点的定义3.AVL树的插入4. AVL树的旋转(重点&#xff09;4.1 新节点插入较高的右子树的右侧&#xff1a;左单璇&#xff1b;4.2 新节点插入较高左子树的左侧&#xff1a;右单璇&#xff1b;4.3&#xff08;双旋…

AJAX——ajax原理

1.XMLHttpRequest 定义&#xff1a;XMLHttpRequest&#xff08;XHR&#xff09;对象用于与服务器交互。通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL&#xff0c;获取数据。这允许网页在不影响用户操作的情况下&#xff0c;更新页面的局部内容。XMLHttpRequest在AJA…