首先学习下C语言如何创建一个进程:
#include 'unistd.h'
pid_t fork(void);//返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1
在linux中,一个进程可以通过调用fork()函数来创建一个新进程,原来的进程称为父进程,新进程称为子进程.
fork()函数被调用一次,但返回两次.其中父进程返回子进程的进程ID,子进程返回0.
子进程可以通过getppid()来获得父进程的进程ID.这样父子进程都能知道对方的信息了.
然后了解下什么叫孤儿进程:
当一个进程的父进程终止时,该进程就会变为孤儿进程,然后被init进程领养.
主要过程是,当一个进程终止时,内核逐个检查所有的活动进程,判断是否是终止进程的子进程.若是,则将该进程的父进程ID置为1(init进程的进程ID).
接着学习下什么叫守护进程:
定义:
守护(daemon)进程是在后台运行且不与任何控制终端相关联的进程.
用途:
守护进程一般作为服务器端程序,在后台一直运行,为系统提供服务.直到系统关闭时,才结束运行.
守护进程一般是进程组的组长进程,并且是会话的首进程.
创建方法:
1调用umask(0),打开所有权限,子进程会继承父进程的文件权限屏蔽字,这样可以避免创建文件时的权限限制.
2调用fork()创建子进程,然后父进程调用exit()退出,这样子进程就继承了父进程的进程组ID.
3调用setsid(),创建一个新的会话,使得子进程满足:a成为会话首进程,b成为进程组的组长进程,c不再拥有控制终端.
4将工作目录改为根目录,以免影响可加载文件系统.或者也可以改变到某些特定的目录.
5关闭所有打开的文件描述符.
6将标准输入、标准输出、标准错误输出重定向到dev/null,关闭守护进程与终端的交互.
消息输出:
daemon进程既然与终端没有交互,也就不能通过printf输出信息了.我们可以通过syslog机制来实现信息的输出.
输出. 接下来继续看代码,接着上一节看main()函数:
int main(int argc, char **argv)
{
.
.
.
if (server.daemonize) daemonize();//将server进程设置为守护进程
.
.
.
}
贴一下daemonize()的代码:
void daemonize(void)
{
int fd;
if (fork() != 0) exit(0);//如果fork()返回的不是0,说明是父进程,父进程要主动退出,使子进程成为孤儿
setsid(); /* create a new session */
/* Every output goes to /dev/null. If Redis is daemonized but
* the 'logfile' is set to 'stdout' in the configuration file
* it will not log at all. */
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
//stdin是FILE *类型,属于标准I/O,在;STDIN_FILENO是文件描述符,是非负整数,一般定义为0,1,2,属于没有buffer的I/O,直接调用系统调用,在.
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > STDERR_FILENO) close(fd);
}
}