一年前搞了个树莓派,弄了个风扇和 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)
中去做吧。
参考:
本站由以下主机服务商提供服务支持:
0条评论