ARM的守护进程和udev守护进程

首先讲解Linux操作系统的守护进程,然后对udev守护进程的特别讲解,最后教大家使用uedv(自动挂载u盘)。

特别讲解usb设备连接ARM时,流程和相关信息的查看。

1.ARM的守护进程

ARM的操作系统是Linux,也就是探索Linux操作系统的守护进程。 当提到ARM架构下的Linux操作系统时,我们实际上是在讨论运行在ARM硬件平台上的Linux系统。ARM处理器因其能效比较高而被广泛应用于嵌入式系统和移动设备中。在这样的系统中,守护进程扮演着至关重要的角色。

1.1 守护进程(什么是守护进程)

概念:在Linux操作系统中,守护进程是一种后台运行的程序,它独立于任何用户会话,通常用于执行系统任务或提供持续的服务。

特点

  • 后台运行:守护进程在后台运行,不与任何终端或控制台交互。

  • 持续运行:它们通常在系统启动时开始运行,并持续运行直到系统关闭。

  • 无用户交互:守护进程设计用于无需用户输入即可独立运行。

  • 系统权限:很多守护进程以root权限运行,因为它们需要访问系统资源或执行管理任务。

  • 服务提供:它们提供网络服务、文件系统管理、打印服务、系统日志记录等核心功能。

1.2 守护进程的作用(为什么要用到守护进程)

守护进程的作用是执行对系统运行至关重要的后台任务。这些任务可能包括:

  • 网络服务:如Web服务器、邮件服务器等。

  • 系统监控:如监控系统性能、资源使用情况。

  • 定时任务:如定时备份、定时执行脚本等。

  • 硬件管理:如打印机队列管理、硬件状态监控。

  • 用户服务:如邮件传输代理、数据库服务等。

使用守护进程的好处包括:

  • 提高效率:自动化系统管理任务,提高系统运行效率。

  • 稳定性:确保关键服务的持续性和稳定性。

  • 安全性:通过隔离关键服务来增强系统的安全性。

  • 可维护性:简化系统维护和故障排除。

1.3 使用守护进程(编写创建一个守护进程)

创建一个守护进程通常涉及以下步骤:

  1. 创建一个前台进程:守护进程需要被进程管理器(如systemd或SysVinit)管理。

  2. 从终端脱离:重定向标准输入、输出和错误流到/dev/null或日志文件。

  3. 运行在后台:确保进程不依赖于任何终端会话。

  4. 处理信号:正确处理如SIGTERM等信号,以便优雅地关闭。

  5. 守护进程的日志记录:使用系统日志服务(如syslog或systemd-journald)来记录信息。

1.操作系统的守护进程自带的,能看懂、知道是干什么的。

2.编写守护进程(代码创建)

您提供的代码示例和说明非常详细,涵盖了守护进程的创建、调试和自启动设置的多个方面。下面是对您提供的信息进行排版和补充的完整内容:

2.1daemon() 函数

daemon() 函数用于创建守护进程,它在 Unix/Linux 系统中常用。函数原型如下:

 #include <unistd.h>
 ​
 int daemon(int nochdir, int noclose);
  • nochdir 参数:指示是否改变守护进程的当前工作目录。如果为非零值,守护进程的当前工作目录将保持不变。

  • noclose 参数:指示是否关闭所有文件描述符。如果为非零值,守护进程不会关闭标准输入、标准输出和标准错误。

  • 返回值:成功创建守护进程时返回 0,失败时返回 -1。

时间日志守护进程

以下是一个使用 daemon() 创建的时间日志守护进程的示例代码:

 // time_daemon.c
 #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 func1_handler(int signum) {
     printf("Process ending\n");
     flag = false;
 }
 ​
 int main() {
     struct sigaction act;
 ​
     act.sa_handler = func1_handler;
     act.sa_flags = 0;
     sigaction(SIGQUIT, &act, NULL);
 ​
     sigemptyset(&act.sa_mask);
 ​
     int ret_daemon = daemon(0, 0);
     if (ret_daemon == -1) {
         perror("daemon");
         exit(-1);
     }
 ​
     while (flag == true) {
         int fd = open("/home/orangepi/time.log", O_WRONLY | O_CREAT | O_APPEND, 0666);
         if (fd == -1) {
             perror("open");
             exit(-1);
         }
 ​
         time_t t = time(0);
         char* time_buf = asctime(localtime(&t));
 ​
         write(fd, time_buf, strlen(time_buf));
         close(fd);
 ​
         sleep(10);
     }
 ​
     return 0;
 }

