打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
奔Linux内核入门篇_chapter8.5.3_后台守护进程

实验详述

  1. 实验目的
    通过本实验了解和熟悉Linux是如何创建和使用后台守护进程的.

  2. 实验步骤
    (1) 写一个用户程序, 创建一个守护进程.
    (2) 该守护进程每隔5秒去查看当前内核的日志中是否有Oops错误.

实验解析

本实验完全是个用户态的程序, 需要知道

  1. 如何创建一个守护进程? (跑在后台, 无控制终端, 无法对前台输出信息)

  2. 如何去读内核的日志?


问题1可以用glibc提供的daemon()函数

man 3 daemon

NAME       daemon - run in the backgroundSYNOPSIS       #include <unistd.h>       int daemon(int nochdir, int noclose);   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):       daemon():           Since glibc 2.21:               _DEFAULT_SOURCE           In glibc 2.19 and 2.20:               _DEFAULT_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)           Up to and including glibc 2.19:               _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)

问题2 可以用glibc提供的klogctl()函数

man 3 klogctl

NAME       syslog, klogctl - read and/or clear kernel message ring buffer; set console_loglevelSYNOPSIS       int syslog(int type, char *bufp, int len);                       /* No wrapper provided in glibc */       /* The glibc interface */       #include <sys/klog.h>       int klogctl(int type, char *bufp, int len);

本实验相对简单,直接看代码.

程序源码

文件名: my_daemon.c
这个直接参考了笨叔的答案
(runninglinuxkernel_4.0/rlk_lab/rlk_basic/chapter_8/lab3_daemon/daemon_test1.c)

/* create a daemon which checks if there are opps errors in the kernel log * every 5 second */#include <stdio.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <string.h>#include <sys/stat.h>#include <sys/klog.h>#define FALLBACK_KLOG_BUF_SHIFT 17  /* CONFIG_LOG_BUF_SHIFT in kernel */#define FALLBACK_KLOG_BUF_LEN   (1 << FALLBACK_KLOG_BUF_SHIFT)#define KLOG_CLOSE         0#define KLOG_OPEN          1#define KLOG_READ          2#define KLOG_READ_ALL      3#define KLOG_READ_CLEAR    4#define KLOG_CLEAR         5#define KLOG_CONSOLE_OFF   6#define KLOG_CONSOLE_ON    7#define KLOG_CONSOLE_LEVEL 8#define KLOG_SIZE_UNREAD   9#define KLOG_SIZE_BUFFER   10/* we use 'Linux version' string instead of Oops in this lab *///#define OOPS_LOG  "Oops"#define OOPS_LOG  "Linux version"int save_kernel_log(char *buffer){char path[128];        time_t t;        struct tm *tm;        int fd;        /* time(2): returns the time as the number of seconds         * since the Epoch, 1970-01-01 00:00:00  0000 (UTC). */        t = time(0);        /* transform date and time to broken-down time or ASCII */        tm = localtime(&t);        /* the structure tm, which is defined in <time.h> as follows:         * struct tm {         *      int tm_sec;    // Seconds (0-60)         *      int tm_min;    // Minutes (0-59)         *      int tm_hour;   // Hours (0-23)         *      int tm_mday;   // Day of the month (1-31)         *      int tm_mon;    // Month (0-11)         *      int tm_year;   // Year - 1900         *      int tm_wday;   // Day of the week (0-6, Sunday = 0)         *      int tm_yday;   // Day in the year (0-365, 1 Jan = 0)         *      int tm_isdst;  // Daylight saving time         * };         */        snprintf(path, 128, "/mnt/%d.%d.%d.%d.%d.%d.log", tm->tm_year 1900,                        tm->tm_mon 1, tm->tm_mday, tm->tm_hour,                        tm->tm_min, tm->tm_sec);        printf("%s\n", path);        fd = open(path, O_WRONLY|O_CREAT, 0644);        if(fd == -1) {printf("open error\n");                return -1;        }        write(fd, buffer, strlen(buffer));        close(fd);        return 0;}int check_kernel_log(){char *buffer;        char *p;        ssize_t klog_size;        int ret = -1;        int size;        printf("start kernel log\n");        /* klogctl(3): read and/or clear kernel message         * ring buffer; set console_loglevel.         * Here returns the total size of the kernel log buffer.         * */        klog_size = klogctl(KLOG_SIZE_BUFFER, 0, 0);        if (klog_size <= 0) {klog_size = FALLBACK_KLOG_BUF_LEN;        }        printf("kernel log size: %d\n", klog_size);        buffer = malloc(klog_size   1);        if (!buffer)                return -1;        /* Read all messages remaining in the ring buffer,         * placing them in the buffer pointed to by buffer.         * The  call reads  the  last klog_size bytes from         * the log buffer (nondestructively) */        size = klogctl(KLOG_READ_ALL, buffer, klog_size);        if (size < 0) {printf("klogctl read error\n");                goto done;        }        buffer[size] = '\0';        /* strstr(3), finds the first occurrence of the substring */        /* check if oops in klog */        p = strstr(buffer,OOPS_LOG);        if (p) {printf("we found '%s' on kernel log\n", OOPS_LOG);                save_kernel_log(buffer);                ret = 0;        }done:        free(buffer);        return ret;}int main(void){/* The daemon(3) function is for programs wishing to         * detach themselves from the controlling terminal         * and run in the background as system daemons. */        if (daemon(0, 0) == -1) {printf("failed to daemon(): %s(%d)\n", strerror(errno), errno);                return -1;        }        while (1) {check_kernel_log();                sleep(5);        }        return 0;}

