精华内容
下载资源
问答
  • 总结下两次fork()的作用 首先,要了解什么叫僵尸进程,什么叫孤儿进程,以及服务器进程运行所需要的一些条件。...但是孤儿进程并不会像上面画的那样持续很长时间,系统发现孤儿进程时,ini...

    总结下两次fork()的作用

     

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

     孤儿进程

            孤儿进程是指父进程在子进程结束之前死亡(return 或exit)。如下图1所示:

    图1  孤儿进程

    但是孤儿进程并不会像上面画的那样持续很长时间,当系统发现孤儿进程时,init进程就收养孤儿进程,成为它的父亲,child进程exit后的资源回收就都由init进程来完成。

     

    僵尸进程

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

         

    图2   僵尸进程

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

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

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

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

    两次fork()技法

             两次fork()的流程如下所示:

    图3    两次fork的控制流

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

     

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

    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()就是为了解决这些相关的...但是孤儿进程并不会像上面画的那样持续很长时间,系统发现孤儿进程时,init进程就收养孤儿进

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

     孤儿进程

            孤儿进程是指父进程在子进程结束之前死亡(return 或exit)。如下图1所示:

    图1  孤儿进程

    但是孤儿进程并不会像上面画的那样持续很长时间,当系统发现孤儿进程时,init进程就收养孤儿进程,成为它的父亲,child进程exit后的资源回收就都由init进程来完成。

     

    僵尸进程

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

         

    图2   僵尸进程

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

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

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

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

    两次fork()技法

             两次fork()的流程如下所示:

    图3    两次fork的控制流

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

     

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

    1. int main(void)  
    2. {  
    3.     pid_t        pid;  
    4.   
    5.     if ( (pid = fork()) < 0)  
    6.           err_sys("fork error");  
    7.     else if (pid == 0)   
    8.         {                /* first child */  
    9.            if ( (pid = fork()) < 0)  
    10.                         err_sys("fork error");  
    11.            else if (pid > 0)  
    12.                  exit(0);        /* parent from second fork == first child */  
    13.   
    14.                 /* We're the second child; our parent becomes init as soon 
    15.                    as our real parent calls exit() in the statement above. 
    16.                    Here's where we'd continue executing, knowing that when 
    17.                    we're done, init will reap our status. */  
    18.   
    19.             sleep(2);  
    20.             printf("second child, parent pid = %d\n", getppid());  
    21.             exit(0);  
    22.         }  
    23.   
    24.     if (waitpid(pid, NULL, 0) != pid)        /* wait for first child */  
    25.             err_sys("waitpid error");  
    26.   
    27.         /* We're the parent (the original process); we continue executing, 
    28.            knowing that we're not the parent of the second child. */  
    29.   
    30.     exit(0);  
    31. }  
    32.        理所当然,第二个子进程的父进程是进程号为1的init进程。  

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

    展开全文
  • 进程基本状态

    2021-02-02 21:52:18
    1.进程三大基本状态 1.1 进程三种基本状态 就绪态 当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。...处于就绪状态的进程,当进程调度程序为之分配了处理机

    1.进程三大基本状态

    1.1 进程三种基本状态
    1. 就绪态
      当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
    2. 运行态
      当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为运行状态。
    3. 阻塞态
      正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信号等。
    1.2 进程三种状态间的转换
    1. 就绪 → 运行
      处于就绪状态的进程,当进程调度程序为之分配了处理机资源后,该进程便由就绪状态转变成执行状态。
    2. 运行 → 就绪
      处于执行状态的进程在其运行过程中,因分配给它的一个时间片已用完而不得不让出处理机,于是进程从运行状态转变成就绪状态。
    3. 运行 → 阻塞
      正在执行的进程因等待某种事件发生(如IO请求)而无法继续执行时,便从运行状态变成阻塞状态。
    4. 阻塞 → 就绪
      处于阻塞状态的进程,若其等待的事件已经完成(如IO结束),于是进程由阻塞状态转变为就绪状态。

    2.Linux进程状态(ps aux)

    1. R:可执行状态。
    2. S:可中断的睡眠状态。
    3. D:不可中断的睡眠状态。
    4. T:暂停状态。
    5. Z:僵尸状态,进程成为僵尸进程。
    6. X:退出状态,进程即将被销毁。

    补充:

    1. s:会话组长
    2. +:前台进程
    3. l :多线程程序
    4. <:比默认的优先级高(数字越小优先级越高。 nice/renice 命令可以调整优先级)
    5. N:比默认优先级更低
    6. t:正在被(如调试器)跟踪
    展开全文
  • 进程运行状态

    2011-11-09 09:20:00
    当进程正在等待 系统中的资源而处于等待状态时,则称其处于睡眠等待状态。在Linux系统中,睡眠等待状态分为可中断的和不可中断的等待状态。 (点击查看大图)图5-21 进程状态及转换关系 (1)运行状态(TASK_RUNNING...

    一个进程在其生存期内,可处于一组不同的状态下,称为进程状态,如图5-21所示。进程状态保存在进程任务结构的state字段中。当进程正在等待 系统中的资源而处于等待状态时,则称其处于睡眠等待状态。在Linux系统中,睡眠等待状态分为可中断的和不可中断的等待状态。

    2011-11-9-9-19

    (点击查看大图)图5-21  进程状态及转换关系

        (1)运行状态(TASK_RUNNING)。当进程正在被CPU执行,或已经准备就绪随时可由调度程序执行,则称该进程为处于运行状态 (running)。若此时进程没有被CPU执行,则称其处于就绪运行状态。见图5-21中3个标号为0的状态。进程可以在内核态运行,也可以在用户态运 行。当一个进程在内核代码中运行时,我们称其处于内核运行态,或简称为内核态;当一个进程正在执行用户自己的代码时,我们称其为处于用户运行态(用户 态)。当系统资源已经可用时,进程就被唤醒而进入准备运行状态,该状态称为就绪态。这些状态(图中中间一列)在内核中表示方法相同,都被称为处于 TASK_RUNNING状态。当一个新进程刚被创建出后就处于本状态中(最下一个0处)。

    (2)可中断睡眠状态(TASK_INTERRUPTIBLE)。当进程处于可中断等待(睡眠)状态时,系统不会调度该进程执行。当系统产生一个中断或者释放了进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(即可运行状态)。

    (3)不可中断睡眠状态(TASK_UNINTERRUPTIBLE)。除了不会因为收到信号而被唤醒,该状态与可中断睡眠状态类似。但处于该状态 的进程只有被使用wake_up()函数明确唤醒时才能转换到可运行的就绪状态。该状态通常在进程需要不受干扰地等待或者所等待事件会很快发生时使用。

    (4)暂停状态(TASK_STOPPED)。当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU时就会进入暂停状 态。可向其发送SIGCONT信号让进程转换到可运行状态。进程在调试期间接收到任何信号均会进入该状态。在Linux 0.12中,还未实现对该状态的转换处理。处于该状态的进程将被作为进程终止来处理。

    (5)僵死状态(TASK_ZOMBIE)。当进程已停止运行,但其父进程还没有调用wait()询问其状态时,则称该进程处于僵死状态。为了了让 父进程能够获取其停止运行的信息,此时子进程的任务数据结构信息还需要保留着。一旦父进程调用wait()取得了子进程的信息,则处于该状态进程的任务数 据结构就会被释放。

        当一个进程的运行时间片用完,系统就会使用调度程序强制切换到其他的进程去执行。另外,如果进程在内核态执行时需要等待系统的某个资源,此时该进程 就会调用sleep_on()或interruptible_sleep_on()自愿地放弃CPU的使用权,而让调度程序去执行其他进程。进程则进入睡 眠状态(TASK_UNINTERRUPTIBLE或TASK_INTERRUPTIBLE)。

         只有当进程从"内核运行态"转移到"睡眠状态"时,内核才会进行进程切换操作。在内核态下运行的进程不能被其他进程抢占,而且一个进程不能改变另一个进程的状态。为了避免进程切换时造成内核数据错误,内核在执行临界区代码时会禁止一切中断。

    转载于:https://www.cnblogs.com/xmphoenix/archive/2011/11/09/2242038.html

    展开全文
  • 进程状态及其转换

    2019-08-31 22:46:49
    ③就绪:一个处于等待状态进程因等待事件发生唤醒后,又因不可能立即得到处理机而进入就绪状态。 ④初始:进程刚被创建,由于其他进程正占有处理机而得不到执行,只能处于初始状态。 ...
  • 进程状态转换

    千次阅读 2012-02-15 21:44:09
    当进程正在等待 系统中的资源而处于等待状态时,则称其处于睡眠等待状态。 在Linux系统中,睡眠等待状态分为可中断的和不可中断的等待状态。    进程状态及转换关系 (1) 运行状态(TASK_RUNNING)。当进程...
  • 当进程执行过程中遇到等待事件,就会发生阻塞 阻塞–》就绪 当进程等待的事件到来,他从阻塞态变成就绪态 各进程状态含义 1.R(RUNNING),可执行状态 只有在该状态的进程才可能在CPU上运行。而同一时刻可能有多个...
  • 进程的三种基本状态 (1)就绪(Ready)状态 当进程已分配到除CPU以外的所有...(3)阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多...
  • 进程的基本状态及转换和阻塞及挂起的理解

    万次阅读 多人点赞 2018-06-24 16:12:26
    执行状态一个进程在处理机上运行,则称该进程处于运行状态。 阻塞状态:一个进程正在等待某一事件发生(例如请求I/O而等待I/O完成等)而暂时仃止运行,这时即使把处理机分配给进程也无法运行,故称该进程...
  • Linux进程的七种状态

    千次阅读 2018-03-30 12:10:06
    当进程正在等待 系统中的资源而处于等待状态时,则称其处于睡眠等待状态。在Linux系统中,睡眠等待状态分为可中断的和不可中断的等待状态。 运行状态(TASK_RUNNING)。当进程正在被CPU执行,或已经准备就绪...
  • 进程状态及转换关系

    千次阅读 2013-10-27 13:24:02
    当进程正在等待 系统中的资源而处于等待状态时,则称其处于睡眠等待状态。 在Linux系统中,睡眠等待状态分为可中断的和不可中断的等待状态。    进程状态及转换关系 (1) 运行状态(TASK_RUNNING):当进程...
  • Linux进程D状态

    2018-07-26 16:48:53
    Linux进程状态:S (TASK_INTERRUPTIBLE),可中断的睡眠状态。...这些事件发生(由外部中断触发、或由其他进程触发),对应的等待队列中的一个或多个进程将被唤醒。通过ps命令我们会看到,一般情况下,进程列...
  • linux6种进程状态

    2020-12-23 00:20:18
    当进程正在等待某个事件(比如网络连接或者信号量)到来,会进入此状态。这样的进程会被放入对应事件的等待队列中。当事件发生,对应的等待队列中的一个或者多个进程就会被唤醒。 三、D TASK_UNINTERRUPTIBLE 不...
  • linux 之进程状态

    2020-10-27 23:46:45
    睡眠态:cpu的资源被别的进程占用,该进程进入睡眠状态等待资源。(进程本省也可以调用sleep()函数来主动进入睡眠状态) 暂停态:一般是由user发信号给进程使其暂停。 僵尸态、死亡态:exit退出函数后,进程...
  • linux进程状态

    2019-04-23 18:13:58
    **S(中断):**进程处于休眠中,某个条件形成后或者接收到信号,则脱离该状态。 **D(不可中断):**进程不响应系统异步信号,即便用kill命令也不能将其中断。 **Z(僵死):**进程已经终止,但进程描述符依然...
  • linux进程的几种状态

    千次阅读 2016-09-12 22:15:02
    进程处于睡眠状态,处于这个状态的进程因为等待某事件的发生(比如等待socket连接、等待信号量),而被挂起。这些事件发生,对应的等待队列中的一个或多个进程将被唤醒。一般情况下,进程列
  • 阻塞状态:正在执行的进程由于发生某事件而暂时无法继续执行,便放弃CPU而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。比如进程当中调用wait()函数,会...
  • 进程内核对象 ...当进程正在运行,进程内核对象处于无信号状态当进程停止运行,进程内核对象处于有信号状态。 可以通过等待进程来检查进程是否仍然运行。 无成功等待的副作用。 示例: ...
  • 执行状态一个进程在处理机上运行,则称该进程处于运行状态。 阻塞状态:一个进程正在等待某一事件发生(例如请求I/O而等待I/O完成等)而暂时仃止运行,这时即使把处理机分配给进程也无法运行,故称该进程...
  • 在没有其他进程可以执行(如所有进程都在阻塞状态),通常会自动执行系统的空闲进程。 2)就绪状态(Ready):进程已获得除处理器外的所需资源,等待分配处理器资源;只要分配了处理器进程就可执行。就绪进程可以按多个...
  • 这些事件发生(由外部中断触发、或由其他进程触发),对应的等待队列中的一个或多个进程将被唤醒。 通过ps命令我们会看到,一般情况下,进程列表中的绝大多数进程处于TASK_INTERRUPTIBLE状态(除非机器的负载...
  • linux进程D状态_转

    2017-06-18 09:40:00
    Linux进程状态:S (TASK_INTERRUPTIBLE),可...这些事件发生(由外部中断触发、或由其他进程触发),对应的等待队列中的一个或多个进程将被唤醒。 通过ps命令我们会看到,一般情况下,进程列表中的绝大多数进程...
  • 运行态:**系统中可能会有很多个进程处于就绪态,CPU空闲,操作系统就会选择一个就绪进程,让它上处理机运行。如果一个进程此时再CPU上运行,那么这个进程就处于运行态。 **3.阻塞态:**在进程运行的过程中,...
  • 阻塞状态:正在执行的进程由于发生某事件而暂时无法继续执行,便放弃CPU而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。比如进程当中调用wait()函数,会...
  • 2.进程处于“核心态”,并且在等待不可获得的资源,处于“核心态 ”的资源默认忽略所有信号。只能重启系统。 kill 只能杀死处于用户状态的进程。 怎么杀父进程呢. ps -aux | grep "进程名称" 结果: Name: uwsgi ...
  • 阻塞状态进程因发生某种事件(如I/O请求、申请缓冲空间等)而暂停执行状态,亦即进程的执行受到阻塞,故称这种状态为阻塞状态,有时也称为“等待状态或“睡眠”状态。会根据堵塞的原因不同,会设置多个堵塞...
  • 就绪态(当进程创建完成后,便进入"就绪态",处于就绪态的进程已经具备运行条件,但由于没有空闲CPU,就暂时不能运行) 运行态 阻塞态(在进程运行的过程中,可能会请求等待某个事件的发生,如等待某种系统资源的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 411
精华内容 164
关键字:

当进程处于等待状态时