Linux hot-plug UDEV mechanism and daemon process

Linux hot plug UDEV mechanism

1. udev is a device management tool, and udev runs as a daemon process.

2. Manage the device files under dev by listening to the uevent sent by the kernel.

3.udev runs in user space, not in kernel space.

4. Able to dynamically update device files, create, delete, etc.

System Frame Diagram

Daemon

1. A process running in the background.

2. Independent of the terminal and executed periodically

3. No need to manually pull up each time.

4. The name of the daemon usually ends in d

5. Common daemon processes: syslogd, httpd, sendmail and mysqld, etc.

Daemon Features

1. The life cycle is long, and it starts and shuts down with the operating system.

2. The daemon process is not associated with the terminal, the control terminal exits, and the daemon still runs

3. The daemon process runs in the background and does not occupy the terminal. The terminal can execute other commands

4. The parent process of the daemon process is the init process. The real parent process forks out of the child process and exits before the child process. It is an orphan inherited by init

child process

5. [] is called the kernel daemon process, without [] is a normal daemon process

6.init: It is a system daemon process. The PPID of many processes is init, which is responsible for adopting orphan processes.

Daemon API

#include <unistd.h>

int daemon(int nochdir, int noclose);

When nochdir is 0, the daemon will change the process working directory to the root directory.

When noclose is 0, daemon redirects STDIN, STDOUT, and STDERR of the process to /dev/null. 

Time related API

struct tm

{

int tm_sec; seconds, range from 0 to 59
int tm_min; minute, range from 0 to 59
int tm_hour; hour, range from 0 to 23
int tm_mday; day of the month, range from 1 to 31
int tm_mon; month, range from 0 to 11
int tm_year; year since 1900
int tm_wday; day of the week, ranges from 0 to 6
int tm_yday; day of the year, ranges from 0 to 365
int tm_isdst; daylight saving time
};



char* asctime(struct tm *ptr)

Function: Express the time represented by the structure struct tm * ptr as a string, and the format of the returned time string is: week, month, day, hour: minute: second, year

Parameters: ptr is obtained through the function localtime() or gmtime()



struct tm *localtime(const time_t *timer)

Fill the tm structure with the value of the timer() function. The value of timer is decomposed into a tm structure and represented by the local time zone


 
struct tm *gmtime(time_t *timer)

Fill the tm structure with the value of the timer() function. The value of timer is decomposed into the tm structure and expressed in Greenwich Mean Time



time_t time(time_t *timer)

When timer=NULL, get the current calendar time (the number of seconds from 1970-01-01 00:00:00 to now)

When timer=time value, it is used to set the calendar time, time_t is an unsigned long type

If the timer is not empty, the return value is also stored in the variable timer, returning the current calendar time or setting the calendar time

demo1:

Use the API to create a daemon process and write the current time to the file every 5s

Code example:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>

bool flag = true;

void signal_handler(int signal_num, siginfo_t *info, void *context)
{
        flag = false;
}

void *func1()
{
        struct sigaction act;
        act.sa_sigaction = signal_handler;
        act.sa_flags = SA_SIGINFO;
        while(1)
        {
                sigaction(SIGINT, & act, NULL);
        }
        pthread_exit(NULL);
}

void *func2()
{
        int fd;
        time_t t;
        char *buf = NULL;
        while(flag)
        {
                umask(0);
                fd = open("/root/pro/date.log",O_CREAT|O_RDWR|O_APPEND,0666);
                if(fd == -1)
                {
                        printf("open/create file fail\\
");
                        perror("error");
                        exit(-1);
                }
                t = time(NULL);
                buf = asctime(localtime( &t));
                write(fd,buf,64);
                sleep(5);
        }
        pthread_exit(NULL);
}

int main()
{
        int ret;
        pthread_t sig;
        pthread_t wri;
        ret = daemon(0,0);
        if(ret == -1)
        {
                printf("create daemon fail\\
");
                perror("error");
                exit(-1);
        }
        pthread_create( & sig, NULL, func1, NULL);
        pthread_create( &wri,NULL,func2,NULL);
        pthread_join(sig, NULL);
        pthread_join(wri, NULL);
        return 0;
}

Example code results:

demo2:

Customize daemonAPI to implement demo1

Code example:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>

bool flag = true;

void sighandler_t(int signal_num)
{
        flag = false;
}

void *func1()
{
        while(1)
        {
                signal(SIGINT, sighandler_t);
        }
        pthread_exit(NULL);
}

void *func2()
{
        int fd;
        time_t t;
        char *buf = NULL;
        while(flag)
        {
                umask(0);
                fd = open("/root/pro/date.log",O_CREAT|O_RDWR|O_APPEND,0666);
                if(fd == -1)
                {
                        printf("open/create file fail\\
");
                        perror("error");
                        exit(-1);
                }
                t = time(NULL);
                buf = asctime(localtime( &t));
                write(fd,buf,64);
                sleep(5);
        }
        pthread_exit(NULL);
}

void mydaemon()
{
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork");
        exit(1);
    }
    else if(pid) {
        exit(0);
    }
    //Create a new session, and the child process is the leader of the session and process.
    if(setsid() == -1)
    {
        perror("setsid");
        exit(1);
    }
    //Close the file descriptor inherited from the parent process.
    int max_fd = sysconf(_SC_OPEN_MAX);
    for(int i = 0; i < max_fd; + + i)
    {
        close(i);
    }
    // redirect file descriptors 0, 1, 2 to /dev/null
    open("/dev/null", O_RDWR);
    dup(0);
    dup(0);
    umask(0);
    chdir("/");
}

int main()
{
        int ret;
        pthread_t sig;
        pthread_t wri;
        mydaemon();
        pthread_create( & sig, NULL, func1, NULL);
        pthread_create( &wri,NULL,func2,NULL);
        pthread_join(sig, NULL);
        pthread_join(wri, NULL);
        return 0;
}

Example code results:

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge