第五篇 Linux守护进程和设备管理器udev

发布于:2022-12-28 ⋅ 阅读:(545) ⋅ 点赞:(0)

目录

一、Linux的守护进程(Daemon Process)

1.守护进程简介

2.了解Linux系统下的一些进程 

(1)内核进程

(2)init进程

(3)守护进程🔖

(4)调度进程

3.一个记录时间的守护进程Demo1.c

4.如何设置守护进程开机自启

(1)修改/etc/rc.local文件权限 

(2)在rc.local添加守护进程执行程序的绝对路径

5.利用守护进程实现程序异常重启

(1)如何判断程序是否在运行Demo2.c

(2)守护进程实现程序异常自动重启Demo3.c

二、Linux的设备管理器udev(暂略)

1.udev概述

2.udev机制实现自动挂载u盘


一、Linux的守护进程(Daemon Process)

参考书籍:《UNIX环境高级编程(第二版)》

1.守护进程简介

        守护进程也称精灵进程(Daemon Process)是一类在后台运行的特殊进程,生存期较长、用于执行系统特定事务活动的一种进程。很多守护进程在系统引导的时候启动,仅在系统关闭时才终止。另一些只在需要的时候才启动,完成任务后就自动结束,一般不需要用户交互。(例如:mysqldhttpdudevd等)

2.了解Linux系统下的一些进程 

通过命令ps -auj或者ps -efjc可以查看到以下内容:(截图有删减)

(1)内核进程

        父进程号(PPID)为0的进程通常是内核进程,内核进程依赖于操作系统实现,作为系统自举过程的一部分而启动。(init进程是内核进程的例外,它是内核在自举启动的用户层命令)。内核进程是特殊的,通常存在系统的整个生命周期中,以超级用户特权运行,无控制终端,无命令行。

(2)init进程

        进程号(PID)为1的进程,是内核启动的第一个用户级进程,是所有用户进程的祖先进程,也是所有孤儿进程的父进程(init会领养孤儿进程)。早期UNIX版本是/etc/init,后期较新版本是/sbin/init。init也是一个系统守护进程,负责个运行层次特定的系统服务,这些服务通常是在其本身拥有的守护进程帮助下实现的。

(3)守护进程🔖

🔖大多数守护进程都以超级用户(用户ID为0)特权运行

(PS:也就是UID为root)

🔖所有守护进程不依赖控制终端,其终端名设置为问号(TTY为?)

PS:与终端无关且运行于后台,终端退出不会导致守护进程退出)

🔖多数守护进程的父进程是init进程

🔖生存周期长,一般从操作系统启动到关闭

(详见《UNIX环境高级编程(第二版)》第13章、第8.2节)

(4)调度进程

        PID为0的进程通常是调度进程,常常被称作交换进程(swapper),调度进程是内核的一部分,并不执行任何磁盘上的程序,因此也被称为系统进程。

3.一个记录时间的守护进程Demo1.c

#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

static bool flag = true;
int fd;

void handler(int sigNum){
    printf("Daemon Process without terminal\n");   //不会打印到终端
    write(fd,"Daemon Process receive SIGQUIT\n",32);    //守护进程收到SIGQUIT信号结束并关闭文件
    close(fd);
    flag = false;
} 
int main(){
    int cnt;
    time_t t;
    char *buffer = (char *)malloc(64);
    /* 利用daemon函数创建守护进程 */
    if(daemon(0,0) == -1){
        perror("daemon");
        return -1;
    }
    /* 打开daemon.log文件 O_APPEND每次写之前,都将文件指针移动到文件的末端 */
    /* 且能保证文件操作是原子的,不需要加锁 */
    fd = open("/home/socket/Desktop/daemon.log",O_CREAT | O_WRONLY | O_APPEND,0644);
        if(fd == -1)perror("open");

    /* 信号处理:收到SIGQUIT信号调用处理函数 */
    struct sigaction act;
    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if(sigaction(SIGQUIT,&act,NULL) == -1){
        printf("sigaction error");
        return -1;
    }

    /* 未收到SIGQUIT,每10s记录当前时间,写入daemon.log文件*/
    while(flag){
        t = time(0);
        buffer = asctime(localtime(&t));
        cnt = write(fd,buffer,strlen(buffer));
        memset(buffer,'\0',cnt);
        sleep(10);
    }
    return 0;
}
 

🔖注意:这里创建的守护进程还无法实现开机自启,如果需要该守护进程开机自启,需要通过/etc/rc.local这个文件,这是Linux系统启动后,会自动执行的一个配置脚本,但一般默认没有执行权限。(rc是run command的意思)。

(该文件默认无执行权限)

4.如何设置守护进程开机自启

(1)修改/etc/rc.local文件权限        

(2)在rc.local添加守护进程执行程序的绝对路径

(注意需要程序的绝对路径,这样就可以实现守护进程的开机自启)

5.利用守护进程实现程序异常重启

(1)如何判断程序是否在运行Demo2.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* 判断a.out的程序是否在运行 */
int isRunning(){

    FILE *file;
    char *cmd = "ps -elf | grep a.out |grep -v grep"; //运行命令
    char *buffer = (char *)malloc(128); //存放popen的执行输出
    file = popen(cmd,"r");  //运行cmd,将结果写到file文件
    fgets(buffer,128,file); //读取file文件内容到缓存buffer中

/* 查找buffer里是否有a.out的相关字符 */
    if(strstr(buffer,"a.out") != NULL){
        return 1;
    }else{
        return 0;
    }
}

int main(){
    if(isRunning() == 1){
        printf("a.out is running now\n");
    }else{
        printf("a.out is not running\n");
    }
    return 0;
}

(2)守护进程实现程序异常自动重启Demo3.c

#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>

static bool flag = true;
int fd;

/* 守护进程收到信号则结束守护a.out */
void handler(int sigNum){
    flag = false;
} 

/* 判断a.out的程序是否在运行 */
int isRunning(){

    FILE *file;
    char *cmd = "ps -elf | grep a.out |grep -v grep"; //运行命令
    char *buffer = (char *)malloc(128); //存放popen的执行输出
    file = popen(cmd,"r");  //运行cmd,将结果写到file文件
    fgets(buffer,128,file); //读取file文件内容到缓存buffer中

/* 查找buffer里是否有a.out的相关字符 */
    if(strstr(buffer,"a.out") != NULL){
        return 1;
    }else{
        return -1;
    }
}

int main(){
    int cnt;
    time_t t;
    char *buffer = (char *)malloc(64);
    /* 利用daemon函数创建守护进程 */
    if(daemon(0,0) == -1){
        perror("daemon");
        return -1;
    }
    /* 信号处理:收到SIGQUIT信号调用处理函数 */
    struct sigaction act;
    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if(sigaction(SIGQUIT,&act,NULL) == -1){
        printf("sigaction error");
        return -1;
    }

    /* 未收到SIGQUIT,每2s守护a.out。
       判断程序运行状态,退出则重新启动 */
    while(flag){
        if(isRunning() != 1){
            /* a.out绝对路径,&后台运行 */
            system("/home/socket/Desktop/a.out &");
        }
        sleep(2);
    }
    return 0;
}

(最后只需要将守护进程设置开机自启,就可以实现对a.out程序的“守护”) 

二、Linux的设备管理器udev(暂略)

1.udev概述

2.udev机制实现自动挂载u盘

说明:由于笔者水平有限,文中难以避免有所错漏,敬请各读者斧正

版权声明:转载请附上原文出处链接及本声明。


网站公告

今日签到

点亮在社区的每一天
去签到