Chinaunix首页 | 论坛 | 博客
  • 博客访问: 968730
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-12-25 19:08:01

13.3 coding rules

建立一个daemon的方法:

其实主要就是让他实现上面描述的特点:

1.设置进程的umask0。这样当daemon要创建一些指定了permission mask的文件的时候,最终生成的文件的权限不会受到dameon进程的mask的影响

2. fork 然后parent exit,这是为了

让这个进程不是一个process group leader,这是调用setsid的前提.

3. setsid, 它会有如下结果

该进程会成为一个session leader, 会成为一个proces group leader,会不再拥有controlling terminal。(一个session leader 第一次打开的terminal 会被默认当作是session controlling terminal,当然如果你没有设置一些选项的话,如O_NOCTTY。)

4.降CWD目录更改为root目录

防止长期运行的daemon进程会影响到一些文件系统的umount。(例如如果你设置的目录恰好在一个要被umount的文件系统的路径下)

5.关闭一些不必要的file descriptors

6. 0,1,2 file descriptor可以重定向到比如/dev/null

下面是一个例子:

Figure 13.1. Initialize a daemon process

#include "apue.h"

#include

#include

#include

 

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 systems 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);

    }

}

 

上面代码中,关于fd0,fd1,fd2就是将012给重定向了,为什么这么说,是因为,你在上面已经将所有的descriptor给关闭了,那么你次打开文件的时候,会默认的从0开始分配descriptor。可以测试一下。注意,在你测试的时候,由于你的1已经不对应标准输出,所以不能再用printf之类的输出了,我使用的是将结果写入一个文件。

 

阅读(946) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~