检测守护进程是否运行

以下是一个检测 time_daemon 守护进程是否运行的程序:

 //test.c
 #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 main() {
     char *cmd = "ps -aux | grep time_daemon | grep -v grep";
     char *buffer;
     buffer = (char *)malloc(128);
 ​
     FILE *file = popen(cmd, "r");
     fgets(buffer, 128, file);
 ​
     printf("%s\n", buffer);
     if (strstr(buffer, "time_daemon") != NULL) {
         printf("time_daemon is running\n");
         return 1;
     } else {
         printf("time_deamon is not running\n");
         return -1;
     }
 }

防止时间日志退出的守护进程

以下是一个防止时间日志守护进程退出的 check 守护进程:

 // check.c
 #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;
 int fd;
 ​
 void handler(int sig) {
     printf("I got a signal %d\nI'm quitting.\n", sig);
     flag = false;
 }
 ​
 int check_Process() {
     char *cmd = "ps -aux | grep time_daemon | grep -v grep";
     char *buffer;
     buffer = (char *)malloc(128);
 ​
     FILE *file = popen(cmd, "r");
     fgets(buffer, 128, file);
 ​
     printf("%s\n", buffer);
     if (strstr(buffer, "time_daemon") != NULL) {
         printf("time_daemon is running\n");
         write(fd, "running\n", strlen("running\n"));
         return 1;
     } else {
         printf("time_deamon is not running\n");
         write(fd, "not running\n", strlen("not running\n"));
         return -1;
     }
 }
 ​
 int main() {
     fd = open("./flag.log", O_CREAT | O_APPEND | O_RDWR, 0666);
     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) {
         write(fd, "1\n", strlen("1\n"));
         int ret = check_Process();
         if (ret == -1) {
             system("/home/orangepi/Project/daemon/time_daemon &");
         }
         sleep(2);
     }
     close(fd);
     return 0;
 }

调试守护进程

在调试守护进程时,由于它们不与终端交互,因此不能使用 printf 将调试信息输出到控制终端。相反,可以使用文件 I/O 函数,如 openwriteread 等,将调试信息写入日志文件或文本文件中。

2.2设置守护进程开机自启动

有几种方法可以设置守护进程开机自启动:

  1. 使用 systemd:创建 systemd 服务单元文件,并启用服务。

  2. 使用 init 脚本:在 /etc/init.d/ 目录下创建 init 脚本,并添加到适当的运行级别。

  3. 使用 rc.local:编辑 /etc/rc.local 文件,在启动时运行守护进程。

以下是使用 systemd 设置开机自启动的示例步骤:

  1. 创建服务单元文件:

     sudo nano /etc/systemd/system/time_daemon.service

    内容可能如下:

     [Unit]
     Description=Time Logging Daemon
     ​
     [Service]
     Type=simple
     ExecStart=/path/to/time_daemon
     Restart=always
     User=orangepi
     ​
     [Install]
     WantedBy=multi-user.target

    请将 /path/to/time_daemon 替换为您的 time_daemon 程序的实际路径。

  2. 启动并启用服务:

     sudo systemctl start time_daemon.service
     sudo systemctl enable time_daemon.service
  3. 对于 check 守护进程,重复上述步骤,创建相应的 check.service 文件。

通过上述步骤,您可以确保 time_daemoncheck 守护进程在系统启动时自动运行。如果您遇到任何问题或需要进一步的帮助,请随时提问。

以下是使用 rc.local 设置开机自启动的示例步骤:

2. udev守护进程

2.1 udev(什么是udev)

概念udev 是 用户空间的设备管理器、更是Linux 系统中的一个用户空间守护进程,负责管理设备节点的动态创建和删除。它基于内核的 uevent 机制工作,能够根据硬件状态的变化动态地创建或移除设备文件。

