精华内容
下载资源
问答
  • 一次fork与两次fork的区别

    千次阅读 2018-03-24 21:42:41
    在讲一次fork和两次fork之前,有必要先来简单讲解一下wait的作用1、阻塞当前进程2、获得子进程退出的相关信息(回收僵尸进程)子进程不返回,父进程后边的内容就没法执行。注:wait函数只能在有子进程的父进程中调用...
    在讲一次fork和两次fork之前,有必要先来简单讲解一下wait的作用
    1、阻塞当前进程
    2、获得子进程退出的相关信息(回收僵尸进程)
    子进程不返回,父进程后边的内容就没法执行。
    注:wait函数只能在有子进程的父进程中调用。


    我们使用fork()函数创建一个子进程出来往往是为了父子进程能够同时执行两段代码。如果在父进程中不写wait()会导致子进程在退出后变成僵尸;但是使用wait()又会导致父进程阻塞,只有等子进程退出后才能继续执行,相当于依然是单进程。对于使用wait带来的问题,可以使用两次fork来解决。

    所以区别就是:使用wait时一次fork实现的其实也就是单进程,两次fork的话可以实现多个进程同时执行。

    怎么通过两次fork实现多进程的过程
    第一次fork 创建出一个子进程,然后父进程wait(),
    第二次fork 子进程再创建一个子进程,也就相当于有了一个孙子进程
    然后将第一次fork出来的子进程结束掉,它的父进程wait()不再阻塞,可以继续执行。
    此时的“孙子进程”就变成了孤儿进程,被托管到“孤儿院”(1号进程)。

    现在“爷爷进程”和“孙子进程”的执行互不影响,实现了多个进程的同时执行。

    展开全文
  • 关于两次fork

    2017-05-23 15:14:54
    两次fork()的作用 首先,要了解什么叫僵尸进程,什么叫孤儿进程,以及服务器进程运行所需要的一些条件。两次fork()就是为了解决这些相关的问题而出现的一种编程方法。 孤儿进程  孤儿进程是指父进程在子进程结束...

    我觉得这里还有些重要的东西没讲,比如setsid()(参见apne 8-11.).


    两次fork()的作用

    首先,要了解什么叫僵尸进程,什么叫孤儿进程,以及服务器进程运行所需要的一些条件。两次fork()就是为了解决这些相关的问题而出现的一种编程方法。

    孤儿进程

        孤儿进程是指父进程在子进程结束之前死亡(return 或exit)。如下图1所示:
        在一定时间内,当系统发现孤儿进程时,init进程就收养孤儿进程,成为它的父亲,child进程exit后的资源回收就都由init进程来完成。

    僵尸进程
        僵尸进程是指子进程在父进程之前结束了,但是父进程没有用wait或waitpid回收子进程。

        父进程没有用wait回收子进程并不说明它不会回收子进程。子进程在结束的时候会给其父进程发送一个SIGCHILD信号,父进程默认是忽略SIGCHILD信号的,如果父进程通过signal()函数设置了SIGCHILD的信号处理函数,则在信号处理函数中可以回收子进程的资源。

          事实上,即便是父进程没有设置SIGCHILD的信号处理函数,也没有关系,因为在父进程结束之前,子进程可以一直保持僵尸状态,当父进程结束后,init进程就会负责回收僵尸子进程。

          但是,如果父进程是一个服务器进程,一直循环着不退出,那子进程就会一直保持着僵尸状态。虽然僵尸进程不会占用任何内存资源,但是过多的僵尸进程总还是会影响系统性能的。黔驴技穷的情况下,该怎么办呢?

             这个时候就需要一个英雄来拯救整个世界,它就是两次fork()技法。

    两次fork()技法
           如上图3所示,为了避免子进程child成为僵尸进程,我们可以人为地创建一个子进程child1,再让child1成为工作子进程child2的父进程,child2出生后child1退出,这个时候child2相当于是child1产生的孤儿进程,这个孤儿进程由系统进程init回收。这样,当child2退出的时候,init就会回收child2的资源,child2就不会成为孤魂野鬼祸国殃民了。

    <unix环境高级编程>这本书里提供了两次fork的一个例子,代码如下:

     

    [cpp] view plaincopy
    
        int main(void)  
        {  
            pid_t        pid;  
          
            if ( (pid = fork()) < 0)  
                  err_sys("fork error");  
            else if (pid == 0)   
                {                /* first child */  
                   if ( (pid = fork()) < 0)  
                                err_sys("fork error");  
                   else if (pid > 0)  
                         exit(0);        /* parent from second fork == first child */  
          
                        /* We're the second child; our parent becomes init as soon 
                           as our real parent calls exit() in the statement above. 
                           Here's where we'd continue executing, knowing that when 
                           we're done, init will reap our status. */  
          
                    sleep(2);  
                    printf("second child, parent pid = %d\n", getppid());  
                    exit(0);  
                }  
          
            if (waitpid(pid, NULL, 0) != pid)        /* wait for first child */  
                    err_sys("waitpid error");  
          
                /* We're the parent (the original process); we continue executing, 
                   knowing that we're not the parent of the second child. */  
          
            exit(0);  
        }  

     

     

     

    
     

     


        理所当然,第二个子进程的父进程是进程号为1的init进程。  

        一言以蔽之,两次fork()是人为地创建一个工作子进程的父进程,然后让这个人为父进程退出,之后工作子进程就由init回收,避免了工作子进程成为僵尸进程。

     

     

    展开全文
  • 两次fork产生进程ID分析

    千次阅读 2018-05-12 10:23:24
    进行两次fork,会产生几个进程,他们的ID是多少,本文通过实例进行分析。基本概念:pid_t:pid_t是typedef定义的类型,表示进程的id。在sys/types.h中定义:typedef short pid_t;所以说pid_t就是一个short类型的...

    进行两次fork,会产生几个进程,他们的ID是多少,本文通过实例进行分析。

    基本概念:

    pid_t:

    pid_t是typedef定义的类型,表示进程的id。
    在sys/types.h中定义:typedef short   pid_t;

    所以说pid_t就是一个short类型的变量,实际表示的是内核中进程表的索引。

    pid_t getpid(void);

    返回目前进程的ID。

    pid_t fork(void);

    分叉函数。返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1。

    子进程将获得父进程数据空间、堆、栈等资源的副本,父子进程间不共享这些存储空间。

    写时拷贝是fork后来采用的优化技术,这样,对于fork后并不是马上拷贝内存,而是只有你在需要改变的时候,才会从父进程中拷贝到子进程中,这样fork后立马执行exec的成本就非常小了。

    1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <stdlib.h>
    4. int main()
    5. {
    6.     pid_t pid = fork();
    7.     if(pid < 0)
    8. perror("first fork\n");
    9.     else if(pid > 0)
    10.     {
    11. printf("父进程ID:%d\n",getpid());
    12. printf("子进程ID:%d\n",pid);
    13.     }
    14.     else
    15.     {
    16. pid_t _pid = fork();
    17. if(_pid < 0)
    18.          perror("second fork\n");
    19. else if(_pid > 0)
    20. {
    21.     printf("子进程ID:%d\n",getpid());
    22.     printf("孙进程ID:%d\n",_pid);
    23. }
    24. else
    25.     printf("孙进程ID:%d\n",getpid());
    26.     }
    27.     exit(0);
    28. }

    结果如下:

    父进程ID:4670
    子进程ID:4671
    子进程ID:4671
    孙进程ID:4672
    孙进程ID:4672

    图示:


    1,2行结果是由11、12行代码产生的

    3,4行结果是由21、22行代码产生的

    5行结果是由25行代码产生的








    展开全文
  • 为什么有时候有些代码会调用两次fork呢? (1)调用一次fork的作用: 第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务,因为调用setsid函数的进程不能是进程组...

    在讲一次fork和两次fork之前,有必要先来简单讲解一下wait的作用
    1、阻塞当前进程
    2、获得子进程退出的相关信息(回收僵尸进程)
    子进程不返回,父进程后边的内容就没法执行。
    注:wait函数只能在有子进程的父进程中调用。

    我们使用fork()函数创建一个子进程出来往往是为了父子进程能够同时执行两段代码。如果在父进程中不写wait()会导致子进程在退出后变成僵尸;但是使用wait()又会导致父进程阻塞,只有等子进程退出后才能继续执行,相当于依然是单进程。对于使用wait带来的问题,可以使用两次fork来解决

    所以区别就是:使用wait时一次fork实现的其实也就是单进程,两次fork的话可以实现多个进程同时执行。

    怎么通过两次fork实现多进程的过程:
    第一次fork 创建出一个子进程,然后父进程wait(),
    第二次fork 子进程再创建一个子进程,也就相当于有了一个“孙子进程”。
    然后将第一次fork出来的子进程结束掉,它的父进程wait()不再阻塞,可以继续执行。
    此时的“孙子进程”就变成了孤儿进程,被托管到“孤儿院”(1号进程)。
    

    为什么有时候有些代码会调用两次fork呢?
    
    1. 调用一次fork的作用:
        第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务,
        因为调用setsid函数的进程不能是进程组组长,如果不fork出子进程,则此时的父进程是进程组组长,就无法调用setsid。
        当子进程调用完setsid函数之后,子进程是会话组长也是进程组组长,并且脱离了控制终端,
        此时,不管控制终端如何操作,新的进程都不会收到一些信号使得进程退出。
        
    2. 第二次fork的作用:
       虽然当前关闭了和终端的联系,但是后期可能会误操作打开了终端。只有会话首进程能打开终端设备,
       也就是再fork一次,再把父进程退出,再次fork的子进程作为守护进程继续运行,
       保证了该精灵进程不是对话期的首进程,第二次不是必须的,是可选的。
    
    展开全文
  • 下面总结下两次fork()的作用。 首先,要了解什么叫僵尸进程,什么叫孤儿进程,以及服务器进程运行所需要的一些条件。两次fork()就是为了解决这些相关的问题而出现的一种编程方法。 孤儿进程  孤儿进程是指父...
  • qemu中daemonize为什么要两次fork

    千次阅读 2014-09-24 22:23:21
    一开始不理解为什么要两次fork,后来查网上资料得知,两次fork是为了防止第一个子进程打开终端。首次fork使父进程退出,子进程继承了父进程的进程组ID,但具有一个新的进程ID,这就保证了子进程不是一个进程组的首...
  • 在一些程序中经常看见使用两次fork创建子进程,原因如下: 以下摘自《UNIX环境高级编程》 如果一个进程fork一个子进程,但不要它等待子进程终止,也不希望子进程处于僵尸状态直到父进程终止,实现这一要求的技巧...
  • 为何要使用两次fork?

    2017-10-16 15:13:17
    两次fork法: 流程如图所示: int main( int argc, char *argv[]) { //这是一个服务器进程 pid_t pid; if ((pid=fork())< 0 ) //服务器创建一个子进程 { cout "error" ; } else if (pid==...
  • 最近在看APUE,在进程控制章节中有个关于两次fork防止进程僵死的列子很是不理解,经过一番研究发现原来原理很简单,以下是实例: 1 #include 2 #include 3 #include 4 5 int main(void) 6 { 7 pid_t pid;...
  • fork函数的几个基本知识点 ①父子进程执行顺序:先后顺序由程序本身来决定,至于哪个先,在用户态看来都是随机的。 ② fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等...
  • 先给出一个会产生僵尸进程的程序,运行后观察结果. #include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/wait.h>... pid = fork(); if(pid > 0)...
  • 僵尸进程产生的原因是父进程没有处理子进程的退出信息,导致子进程退出后因zombie结构没有及时释放而变成了僵尸进程,为避免该问题的产生,建议采用fork两次的方案。 进程关系为:爷爷->父亲->孙子。 方案分析: ...
  • 两次fork防止僵尸进程

    2014-03-02 23:28:34
    3、解决办法:调用两次fork避免僵尸进程 #include "apue.h" #include int main(void) { pid_t pid; if ((pid = fork()) ) { err_sys("fork error"); } else if (pid == 0) // 第一个子进程 { if ((pid =...
  • 可以看到上面的代码中调用了fork,也有人在setsid函数调用之后再调用一次fork,是对程序的优化,但第二次fork并不是必须。 首先第一次fork:让shell认为这条命令已经终止,不用挂在终端输入上。也是为了后面的...
  • APUE 上的定义如下: ...为何两次Fork 这是创建Daemon进程的大致步骤及作用: 第一次fork(产生父子进程,父进程退出,子进程与父进程控制终端脱离) 子进程setsid(子进程成为会话组长,与...
  •  为避免产生僵尸进程,可以通过两次fork()操作,第一次fork产生第一个子进程,第二次fork由第一个子进程产生第二个子进程,目前的状态变成:爷爷->父亲->孙子。爷爷回收父亲后退出,此时孙子的父进程自动托管给init...
  • 上一篇博客讲了,fork的作用,那么为什么有时候有些代码会调用两次fork呢? (1)调用一次fork的作用:  第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端输入上,还有就是为了后面的setsid服务...
  • 前几天接到某互联网公司的电话面试,面试官问我两次fork()的作用,我一头雾水,说不知道。知识面还是太窄了。下面就总结下两次fork()的作用。   首先,要了解什么叫僵尸进程,什么叫孤儿进程,以及服务器进程...
  • 要知道在创建守护进程的时候fork一次和fork两次两者有什么区别,就要先知道第一次fork和第二次fork都起到了什么作用? (1)调用一次fork的作用: 第一次fork的作用是让shell认为这条命令已经终止,不用挂在终端...
  • 两次fork()就是为了解决这些相关的问题而出现的一种编程方法。 孤儿进程 孤儿进程是指父进程在子进程结束之前死亡(return 或exit)。如下图所示: 但是孤儿进程并不会像上面画的那样持续很长时间,当系统发现...
  • 创建守护进程为什么要fork两次

    千次阅读 2017-06-19 17:12:27
    1、守护进程的概念与特点 2、创建守护进程 3、创建守护进程为什么需要fork两次

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,143
精华内容 39,257
关键字:

两次fork