`
memorymyann
  • 浏览: 270763 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

wait4的实现

阅读更多

不贴实现的代码了,很长,估计大家看了也不愿意读。这里介绍下它实现的流程。

首先实现的功能是:根据给定的参数去守候子进程,收集子进程使用资源的记录信息,比回收子进程没有回收的资源,系统堆栈空间。

流程:某个进程调用了wait4函数,假设调用如:wait(要等待的子进程的pid,WUNTRACED,status,reus)。

wait第一个动作就是current->state = TASK_INTERRUPTIBLE;将当前进程的状态设置成TASK_INTERRUPTIBLE表示挂起,休眠,阻碍等等。接下来是一大堆的检查判断,判断通过的话就执行current->state = TASK_RUNNING;,将进程状态设置成可以运行,然后执行remove_wait_queue(&current->wait_chldexit,&wait);再返回,至于是什么判断这里先不管这些,最后执行schedule();意思就是进程从新调度。下面我们看看这么做的意义:

首先我们把进程状态改成了阻塞,如果判断条件没通过,意思就是说在调用schedule()后当前进程就被阻塞不会运行了。那什么时候会唤醒呢,前面我们讨论过exit函数,一个进程在exit时候就会唤醒他的父进程,这里就是他该唤醒的地方,唤醒后,父进程会循环继续回到current->state = TASK_INTERRUPTIBLE;继续运行,如此循环,那么退出循环就是以下几个条件之一被满足:

a.所等待的子进程状态变成了TASK_STOPPED或者TASK_ZOMBIE;

b.所等待的子进程存在但不是上面2种状态,而调用参数为WNOHANG,或者当前进程收到了其它的信号;

c.所等待的进程PID不存在,或者不是当前进程的子进程。

这几种条件判断正好适应以下几种情况:

1.等待子进程被跟踪,属于TASK_STOPPED,

2.等待子进程僵死,属于TASK_ZOMBIE,

3.参数为WNOHANG,正好符合我们wait4调用参数WNOHANG的意义,就是不等待子进程直接执行完毕。

4.进程收到其它信号,属于其它情况。

5.等待进程的PID不存在或者不是当前进程的子进程,代码写错了。

 

我想我们的代码wait(要等待的子进程的pid,WUNTRACED,status,reus)应该是在第2种情况,此时当子进程exit后,便会唤醒父进程然后,父进程将会回到current->state = TASK_INTERRUPTIBLE,会再次检查条件,发现第a个条件满足到达代码current->state = TASK_RUNNING;处(在到达这里之前还有其它动作,读者可以自己参看代码)。接下来就是回收资源,拷贝子进程的资源使用信息。

 

下面是个小实验,我们知道当我们新建一个进程后,如果我在父进程里面没有调用wait4是不是表示这个子进程系统堆栈空间不会被回收了呢?我们看下面的程序

[root@liumengli wait]# cat print.c
#include "stdio.h"

int main() {
        int i;
        //for (i = 0; i < 50; i++)
        while(1)
                printf("Hello, This is print!!!\n");
        exit(1);
}
[root@liumengli wait]# cat test_wait.c
#include "stdio.h"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>

int main() {
        int child;
        int * status;
        struct rusage  * rus;
        char * argu[] = {"/program/wait/print", NULL};
        if(!(child = vfork())) {
                execve("/program/wait/print", argu, NULL);
        } else {
                //wait4(child,status,WUNTRACED,rus);
                //printf("The son's pid:%d, status:%d, The memory is:%d\n", child, WIFEXITED(status),rus->ru_nswap);
                while(1)
                      printf("This is test_wait\n");
        }
        exit(0);
}
我将print.c编译完毕,名字为print, test_wait.c编译成了test_wait,我在虚拟机里面启动中断,然后执行命令./test_wait,这个大家大概都知道了,就是2个死循环在一直打印,我用SSH链接我的虚拟机,执行PS命令看下系统进程的信息,如下:

0 S     0  2901  2898  0  76   0 -  1438 wait   pts/2    00:00:00 bash
0 R     0  6241  2901  3  77   0 -   353 -      pts/2    00:00:00 test_wait
0 R     0  6242  6241  0  79   0 -   353 -      pts/2    00:00:00 print
4 R     0  6245  2854  0  76   0 -  1379 -      pts/1    00:00:00 ps
这里我们看到,明显这2个进程都在运行,接下来我执行kill 6242杀死print进程

[root@liumengli wait]# kill 6242
[root@liumengli wait]# ps -le
下面是杀死print进程后的进程信息:

0 S     0  2901  2898  0  76   0 -  1438 wait   pts/2    00:00:00 bash
0 S     0  6241  2901  5  75   0 -   353 write_ pts/2    00:00:04 test_wait
0 Z     0  6242  6241  3  75   0 -     0 exit   pts/2    00:00:03 print <defunct>
4 R     0  6257  2854  0  76   0 -  1379 -      pts/1    00:00:00 ps
这里我们看到print依然存在,而且被ps检索到,这就是僵死状态,我们没有执行wait所以到目前它的系统堆栈没有被回收,如果我们杀死test_wait呢

[root@liumengli wait]# kill 6241
0 S     0  2901  2898  0  76   0 -  1438 -      pts/2    00:00:00 bash
4 R     0  6274  2854  0  76   0 -  1379 -      pts/1    00:00:00 ps
这下我们看到2个进程都没有了,那是谁回收了print的资源。我想应该是init进程,我们在exit提过,所有无主的孤儿进程都会被送进托儿所,虽然是僵死下的print,在其死亡后尸体也是被交给init来处理的,我们查看了wait4代码就清楚了,我猜init的 wait等待进程的ID应该是小于-1,这样他就等待所有的子进程,当test_wait在exit以后,他不但会把孤儿托付给init还会向init发送信号,接受到信号的init从沉睡中醒来,完成检测所有子进程,然后回收资源的任务。我猜的,我想这些应该在读完系统初始化后可以揭晓吧。

分享到:
评论

相关推荐

    Waitqueue、Event及Semaphore的实现机制分析

    Linux内核提供了多种工具来实现这些功能,包括Waitqueue(等待队列)、Event(事件)以及Semaphore(信号量)。本文将深入探讨这三种机制的实现原理。 **1. Waitqueue** Waitqueue是Linux内核中用于线程等待和唤醒...

    wait()编程wait()编程wait()编程wait()编程

    综上所述,`wait()`是Java多线程编程中的关键工具,正确使用它可以实现复杂的线程同步和协作策略。理解其工作原理和使用场景,有助于编写出高效、稳定的多线程程序。在实际应用中,应结合`notify()`和`notifyAll()`...

    任务一-系统调用spawn_kill_wait实现1

    本文将介绍操作系统研讨课中 Project 4 Task 1 的系统调用 spawn、kill、wait 的实现。该任务的主要目的是实现三个系统调用:spawn、kill、wait,即 kernel.c 中的三个函数:do_spawn、do_kill、do_wait。 spawn ...

    stop and wait

    但是,滑动窗口协议的实现和管理比stop and wait复杂得多。 8. **网络延迟和往返时间RTT**:在评估stop and wait协议性能时,网络延迟(包括传输时间和处理时间)是非常重要的因素,因为它直接影响了等待确认的时间...

    CLOSE_WAIT错误详解

    4. **长时间无数据交换**:如果服务器在CLOSE_WAIT状态下长时间没有与客户端交互,可能导致连接占用资源过多。 **解决CLOSE_WAIT错误的策略** 1. **优化代码**:确保服务器端的程序在接收FIN标志后,及时发送FIN...

    大量TIME_WAIT状态的连接解决方法

    4. **缩短TIME_WAIT超时时间**:减少TIME_WAIT状态的持续时间有助于缓解该状态的连接积压。通过修改`net.ipv4.tcp_fin_timeout`参数,可以调整TIME_WAIT状态的默认超时时间。 ```bash ...

    oraclev$sessionv$session_wait用途详解

    综上所述,`v$session`与`v$session_wait`视图是Oracle数据库管理中不可或缺的工具,它们提供的详尽信息是实现高效数据库管理和性能优化的基础。通过熟练掌握这两个视图的查询技巧,数据库管理员可以更加精准地监控...

    信号pthread_cond_wait

    总结,`pthread_cond_wait`是多线程编程中实现线程同步的重要工具,正确理解和使用它能够帮助我们编写出高效、可靠的多线程程序。然而,由于其涉及到复杂的线程交互,因此在使用时需要特别注意避免死锁和无效等待,...

    fast-wait-free-queue, 并发队列实现的基准框架.zip

    fast-wait-free-queue, 并发队列实现的基准框架 快速等待空闲队列这是评估并发队列性能的基准测试框架。 目前,它包含4 个并发队列。 它们是:一个快速等待队列 wfqueueafek的Morrison和 lcrqkallimanis的Fatourou和...

    Iowait 的成因、对系统影响及对策

    Iowait 的计算可以通过监控Linux系统的 `/proc/stat` 文件来实现。这个文件包含了关于系统CPU使用情况的各种统计信息。`vmstat` 命令会读取 `/proc/stat` 中的数据,并计算出iowait时间。在内核中,`proc_misc.c` ...

    前端开源库-wait-for-event

    在前端开发领域,开源库是开发者们常用的工具,它们提供了丰富的功能,简化了代码实现,提高了开发效率。"wait-for-event"是一个专为前端设计的开源库,它的核心功能是帮助开发者等待特定事件的发生,从而更好地控制...

    MySQL wait_timeout连接超时

    这可以通过在MySQL配置文件(如my.cnf)中修改或在运行时使用`SET GLOBAL wait_timeout = 新的超时值`命令来实现。 2. **定期发送心跳请求**:应用程序可以在连接空闲时定期发送简单的查询(如`SELECT 1`)来保持...

    wait1_Windows编程_wait_

    4. **计时等待**: 描述中提到的"wait prozess for milliseconds"表明我们可能在关注带有时间限制的等待。在Windows API中,可以通过设置超时参数来实现这种计时等待。如果等待的对象在指定时间内没有变为有信号状态...

    UE4使用C++在蓝图中实现打开外部exe程序功能(含源码)

    在UE4(Unreal Engine 4)中,开发者经常需要集成各种自定义功能,其中之一就是通过C++代码在蓝图中实现打开外部exe程序。这个功能对于游戏中的交互性或者工具集成非常有用,例如启动辅助编辑器、执行数据分析脚本等...

    Shell等待示例[ShellWait.rar]-精品源代码

    在这个名为"Shell等待示例[ShellWait.rar]"的压缩包中,包含的是一些与Shell脚本编程相关的源代码文件,这些文件可能是为了演示如何在Shell脚本中实现程序或进程的等待功能。 1. **ShellWait.bas**:这是一个Basic...

    系统调优,你所不知道的TIME_WAIT和CLOSE_WAIT1

    4. **调整TIME_WAIT计时器**:在必要时,可以适当降低TIME_WAIT的等待时间,但要注意这可能会影响TCP的可靠性。 CLOSE_WAIT状态: CLOSE_WAIT状态发生在被动关闭连接的一方,即接收到对方的FIN包后,表示它已经收到...

    解决SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded_runtimeerror怎么修复

    也可以在应用层面上实现死锁的检测和处理。 综上所述,解决"Lock wait timeout exceeded"问题需要从多方面入手,包括优化SQL语句、调整数据库配置、改进事务处理逻辑等。理解错误背后的原因并采取适当的措施,对于...

    信号量同步等待机制 semaphore wait-and-signal

    4. **有限等待**:任何线程在尝试进入其临界区时,必须能够在有限的时间内成功进入。 #### 三、信号量(Semaphore) 信号量是一种用于控制多个线程对共享资源访问的同步原语。它是一个整型变量,可以用来实现对...

    Sleep和Wait的区别.pdf

    ### Sleep与Wait的区别详解 #### 一、基本概念 在多线程编程中,`sleep`和`wait`是两个非常重要的方法,用于控制线程的执行和协调多个线程之间的交互。理解这两个方法的不同之处对于正确实现多线程程序至关重要。 ...

Global site tag (gtag.js) - Google Analytics