特点:通过使用 udev,Linux 系统能够更加灵活和自动化地管理硬件设备,提高了系统的易用性和可维护性。

  • 事件驱动udev 响应来自内核的 uevent,这些事件通常与硬件设备的添加、移除或更改有关。

  • 规则系统udev 使用一套复杂的规则系统来确定如何处理设备事件。

  • 动态设备节点udev 可以自动创建或移除位于 /dev 目录下的设备节点,无需重启系统。

  • 持久化设备名称udev 支持持久化设备名称,即使设备被移除再重新插入,也能保持相同的设备节点名。

  • 访问控制udev 可以设置设备节点的权限,控制哪些用户或组可以访问特定的硬件设备。

2.2 udev的作用(使用udev的好处)

udev 的主要作用包括:

  • 自动化:自动管理设备的添加和移除,无需手动干预。

  • 即插即用:支持即插即用功能,用户可以无缝地使用USB等热插拔设备。

  • 设备管理:简化了设备的管理,使得设备管理更加灵活和高效。

  • 权限管理:提供了细粒度的访问控制,增强了系统的安全性。

  • 系统维护:减少了系统维护的复杂性,因为许多设备相关的任务由 udev 自动处理。

2.3 udev的工作流程
  1. 内核检测到硬件状态变化(如设备插入)。

  2. 内核发送 uevent 到用户空间。

  3. udev 监听到 uevent 并触发规则处理。

  4. udev 根据规则执行操作,如创建设备节点或执行脚本。

  5. 操作完成后,udev 通知系统和其他应用程序。

3. 配置、使用udev

3.1 如何使用udev
  • 监控 udev 事件:使用 udevadm monitor 命令来实时查看 udev 事件。

  • 查询设备信息:使用 udevadm info 命令来获取设备的详细信息。

  • 测试规则:使用 udevadm test 命令来测试规则文件。

3.2 udev配置文件
  • /etc/udev/udev.conf:这是 udev 的主配置文件,包含了 udev 的全局设置。

3.3 udev规则文件
  • /etc/udev/rules.d/:这是自定义 udev 规则文件的存放位置。

  • /lib/udev/rules.d/:系统默认的 udev 规则文件存放位置。

  • /run/udev/rules.d/:在系统运行时,udev 会自动将某些规则放入此目录。

通过编写规则文件,用户可以根据设备的特征(如Vendor ID、Product ID、Serial Number等)来指定设备的行为,如自动挂载文件系统、设置权限、执行自定义脚本等。

使用 udev 可以极大地提高硬件设备的管理效率,使得Linux系统更加灵活和强大。

4. 使用udev自动挂载U盘

4.1 U盘为什么要挂载

在Linux系统中,"挂载"是指将一个文件系统映射到系统目录结构中的一个点,使得用户可以访问该文件系统中的文件。U盘(或任何存储设备)在使用前需要挂载的原因包括:

  1. 文件访问:允许用户读取和写入U盘中的文件。

  2. 系统识别:让操作系统识别U盘作为一个可访问的存储介质。

  3. 设备管理:通过挂载,系统可以更有效地管理设备和文件系统。

  4. 持久访问:挂载后,即使设备被拔出再插入,系统也能通过相同的路径访问U盘。

4.2 挂载U盘

挂载U盘可以通过手动或自动(使用udev)的方式进行。

4.2.1 手动挂载U盘

手动挂载U盘涉及以下步骤:

  1. 识别设备:使用 lsblkfdisk -l 命令识别U盘的设备名称(如 /dev/sdb1)。

  2. 创建挂载点:创建一个目录作为挂载点,如 mkdir /mnt/usb

  3. 挂载设备:使用 mount 命令将U盘挂载到创建的目录,如 mount /dev/sdb1 /mnt/usb

  4. 访问文件:现在可以访问挂载点 /mnt/usb 下的文件。

    流出:

     orangepi@orangepizero2:~$ sudo mkdir /mnt/usb
     orangepi@orangepizero2:~$ sudo mount /dev/sda /mnt/usb

    不成功,改为 sudo mount /dev/sda1 /mnt/usb,成功。在 Linux 系统中,/dev/sda 通常指的是整个磁盘设备,而 /dev/sda1 指的是该磁盘上的一个特定分区。 挂载 /dev/sda1 而不是 /dev/sda 可以更精确地控制您想要访问的存储内容,并且可以避免潜在的跨分区操作。

    自动挂载:(可能是不用udev,还未试验)

    如果分区成功挂载,您应该在 /mnt/usb 下看到该 USB 设备的文件系统内容。现在,您可以像访问本地磁盘一样访问这个 USB 设备上的数据。

    请注意,为了保持挂载在系统重启后依然有效,您可能需要将挂载点添加到 /etc/fstab 文件中。这通常涉及到找到 USB 设备的 UUID(通用唯一识别码),并将其与挂载点关联起来。

    要找到设备的 UUID,您可以使用 blkid 命令:

     sudo blkid

    这将列出所有已识别的块设备及其 UUID。找到对应于 /dev/sda1 的 UUID 后,您可以按照以下格式将其添加到 /etc/fstab 文件中:

     UUID=<UUID-of-sda1> /mnt/usb <fs-type> <mount-options> 0 0

    <UUID-of-sda1> 替换为实际的 UUID,<fs-type> 替换为文件系统类型(如 vfatext4 等),<mount-options> 替换为所需的挂载选项(如 defaultsro(只读)等)。

    编辑 /etc/fstab 文件通常需要 root 权限,可以使用 nanovim 等文本编辑器:

     sudo nano /etc/fstab

    或者:

     sudo vim /etc/fstab

    在文件中添加上述行后,保存并退出编辑器。这样,每次系统启动时,/dev/sda1 都会自动挂载到 /mnt/usb

手动挂载是临时的,当系统重启或U盘被拔出后,挂载不再存在。

4.2.2 udev自动挂载

使用udev自动挂载U盘可以省去手动挂载的步骤,udev会根据规则自动完成挂载。配置udev自动挂载的步骤包括:

  1. 确定挂载点:选择或创建一个目录作为U盘的永久挂载点,如 /mnt/usb

  2. 创建规则文件:在 /etc/udev/rules.d/ 目录下创建一个规则文件,如 70-usb-automount.rules。(此处的名字决定了它的加载顺序。由于我在使用70-usb-automount.rules时不能正确的挂载U盘,而重名为 usbpan.rules后,改变了它的加载顺序,所以导致了挂载成功,在这里就用更改后的名字)

  3. 编写udev规则:在规则文件中编写udev规则,指定何时以及如何自动挂载U盘。例如:

     1.这个规则文本是人工智能给出的:(目前测试还不行,好像成功了)
     ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", RUN+="/bin/mount -t auto /dev/%k /mnt/usb"
     2.usbpan.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"
     ​

    这条规则表示当一个USB设备被添加,且其供应商ID和产品ID分别匹配时,自动以自动识别的文件系统类型将该设备挂载到 /mnt/usb

  4. 重新加载udev规则:使用 udevadm control --reload-rules 命令重新加载udev规则。(就是重启下。不过触发 udev:如果 USB 设备已经连接,触发 udev 来检查规则:sudo udevadm trigger)

  5. 测试规则:插入U盘后,使用 udevadm monitor --property 命令监控udev事件,确保规则被正确触发。

  6. 访问文件:U盘被插入时,udev将自动将其挂载到指定的挂载点。

    用tree命令查看:

    (成功地安装了 tree 命令,并使用它列出了 /media/ 目录的内容。tree 是一个递归地列出目录内容的命令,它可以以树状图的方式显示目录和子目录的结构,非常直观。

    根据 tree /media/ 命令的输出,我们可以看到:

     复制/media/
     ├── sdc
     └── sdc1

    这表明在 /media/ 目录下有两个目录:sdcsdc1。通常,sdc 可能代表一个整个磁盘设备,而 sdc1 是该磁盘上的一个分区。在大多数 Linux 系统中,可移动存储设备(如 USB 闪存驱动器或外部硬盘驱动器)会被自动挂载到 /media/ 目录下。)

使用udev自动挂载U盘的好处是方便和自动化,用户无需每次手动执行挂载命令,当U盘被拔出时,udev也可以自动卸载设备,保持系统的整洁和安全。

注:挂载的U盘,设备节点都是在根目录下。

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值