您的位置:首页 > 大数据 > 人工智能

wait和waitpid的区别

2013-08-11 10:50 176 查看
        1、一个进程正常结束:
(1)return
(2)exit
(3)_exit和_Exit
(4)进程的最后一个线程使用return
(5)进程的最后一个线程使用phread_exit
2、一个异常进程结束:
(1)abort
(2)signal
(3)cancellation request ,最后一个线程被取消
3、当一个进程结束时,它的父进程需要知道它是如何结束的,于是需要得到子进程的termination status,parent process可以通过wait 和waitpid两个函数得到。
(1)当parent process 先于child process结束
init process(ID is 1)接手它的child process,kernel搜索所有的进程,看看结束的进程是否是正在运行的进程的父进程,如果是,则将它们的父进程改为init process。
(2)子进程先于父进程结束
kernle保留了所有将要结束的进程的信息,如:process ID,termnation status,a mount of CPU time,这样的话,parent process可以通过wait和waitpid得到termination status。
(3)当一个进程的父进程变成init process时,发生了什么?
无论何时child process结束,init调用wait函数得到termination status。init进程总是可以获得子进程的终止状态。
4、wait和waitpid
      当调用这两个函数时,可能发生三种情况:
(1)block——如果它的子进程全部都在运行。

        (2)立即返回child process的termination status——如果有子进程终止。
(3)返回error——如果没有子进程。
# include <sys/wait.h>
pid_t wait (int *statloc);
pid_t waitpid (pid_t pid, int *statloc, int options);
      两者的区别
(1)wait可能阻塞caller直到一个子进程终止,而waitpid则可以通过选项不会阻塞。
(2)waitpid并不等待第一个终止的进程,它有选项可以控制它所等待的进程。
(3)对于得到的ternimation status我们可以通过四个macos来区分:
    1    WIFEXITED(status) //正常终止
    2    WIFSIGNALED(status) //异常终止,获取异常信号
    3    WIFSTOPPED(status)
    4    WIFCONTINUED(status)
(4)waitpid根据pid的不同来获取不同的进程termination status。
    1    waitpid可以wait某个特定的process,而wait则是任何的terminated child
    2    waitpid是nonblockling //可以使用选项控制为非阻塞
    3    waitpid支持WUNTRACED和WCONTINUED //waitpid支持任务控制
备注:当子进程结束的时候,父进程会收到SIGCHLD通知 2.进程可以调用wait/waitpid等待此Signal.为了减少僵尸进程的产生,我们可以采用waitpid而减少wait的使用,虽然僵尸进程可以由init回收
今天看了unix网络编程中的关于wait和waitpid的区别,它采用的验证例子是客户/服务器的连接问题

1.当子进程结束的时候,父进程会收到SIGCHLD通知
2.进程可以调用wait/waitpid等待此Signal
    a.当所有子进程都在执行的时候,会block
    b.当某个子进程中止,成为zombie的时候,立刻返回
    c.如果没有任何子进程,则返回错误
以前曾经学过这两函数的使用,但是没有什么例子可以验证,今天巧遇网络编程,就把这两个函数重新温习一下:
pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
两个函数的不同在于wait会令调用者阻塞直至某个子进程终止而waitpid则可以通过设置一个选项来设置为非阻塞,另外waitpid并不是等待第一个结束的进程而是等待参数中pid指定的进程。

       
两个函数中的变量statloc是一个指向int型数据的指针。如果此变量不是NULL,则结束的进程的termination status会被保存在statiloc所指向的内存的区域;如果我们不关心termination status,则可以把statloc置为NULL。

waitpid函数:
如果一个进程有若干个子进程, 那么只要有一个子进程返回, wait就返回. 如果要等待一个指定的子进程, 有两种方法. 第一个种, 早期的UNIX必须调用wait, 然后把返回的pid和期望pid做比较, 如果不是期望的, 把该pid保存起来, 继续调用wait, 直到进程终止. 第二种是使用waitpid.
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *statloc, int options);
函数返回: 若成功则为进程ID, 若出错则为-1.
参数说明:
pid:
pid == -1 等待任一子进程. 这个时候waitpid与wait等效.

        pid > 0     等待其ID与pid相等的子进程.

        pid == 0 等待其组ID与调用进程的组ID的任一子进程.

        pid < -1    等待其组ID等于pid绝对值的任一子进程.

对于waitpid函数, 如果指定的进程或进程组不存在, 或者调用进程没有子进程都会出错.
options:
这个一参数可以让我们进一步控制waitpid的操作, 此参数或者是0, 或者是下列的逐位或常数之一:
WNOHANG: 若由pid指定的子进程并不立即可用, 则waitpid不阻塞, 此时其返回值为0.
WUNTRACED: 若某实现支持作业控制, 则由pid指定的任一子进程状态已暂停, 且其状态自暂停以来还未报告过, 则返回其状态. WIFSTOPPED宏确定返回值是否对应于一个暂停子进程.
    下面我们来具体看看wait和waitpid在网络编程中使用的区别:


void sig_chld(int signo)






{


   pid_t pid;


   int stat;


   pid = wait(&stat);


   printf("child %d terminated \n",pid);


   return;


}




void sig_chld(int signo)






{


   pid_t pid;


   int stat;


   while((pid = waitpid(-1,&stat,WNOHANG))>0)


   printf("child %d terminated \n",pid);


   return;


}
上面是两段不同的信号处理函数,它们的结果可能相差很多的,下面我们就来看看有哪些区别:
首先我们看看用wait函数产生的效果:
1、下面的输出是在启动客户端和服务器端程序后的ps输出
备注:在客户端程序中,我们连续产生5个服务器连接进程,所以一共6个waitsrv进程



2、下面是在客户端输入ctrl+d后的服务器端输出和ps查询后的结果





我们从上面可以看出利用wait的一个致命的缺点就是只能回收一个子进程,其他的进程由于没有得到回收而变成僵尸进程
下面我们来看看利用waitpid函数的输出结果:
   1、启动服务器端和客户端后的ps输出



2、在客户端输入ctrl+d后的服务器端输出和ps的结果





   我们可以发现所有服务器的子进程在接受到客户端输入的EOF后,都被回收了!

   由此,我们可以发现,为了减少僵尸进程的产生,我们可以采用waitpid而减少wait的使用,虽然僵尸进程可以由init回收
   以上的例子程序是采用的unix网络编程中的例子,在此代码就不再详细列出了!
 
 
 
 
 
 
 
 
 
 sleep和wait的区别

1、这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

2、最主要sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

Thread.Sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

3、使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

   synchronized(x){

      x.notify()

     //或者wait()

   }

4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: