目录
linux各种守护进程说明
守护进程的编写规则
守护进程的一个例子
syslog
syslog的例子
参考
进程名 | 说明 |
kthreadd | |
kswapd0 | 内存交换守护进程,支持虚拟内存子系统在经过一段时间后将脏页面慢慢的写回磁盘来回收这些页面 |
flush-8:0 | 在内用内存达到设置的最小阀值时将脏页写到磁盘,也定期将脏页面写回磁盘来减少在系统出现故障时发生的数据丢失 多个flush守护进程可以同时存在,每个写回设备都有一个flush的守护进程,flush-8:0表示主设备号为8,副设备号为0 |
jbd2/sda1-8 | 守护进程帮助实现了ext4文件系统中的日志功能 |
rpcbind | 提供远程过程调用 |
sync_supers | 定期将文件系统元数据写到磁盘 |
crypto/0 kthrotld/0 aio/0 md/0 md_misc/0 linkwatch khungtaskd ata_sff/0 kblockd/0 kintegrityd/0 cgroupkhelper events/0 migration/0 ksoftirqd/0 watchdog/0 |
在编写守护进程时需遵循一些基本规则,以便防止产生并不需要的交互作用。下面先说明这些规则,然后给出一个按照这些规则编写的函数daemonize。
#include
#include
#include
#include
#include
#include
void err_quit(const char *fmt, ...) {
printf(fmt);
exit(1);
}
void daemonize(const char *cmd) {
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/*
** Clear file creation mask.
*/
umask(0);
/*
** Get maximum number of file descriptors.
*/
if(getrlimit(RLIMIT_NOFILE, &rl) < 0)
err_quit("%s: can't get file limit", cmd);
/*
** Become a session leader to lose controlling TTY.
*/
if((pid = fork()) < 0)
err_quit("%s: can't fork", cmd);
else if (pid != 0) /* parent */
exit(0);
setsid();
/*
** Ensure future opens won't allocate controlling TTYs.
*/
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if(sigaction(SIGHUP, &sa, NULL) < 0)
err_quit("%s: can't ignore SIGHUP");
if((pid = fork()) < 0)
err_quit("%s: can't fork", cmd);
else if( pid != 0 ) /* parent */
exit(0);
/*
** Change the current working directory to the root so
*** we won't prevent file system from being unmounted.
*/
if(chdir("/") < 0)
err_quit("%s: can't change directory to /");
/*
** Close all open file descriptors.
*/
if(rl.rlim_max = RLIM_INFINITY)
rl.rlim_max = 1024;
for(i = 0; i < rl.rlim_max; i++)
close(i);
/*
** Attach file descriptors 0, 1, and 2 to /dev/null.
*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/*
** Initialize the log file.
*/
openlog(cmd, LOG_CONS, LOG_DAEMON);
if(fd0 != 0 || fd1 != 1 || fd2 != 2)
{
syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2);
exit(1);
}
sleep(3600);
}
int main() {
daemonize("xx");
return 0;
}
1.内核程序可以调用log函数记日志. 任何用户进程可以打开并读取/dev/klog设备读取这些消息
2.大多数用户进程,调用syslog函数产生日志消息. 这使得消息发送到UNIX域数据报套接字/dev/log
3.用户进程发送日志消息到UDP端口514
通常syslogd守护进程会读取一个配置文件(/etc/syslog.conf)来决定不同类型的消息应该送到何处.
//相关函数
#include
void openlog(const char* ident,int option,int facility);
void syslog(int priority,const char* format,...);
void vsyslog(int priority,const char* format,va_list arg);
void closelog();
/* 返回旧的日志优先级屏蔽值 */
int setlogmask(int maskpriority);
openlog函数
option参数是指定许多选项的位屏蔽
options | 说明 |
---|---|
LOG\_CONS | 若无法将信息发送到syslogd,则直接输出到控制台 |
LOG\_NDELAY | 立即打开与syslogd的连接,默认为第一次写日志时才建立连接 |
LOG\_ODELAY | 在就第一条消息时才建立与syslogd的连接 |
LOG\_PERROR | 输出到stderr中 |
LOG\_NOWAIT | syslog记录日志时可能会fork子进程,该选项表示不wait子进程退出 |
LOG\_PID | 每条消息都记录下进程ID |
参数facility说明
参数facility指明了默认的消息种类. 消息种类会根据syslogd的配置文件来分发到不同位置
facility | 说明 |
---|---|
LOG\_AUTH | 认证相关的信息,入login,su,getty产生的信息 |
LOG\_CRON | 由cron或at产生的信息 |
LOG\_DAEMON | 系统守护进程产生的消息 |
LOG\_FTP | FTP守护进程产生的消息 |
LOG\_KERN | 内核产生的消息 |
LOG\_LOCAL0 – LOG\_LOCAL7 | 保留本地使用 |
LOG\_LPR | 行打印系统产生的消息 |
LOG\_MAIL | 邮件系统产生的消息 |
LOG\_NEWS | Usenet网络新闻系统产生的消息 |
LOG\_SYSLOG | syslogd本身产生的消息 |
LOG\_USER | 来自其他用户进程的消息(默认) |
LOG\_UUCP | UUCP系统产生的消息 |
syslog函数
参数priority可以用来指明消息的 种类 和 等级
即priority的可选择同时包含了openlog中facility参数的可选择和level可选值
facility | 说明 |
---|---|
LOG\_AUTH | 认证相关的信息,入login,su,getty产生的信息 |
LOG\_CRON | 由cron或at产生的信息 |
LOG\_DAEMON | 系统守护进程产生的消息 |
LOG\_FTP | FTP守护进程产生的消息 |
LOG\_KERN | 内核产生的消息 |
LOG\_LOCAL0 – LOG\_LOCAL7 | 保留本地使用 |
LOG\_LPR | 行打印系统产生的消息 |
LOG\_MAIL | 邮件系统产生的消息 |
LOG\_NEWS | Usenet网络新闻系统产生的消息 |
LOG\_SYSLOG | syslogd本身产生的消息 |
LOG\_USER | 来自其他用户进程的消息(默认) |
LOG\_UUCP | UUCP系统产生的消息 |
LOG\_EMERG | 紧急状态(系统不可用) |
LOG\_ALTERT | 必须立即修复的状态 |
LOG\_CRIT | 严重状态(例如硬件故障) |
LOG\_ERR | 出错信息 |
LOG\_WARNING | 警告信息 |
LOG\_NOTICE | 正常,但重要的消息 |
LOG\_INFO | 消息性质的信息 |
LOG\_DEBUG | 调试信息 |
closelog函数
这个函数也是可选的,只有在调用openlog后才需要调用. 它用于关闭曾被用于与syslogd守护进程通信的描述符
#include
int main(int argc, char **argv) {
openlog("MyMsgMARK", LOG_CONS | LOG_PID, 0);
syslog(LOG_DEBUG,"hello'%s'\n",argv[0]);
closelog();
return 0;
}
strace这个程序
//通过strace可以看出,是通过socket来实现syslog的
...
socket(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/dev/log"}, 110) = 0
sendto(3, "<15>Oct 8 16:38:01 MyMsgMARK[27"..., 54, MSG_NOSIGNAL, NULL, 0) = 54
close(3) = 0
....
守护进程之编程规则
进程关系之会话
linux下C语言编程打印syslog日志
UNIX环境高级编程之syslog