Because they don’t have a controlling terminal, we say that they run in the background.
some common system daemons and how they relate to the concepts of process groups
linux 下面我用root权限获取的信息:
ps -efj
UID PID PPID PGID SID C STIME TTY TIME CMD
root 1 0 1 1 0 13:08 ? 00:00:03 /sbin/init
root 2 0 0 0 0 13:08 ? 00:00:00 [kthreadd]
root 3 2 0 0 0 13:08 ? 00:00:01 [ksoftirqd/0]
root 5 2 0 0 0 13:08 ? 00:00:00 [kworker/0:0H]
root 6 2 0 0 0 13:08 ? 00:00:00 [kworker/u:0]
root 7 2 0 0 0 13:08 ? 00:00:00 [kworker/u:0H]
root 8 2 0 0 0 13:08 ? 00:00:00 [migration/0]
root 9 2 0 0 0 13:08 ? 00:00:00 [rcu_bh]
root 10 2 0 0 0 13:08 ? 00:00:03 [rcu_sched]
root 11 2 0 0 0 13:08 ? 00:00:00 [watchdog/0]
root 12 2 0 0 0 13:08 ? 00:00:06 [watchdog/1]
root 13 2 0 0 0 13:08 ? 00:00:00 [ksoftirqd/1]
root 14 2 0 0 0 13:08 ? 00:00:00 [migration/1]
........
........
jasonleaster 2093 2028 2028 2028 0 13:12 ? 00:00:02 /usr/lib/gnome-settings-daemon/gnome-settings-daemon
jasonleaster 2105 1 2104 2104 0 13:12 ? 00:00:00 /usr/bin/pulseaudio --start --log-target=syslog
jasonleaster 2112 1 2077 2077 0 13:12 ? 00:00:00 /usr/lib/gvfs/gvfsd
The system processes you see will depend on the operating system implementation. Anything with a parent process ID of 0 is usually a kernel process started as part of the system bootstrap procedure.
Note that most of the daemons run with superuser (root) privileges.Most of the user-level daemons are process group leaders and session leaders, and are the only processes in their process group and session. (The one exception is rsyslogd .) Finally,note that the parent of the user-level daemons is the init process.
1. Call umask to set the file mode creation mask to a known value, usually 0. The inherited file mode creation mask could be set to deny certain permissions.
2. Call fork and have the parent exit.
3. Call setsid to create a new session.
4. Change the current working directory to the root directory .
5. Unneeded file descriptors should be closed.
6. Some daemons open file descriptors 0, 1, and 2 to /dev/null so that any library routines that try to read from standard input or write to standard output or standard error will have no effect.
One problem a daemon has is how to handle error messages. A central daemon error-logging facility is required.
1. Kernel ro utines can call thelog function. These messages can be read by any user process that opens and reads the /dev/klog device.
2. Most user processes (daemons) call the syslog(3) function to generate log messages.
3. A user process on this host, or on some other host that is connected to this host by a TCP/IP network, can send log messages to UDP port 514.
Our interface to this facility is through the syslog function.
#include <syslog.h> void openlog(const char *ident,int option ,int facility ); void syslog(intpriority,const char *format ,...); void closelog(void); int setlogmask(int maskpri); Returns: previous log priority mask value
没有terminal联系起来,daemon最多的联系就是logfile了。这个时候就是分析各种各样的log file...
linux下各种各样的log file
jasonleaster@ubuntu:/var/log$ ls
alternatives.log apt ConsoleKit dpkg.log.2.gz kern.log.3.gz pm-powersave.log.4.gz udev
alternatives.log.1 auth.log cups dpkg.log.3.gz kern.log.4.gz samba ufw.log
alternatives.log.2.gz auth.log.1 dist-upgrade dpkg.log.4.gz lastlog speech-dispatcher unattended-upgrades
apport.log auth.log.2.gz dmesg faillog lightdm syslog upstart
apport.log.1 auth.log.3.gz dmesg.0 fontconfig.log mail.err syslog.1 vmware-tools-upgrader.log
apport.log.2.gz auth.log.4.gz dmesg.1.gz fsck mail.log syslog.2.gz wtmp
apport.log.3.gz boot dmesg.2.gz hp news syslog.3.gz wtmp.1
apport.log.4.gz boot.log dmesg.3.gz installer pm-powersave.log syslog.4.gz Xorg.0.log
apport.log.5.gz bootstrap.log dmesg.4.gz kern.log pm-powersave.log.1 syslog.5.gz Xorg.0.log.old
apport.log.6.gz btmp dpkg.log kern.log.1 pm-powersave.log.2.gz syslog.6.gz Xorg.1.log
apport.log.7.gz btmp.1 dpkg.log.1 kern.log.2.gz pm-powersave.log.3.gz syslog.7.gz Xorg.1.log.old
表示我木有找到/var/log/messages....
日志文件系统不熟悉。。。感觉daemon学的有点。。。不懂。。。几乎就写不出demo出来。。。
待更新吧。。。待俺功力精进之后。。。。
update: 2014.05.10
#include <syslog.h> #include <fcntl.h> #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> #include <myerr.h> void daemonize(const char * cmd) { int i,fd0,fd1,fd2; pid_t pid; struct rlimit rl; struct sigaction sa; umask(0); if(getrlimit(RLIMIT_NOFILE,&rl) < 0) { err_quit("%s: can't get file limit",cmd); } if((pid = fork()) < 0) { err_quit("%s : can't fork",cmd); } else if(pid != 0) { exit(0); } //第一次fork,然后杀掉parent process,得到child process,这时候这个child process还在原来的process group里面。这个grp成为了孤儿进程组!! setsid(); //由于此时child process所在的进程组它不是process leader,leader是他原来还活着的parent process(此时parent是 init进程),于是它可以成为session leader sa.sa_handler = SIG_IGN; //成为orphaned group,会被发送SIGHUP和SIGCONT信号(由0.12内核代码阅读所得,可能和现在的3.0的略有不同) sigemptyset(&sa.sa_mask); //统统忽略掉这两个信号,防止这个即将称为deamon进程被杀 sa.sa_flags = 0; if((sigaction(SIGHUP,&sa,NULL)) < 0) { err_quit("%s can't fork\n",cmd); } if((pid = fork()) < 0) //第二次fork是为了杀死原来的进程,创造出新child proces,新的child proces不是session leader,于是不可能再与terminal有联系!That's all! { err_quit("%s : can't fork",cmd); } else if (pid != 0) { exit(0); } if(chdir("/") < 0) //切换当前工作目录 { err_quit("%s can't change dirctory to /\n"); } if(rl.rlim_max == RLIM_INFINITY) { rl.rlim_max = 1024; } for(i = 0; i < rl.rlim_max;i++) { close(i); } fd0 = open("/dev/null",O_RDWR); //因为close(i)关闭了所有的file descriptor,于是这时候open打开的/dev/null的fd是0,fd 0 1 2 // 都定向到null,保证不会有信息通过 fd 0 1 2输入输出到标准输入输出错误 fd1 = dup(0); fd2 = dup(0); openlog(cmd,LOG_CONS,LOG_DAEMON); //打开syslog,把cmd字符串写进去,这里cmd是helloworld,可以在syslog里面找到,见下面的图 if(fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR,"unexpected file deacriptors %d %d %d\n",fd0,fd1,fd2); exit(1); } } int main() { daemonize("hello world!\n"); return 0; }
这里如果把if判断条件改一下,就可以调用syslog函数,把参数写入syslog文件
if(fd0 == 0 || fd1 != 1 || fd2 != 2)