抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

让 c 程序在 Linux 上保持后台运行以及日志输出

一年前搞了个树莓派,弄了个风扇和 oled 脚本,今年无意中发现几次风扇并没有按理想的状态运行,就重新看了下脚本,发现以前运行时启动就会阻塞在那而且有很多 printf,我想大概就是这么个原因。于是想起来改造:

  • 脚本执行后创建守护进程后台运行
  • 将打印改为日志输出

经过几天验证,发现挺顺利的。因为我并不从事 C 相关开发,文末也贴上了更为详细的文章,这里直接给出解决方案。

#include <fcntl.h>
#include <unistd.h>
#include <syslog.h>

#define _PATH_DEVNULL "/dev/null"

int daemon(int nochdir, int noclose);

int main(void)
{
    //启用日志
    openlog("LOG_TAG", LOG_CONS | LOG_PID, 0);

    if (0 == daemon(1, 0))
    {
        //守护进程开启成功
        syslog(LOG_DEBUG, "daemon ok\n");
    }
    else
    {
        //守护进程开启失败
        syslog(LOG_ERR, "daemon failed\n");
    }

    while (1)
    {
        //TODO 做一些常驻内存或者轮询的事
    }

    //关闭日志
    closelog();

    return 0;
}

int daemon(nochdir, noclose) int nochdir, noclose;
{
    int fd;

    switch (fork())
    {
    case -1:
        return (-1);
    case 0:
        break;
    default:
        _exit(0);
    }

    if (setsid() == -1)
        return (-1);

    if (!nochdir)
        (void)chdir("/");

    if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
    {
        (void)dup2(fd, STDIN_FILENO);
        (void)dup2(fd, STDOUT_FILENO);
        (void)dup2(fd, STDERR_FILENO);
        if (fd > 2)
            (void)close(fd);
    }
    return (0);
}

值得一提的是日志输出中 syslog 并不通用,我这边环境为 Ubuntu,这种日志是输出到/var/log/syslog文件的,我选择它的原因是它最为简单。

daemon 函数参数解释:第一个参数是指是否需要将工作空间切换至/,一般是不需要的,第二个参数是指是否需要将输出流转向到/dev/null,所以:

daemon 函数的参数请传 1,0 ,不然即使在后台运行,print 之类的还是会输出到当前控制台,仅在调试时传 1,1

另外任务什么的就把代码块放在 while(1) 中去做吧。

参考:

如何让程序真正地后台运行?

linux下C编程打印log


本站由以下主机服务商提供服务支持:

0条评论

发表评论