目录
- 守护进程
- daemon()函数
- 系统日志
- openlog(),syslog()与closelog()函数
守护进程
在Linux下进行编程时,程序运行时往往会占用终端,因此经常需要让程序进入后台运行,Linux命令中存在使程序后台运行的指令,在命令后加上&(后台运行符)可以让该命令后台运行,如make &
,不过以这种方式让程序进入后台运行只是一种假象,程序仍然依赖终端(terminal)程序,即以这种方式后台运行的程序仍是terminal的子进程,因此,当终端被关闭时该程序也随之终止,那有没有真正不依赖于终端存在的后台运行的进程呢
这种进程就是守护进程(daemon进程)又称精灵进程,因为它就像精灵一样隐匿于角落难以捕获。daemon程序通常作为服务进程使用,
守护进程一旦脱离了终端,退出就成了问题,这时需要需要使用ps命令查出进程ID后再使用kill命令停止
那么如何在编程时使程序成为daemon进程进入后台运行呢,这就需要用到daemon()函数
daemon()函数
- daemon()函数简介
daemon()函数原型及所需头文件如下
#include <unistd.h>
int daemon(int nochdir, int noclose);
daemon()函数原型很简单,只有两个参数
- 第一个参数nochdir即not change
directory的缩写,用来判断是否切换当前工作路径到“/”目录,赋值为“0”时切换工作路径到“/“目录;赋值为1时则不会改变 - 第二个参数noclose用来指定是否关闭标准输入,标准输出和标准出错(即重定向到/dev/null),传0时为关闭;传1时则不关闭
daemon()函数的两个参数通常都传0
系统日志
syslog是- 种工业标准的协议,可用来记录设备的日志。在UNIX系统,路由器、交换机等网络设备中,系统日志(System
Log)记录系统中任何时间发生的大小事件。管理者可以通过查看系统记录,随时掌握系统状况。UNIX的系统日志是通过syslogd这个进程记录系统有关事件记录,也可以记录应用程序运作事件。通过适当的配置,我们还可以实现运行syslog协议的机器间通信,通过分析这些网络行为日志,藉以追踪掌握与设备和网络有关的状况
对系统日志的操作可以通过系统自带的函数实现,经常用到的有openlog(),syslog()与closelog()函数
openlog(),syslog()与closelog()函数
这三个函数的函数原型如下
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
openlog()
用来打开系统日志,如果不调用openlog(),在第一次调用syslog()时,系统会自动调用openlog()
- ident:是一个标记,ident 所表示的字符串将固定的加在每行日志的前面一标识这个日志,通常就写成当前程序的名称以作标记
- option: 指定openlog函数和接下来调用的syslog函数的控制标志。可以取以下值:
LOG_CONS | 如果将信息发送给 syslogd 守护进程时发生错误,直接将相关信息输出到终端 |
LOG_NDELAY | 立即打开与系统日志的连接(通常情况下,只有在产生第一条日志信息的情况下才会打开与日志系统 |
LOG_ODELAY | 类似于 LOG_NDELAY 参数,与系统日志的连接只有在 syslog 函数调用时才会创建 |
LOG_PERROR | 在将信息写入日志的同时,将信息发送到标准错误输出 |
LOG_PID | 每条日志信息中都包含进程号 |
- facility:指定记录消息程序的类型,与 syslogd 守护进程的配置文件 syslog.conf 中的 facility
对应。可取如下值:
LOG_AUTH | 认证系统(login、su、getty等) |
LOG_AUTHPRIV | 同 LOG_AUTH 但只登陆到所选择的单个用户可读的文件中 |
LOG_CRON | cron 守护进程 |
LOG_DAEMON | 其他系统守护进程,如 routed |
LOG_FTP | 文件传输协议:ftpd、tftpd |
LOG_KERN | 内核产生的消息 |
LOG_LPR | 系统打印机缓冲池:lpr、lpd |
LOG_MAIL | 电子邮件系统 |
LOG_NEWS | 网络新闻系统 |
LOG_SYSLOG | 由 syslogd(8)产生的内部消息 |
LOG_USER | 随机用户进程产生的消息 |
LOG_UUCP | UUCP 子系统 |
LOG_LOCAL0 ~ LOG_LOCAL7 | 本地使用保留 |
syslog()
用来写入日志
- priority:表示消息的级别,与 syslogd 守护进程的配置文件 syslog.conf 中的 level 对应。可取如下值:
LOG_EMERG | 紧急情况 |
LOG_ALERT | 应该被立即改正的问题,如系统数据库破坏 |
LOG_CRIT | 重要情况,如硬盘错误 |
LOG_ERR | 错误 |
LOG_WARNING | 警告信息 |
LOG_NOTICE | 不是错误情况,但是可能需要处理 |
LOG_INFO | 情报错误 |
LOG_DEBUG | 包含情报的信息,通常指在调试一个程序时使用 |
- 写入日志的信息与printf格式类似
syslog(LOG_NOTICE,"%s start runing\n",program_name);
closelog()
关闭日志设备,与文件系统调用的close类似;调用closelog也是可选择的,它只是关闭被用于与syslog守护进程通信的描述符
应用实例
有些时候我们会需要让一个程序持续运行同时不占用终端,例如服务器程序需要持续监听而我们并不希望它持续占用终端,下面是一个用来实现这个功能daemon模块的示例
program_name=basename(argv[0]);/*获取程序名*/
openlog(program_name,LOG_CONS | LOG_PID,0);/*打开系统日志*/
syslog(LOG_NOTICE,"%s start runing\n",program_name);/*在日志中记录“程序开始运行”*/
------------------------------------------------------
if(daemon_run)/*daemon模块*/
{
printf ("Program start run on background,you can get the pid by command'ps aux | grep ./%s'and stop the process by command'kill -pid'\n",program_name);/*在程序调用daemon()函数转入后台运行之前输出到终端*/
daemon(0,0);/*程序进入后台运行*/
syslog(LOG_NOTICE,"Program start run on background");/*程序转入后台后无法将信息输出到终端,因此调用syslog()函数将“程序进入后台运行”写入日志*/
}