编译

这里直接编译就行

arm-linux-gnueabi-gcc my_daemon.c -o my_daemon.exe --static

验证执行

/mnt #/mnt # pwd/mnt/mnt # find . -name "*.log"/mnt # ./my_daemon.exe/mnt #/mnt # find . -name "*.log"./2021.1.24.1.45.50.log./2021.1.24.1.45.55.log./2021.1.24.1.46.0.log/mnt #/mnt # pgrep my_daemon792/mnt # kill -9 792/mnt #/mnt #/mnt # head 2021.1.24.1.45.50.log<6>[    0.000000] Booting Linux on physical CPU 0x0<6>[    0.000000] Initializing cgroup subsys cpuset<5>[    0.000000] Linux version 4.0.0  (gewkiff@ukylin) (gcc version 5.5.0 20171010 (Ubuntu/Linaro 5.5.0-12ubuntu1) ) #2 SMP Sun Sep 20 06:37:58 CST 2020<6>[    0.000000] CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d<6>[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache<6>[    0.000000] Machine model: V2P-CA9<6>[    0.000000] Memory policy: Data cache writealloc<7>[    0.000000] On node 0 totalpages: 25600<7>[    0.000000] free_area_init_node: node 0, pgdat c10e9e40, node_mem_map c6332000<7>[    0.000000]   Normal zone: 200 pages used for memmap/mnt #/mnt #/mnt # head 2021.1.24.1.45.55.log<6>[    0.000000] Booting Linux on physical CPU 0x0<6>[    0.000000] Initializing cgroup subsys cpuset<5>[    0.000000] Linux version 4.0.0  (gewkiff@ukylin) (gcc version 5.5.0 20171010 (Ubuntu/Linaro 5.5.0-12ubuntu1) ) #2 SMP Sun Sep 20 06:37:58 CST 2020<6>[    0.000000] CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d<6>[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache<6>[    0.000000] Machine model: V2P-CA9<6>[    0.000000] Memory policy: Data cache writealloc<7>[    0.000000] On node 0 totalpages: 25600<7>[    0.000000] free_area_init_node: node 0, pgdat c10e9e40, node_mem_map c6332000<7>[    0.000000]   Normal zone: 200 pages used for memmap/mnt #

kernel log buffer

这是在man 3 klogctl 中看到的关于kernel log buffer的简短介绍

The kernel log buffer
The kernel has a cyclic buffer of length LOG_BUF_LEN in which
messages given as arguments to the kernel function printk()
are stored (regardless of their log level).
In early kernels, LOG_BUF_LEN had the value 4096;
from kernel 1.3.54, it was 8192; from kernel 2.1.113, it was 16384;
since kernel 2.4.23/2.6, the value is a kernel configuration option
(CONFIG_LOG_BUF_SHIFT, default value dependent on the architecture).
Since Linux 2.6.6, the size can be queried with command type 10 (see below).

来源:https://www.icode9.com/content-3-832451.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
libvirt: Logging in the library and the daemo...
NFS安装在ubuntu并共享
NFS安装配置
linux 变成“file system read
LINUX下的tty,console与串口
linux Log Level
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服