【Orangepi Zero2】守护进程daemon
daemon()函数
daemon()
函数是用于创建守护进程的函数,它在Unix/Linux系统中常被使用。
#include <unistd.h>
int daemon(int nochdir, int noclose);
nochdir
参数用于指示是否改变守护进程的当前工作目录。如果 nochdir
为非零值,守护进程的当前工作目录将保持不变。
noclose
参数用于指示是否关闭所有的文件描述符。如果 noclose
为非零值,守护进程将不会关闭标准输入、标准输出和标准错误。
函数成功创建守护进程时返回 0,失败时返回 -1。
请注意,使用 daemon()
函数创建守护进程的时候,要确保你的程序适合在后台运行,因为一旦它脱离了终端控制,就不再接收用户输入。
用守护进程写一个时间日志
创建守护进程的C程序,它将当前时间写入文件 /home/orangepi/daemon.log
,每隔10秒钟写入一次。程序会在接收到 SIGQUIT
信号时退出。
#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;
}
ps -aux | grep time_daemon
查看守护进程 time_daeomn
再写一个 check 守护进程 防止 时间日志 退出
先做一个 test.c 检测 time_damon 守护进程 是否在运行
过滤掉过滤指令
ps -aux | grep time_daemon | grep -v grep
#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 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.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()
{
time_t t;
int ret;
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"));
ret = check_Process();
if (ret == -1){
system("/home/orangepi/Project/daemon/time_daemon"); // & 设置为后台程
}
sleep(2);
}
close(fd);
return 0;
}
在调试程序的时候,如果遇到像守护进程不能将调试的信息用 printf
输出到 terminal
控制终端,那么可以采用 open
write
read
等函数将调试信息以 log
日志或者 txt
文本的形式呈现出来,这是一种非常可行的调试手段
ps -aux | grep check | grep -v grep
当调用 kill
杀死 time_daemon
的进程时,守护进程 check
检测到 time_daemon
进程被杀死,就会用system
函数再次运行 time_daemon
,得到新的进程号。
将守护进程设置为开机启动
需求:将 time_daemon
进程和 check
守护进程设置为开机自启动。
sudo vi /etc/rc.local 开机自启动,绝对路径加程序名字
重启可以看到,已经开机启动了。