b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

守护进程

电脑杂谈  发布时间:2020-06-17 19:18:32  来源:网络整理

守护进程_僵尸进程 孤儿进程_僵尸进程和孤儿进程

守护程序是在后台长时间运行的进程,不受任何终端的控制.

我们知道Linux有许多内置的守护程序,例如syslogd,crond,sendmail等. 为什么用户或开发人员编写的程序需要成为守护程序?

这主要是由于守护程序的性质. 守护程序进程不受任何终端的控制,以防止进程在执行过程中在终端上输出信息,并防止进程被终端生成的信息打断(例如输入ctrl + c)在终端上或直接退出由ssh连接丢失导致的进程). 通用服务软件需要这种性质,例如nginx,它必须运行很长时间,并且不受终端输入的影响.

此步骤有两个效果:

1. 非系统守护程序可以由用户手动执行,例如终端外壳上的./nginx. 父进程的终止将使外壳程序认为该命令已执行.

僵尸进程和孤儿进程_僵尸进程 孤儿进程_守护进程

2. 子进程将继承父进程的进程组ID,但是子进程绝对不是组长. 此功能是呼叫setsid的下一步.

此步骤具有三个效果:

1. 使该过程成为新会话的第一个过程.

2. 使流程成为新流程组的负责人.

3. 将过程移出控制终端. (登录到终端的用户将生成一个新的会话,例如ssh telnet等. 这些登录名生成的会话都是可见的,而setid生成的新会话则是不可见的,因此达到了离开终端控件的目的. ...个人理解,我不知道我是否正确. )

僵尸进程 孤儿进程_守护进程_僵尸进程和孤儿进程

此步骤具有三个效果:

1. 修改从父进程继承的文件屏蔽字,以避免父进程最初设置的文件屏蔽字对守护程序不合理.

2. 守护程序应该需要调用某些库函数守护进程,并且这些库函数可能不允许调用者通过显式参数指定模式,因此最好在此过程中设置所需的默认文件. 屏蔽词.

此步骤是可选的,主要是让守护程序设置自己的工作目录,而不是严格继承父进程.

此步骤也是可选的,如果守护程序认为有必要,则可以这样做. 如果您确定没有从父进程继承的文件描述符,或者如果您需要这些继承的文件描述符,则无需关闭它们.

僵尸进程 孤儿进程_僵尸进程和孤儿进程_守护进程

目的很明显. 我们既不想在终端上看到守护程序的输出,也不希望用户希望守护程序读取他们在终端上的输入.

我们使用nginx实施守护进程来具体说明上述步骤:

ngx_int_t
ngx_daemon(ngx_log_t *log)
{
    int  fd;
	// 1.创建子进程,父进程退出。
    switch (fork()) {
    case -1:
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
        return NGX_ERROR;
    case 0:
        break;
    default:
        exit(0);
    }
    ngx_parent = ngx_pid;
    ngx_pid = ngx_getpid();
	// 2.创建新会话。
    if (setsid() == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
        return NGX_ERROR;
    }
	// 3.设置文件屏蔽字。
    umask(0);
	// 6.将标准输出和标准输入重定向到/dev/null。
    fd = open("/dev/null", O_RDWR);
    if (fd == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "open(\"/dev/null\") failed");
        return NGX_ERROR;
    }
    if (dup2(fd, STDIN_FILENO) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
        return NGX_ERROR;
    }
    if (dup2(fd, STDOUT_FILENO) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
        return NGX_ERROR;
    }
#if 0 //这里保留了标准错误输出,使得nginx在启动过程中有致命的错误导致不能启动时,输出这些错误。
    if (dup2(fd, STDERR_FILENO) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
        return NGX_ERROR;
    }
#endif
    if (fd > STDERR_FILENO) {
        if (close(fd) == -1) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
            return NGX_ERROR;
        }
    }
    return NGX_OK;
	// 4和5可做可不做。
}

有许多实现两次fork的守护进程. 这主要是为了避免产生僵尸进程.

Linux中的进程属于一棵树,树的根节点是init(pid为1). 除了初始化进程外,其他进程还将有一个父进程,该父进程负责分配(分叉)和回收(等待)其子进程资源.

僵尸进程和孤儿进程_僵尸进程 孤儿进程_守护进程

父进程在子进程之前退出: 其子进程由init接管,而父进程变为init. 该子进程称为孤立进程.

子进程在父进程之前退出: 子进程结束调用exit清理资源后,它此时并未结束守护进程,而是进入僵尸状态,等待其父进程调用wait4清除其task_struct . 也就是说,在退出调用之后,父进程调用wait4之前,子进程称为僵尸进程.

如果一切正常,则儿童僵尸状态将只存在很短的时间. 但是,在某些异常情况下,如果父进程长时间在其他服务上受阻且无法调用wait4,则将导致僵尸状态长时间存在. 只有父进程可以回收子进程的资源,因此父进程不会死,其他进程也无法解决僵尸进程. 父进程已死,则可以由init接管,并且僵尸进程不存在. 僵尸进程是服务器的禁忌,大量僵尸进程将导致服务器停机.

出于僵尸进程的考虑,守护进程将两次调用fork: 父进程生成守护进程后,还有其他事情要做,它的“生命意义”不仅仅是创建守护进程. 这时,如果守护进程由于某些意外事件而退出,并且父进程在其他服务中被阻止并且无法调用wait4,则将生成一个僵尸进程. 如果父进程首先分叉子进程,则子进程立即分叉孙子进程,以便孙子进程成为守护进程,并立即由init接管. 无论父进程如何阻塞,它都与守护进程无关.

您是否需要两个fork主要取决于您自己的设计,上面的nginx没有两个fork,因为设计非常清晰,父进程在创建守护程序后立即退出,僵尸进程不会有任何问题.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-248875-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 折笠爱
        折笠爱

        给无望的人希望和生命的喜悦

      热点图片
      拼命载入中...