1、wait和waitpid出现的原因

SIGCHLD

q  当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)

q  子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态。

父进程查询子进程的退出状态可以用wait/waitpid函数

2、wait和waitpid函数用法

Wait

q  头文件<sys/types.h>和<sys/wait.h>

q  函数功能:当我们用fork启动一个进程时,子进程就有了自己的生命,并将独立地运行。有时,我们需要知道某个子进程是否已经结束了,我们可以通过wait安排父进程在子进程结束之后。

q  函数原型

q  pid_t wait(int *status)

q  函数参数

q  status:该参数可以获得你等待子进程的信息

q  返回值:

q  成功等待子进程函数返回,返回值是等待子进程的ID

q  wait系统调用会使父进程暂停执行,直到它的一个子进程结束为止。

q  返回的是子进程的PID,它通常是结束的子进程

q  状态信息允许父进程判定子进程的退出状态,即从子进程的main函数返回的值或子进程中exit语句的退出码。

q  如果status不是一个空指针,状态信息将被写入它指向的位置

Wait获取status后检测处理

宏定义     描述

WIFEXITED(status)  如果子进程正常结束,返回一个非零值

WEXITSTATUS(status)      如果WIFEXITED非零,返回子进程退出码

WIFSIGNALED(status)     子进程因为捕获信号而终止,返回非零值

WTERMSIG(status) 如果WIFSIGNALED非零,返回信号代码

WIFSTOPPED(status)       如果子进程被暂停,返回一个非零值

WSTOPSIG(status)   如果WIFSTOPPED非零,返回一个信号代码

Waitpid

q函数功能:用来等待某个特定进程的结束

q函数原型:

pid_t waitpid(pid_t pid, int *status,int options)

q参数:

q  status:如果不是空,会把状态信息写到它指向的位置

qoptions:允许改变waitpid的行为,最有用的一个选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起

q  返回值:如果成功返回等待子进程的ID,失败返回-1

对于waitpid的p I d参数的解释与其值有关:

pid == -1 等待任一子进程。于是在这一功能方面waitpid与wait等效。

pid > 0 等待其进程I D与p I d相等的子进程。

pid == 0 等待其组I D等于调用进程的组I D的任一子进程。换句话说是与调用者进程同在一个组的进程。

pid < -1 等待其组I D等于p I d的绝对值的任一子进程。

3、wait pk waitpid

Wait和waitpid区别和联系

q  在一个子进程终止前, wait 使其调用者阻塞,而waitpid 有一选择项,可使调用者不阻塞。

q  waitpid并不等待第一个终止的子进程—它有若干个选择项,可以控制它所等待的特定进程。

q  实际上wait函数是waitpid函数的一个特例。

僵尸进程

q  当一个子进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行或者父进程调用了wait才告终止。

进程表中代表子进程的数据项是不会立刻释放的,虽然不再活跃了,可子进程还停留在系统里,因为它的退出码还需要保存起来以备父进程中后续的wait调用使用。它将称为一个“僵进程”

如何避免僵尸进程

q  调用wait或者waitpid函数查询子进程退出状态,此方法父进程会被挂起。

q  如果不想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略SIGCHLD信号,该信号是子进程退出的时候向父进程发送的。

#include <sys/types.h>
#include <unistd.h>
#include "errno.h" #include "stdio.h"
#include "stdlib.h"
#include "string.h" #include <sys/types.h>
#include <sys/wait.h> void LoopFunc(int num)
{
printf("LoopFunc() %d....\n", num);
} int main(void )
{ int i , j = ; printf("hello...\n"); int procNum = ;
int loopNum = ;
printf("\n请输入要运行的进程数");
scanf("%d", &procNum); printf("\n请输入每个进程运行圈数");
scanf("%d", &loopNum); pid_t pid;
printf("befor fork pid:%d\n", getpid()); //fork 子进程 for (i=; i<procNum; i++)
{ pid = fork();
if (pid == -)
{
//On failure, a -1 will be retur
//errno
perror("fork err");
return ;
} if (pid == )
{
for (j=; j<loopNum; j++)
{
LoopFunc(j);
}
exit(); //让子进程跑圈 子进程不参与下一次的fork }
if (pid > ) //大于0是父进程
{
; }
} //退出
printf("after fork \n");
int mypid ; while( (mypid = waitpid(-, NULL, WNOHANG)) > )
{
printf("孩子死掉:%d\n ", mypid);
}return ; }
 
 
 
 
 

[学习笔记]父进程wait和waitpid的更多相关文章

  1. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  2. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  3. Linux学习笔记(六) 进程管理

    1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...

  4. Linux C语言编程学习笔记 (1)进程控制入门

    想进行Linux系统开发已经很久了,一直没有付诸实践.今日终于开始学习Linux下的C语言编程,研究一天,终于大概弄明白了Linux系统进程管理的一些基本概念和编程方法,总结下来以方便大家学习和自己实 ...

  5. RHCA学习笔记:RH442-Unit8进程与调度

      UNIT 8  Processes and the Scheduler 进程与调度 学习目标 A. CPU cache 与Service time之间的关系 B. 分析应用程序使用CPU cach ...

  6. linux学习笔记之进程

    一.基础知识 1:进程. 1,进程ID: 非负整数,具有唯一性. 1)ID=0的进程:调度进程/交换进程.内核的一部分.不执行任何磁盘上的程序. 2)ID=1的进程:init进程. 1-自举结束时,由 ...

  7. Linux System Programming 学习笔记(五) 进程管理

    1. 进程是unix系统中两个最重要的基础抽象之一(另一个是文件) A process is a running program A thread is the unit of activity in ...

  8. APUE 学习笔记(六) 进程控制

    1. fork 创建新进程 fork创建的新进程称为子进程,fork函数调用一次,返回两次. 两次返回的唯一区别就是子进程的返回值是0,而父进程的返回值是新子进程的进程ID 在fork之后是父进程先执 ...

  9. python 学习笔记八 进程和线程 (进阶篇)

    什么是线程(thread)? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执 ...

随机推荐

  1. Python 函数之递归

    递归函数定义 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 我们来计算阶乘 n! = 1 x 2 x 3 x ... x n ,用函数 fact(n) 表示 f ...

  2. Python collections系列之双向队列

    双向队列(deque) 一个线程安全的双向队列 1.创建一个双向队列 import collections d = collections.deque() d.append(') d.appendle ...

  3. 使用navicat进行数据表迁移

    使用navicat进行数据和表迁移只需要复制,粘贴就可以实现.

  4. PHP 实现了一种代码复用的方法,称为 trait

    自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.Trait 为了减少单继承语言的限制,使开发人员能 ...

  5. nginx提示Error: Too many open files的解决办法

    nginx提示:Too many open files这种错误问题的原因是因为linux文件系统最大可打开文件数为1024,而你的nginx中的error.log出现大量的Too many open ...

  6. Nginx报错 connect() failed (111: Connection refused) while connecting to upstream 的解决方法

    今天访问公司的网站突然报错,抛出一些英文,提示看一下Nginx的error.log日志: cd  /usr/local/nginx/logs/  看到了error.log ,下一步 tail -n 2 ...

  7. 反射ORM 三层(for sql server/mysql)

    sql server and oracle 不同之处只在于: 1·参数@和: 2·自增和序列 RPROM.cs //(写错愕,应该是RPORM) RPROM.Insert(p1); //需求:DBS中 ...

  8. [转] CentOS系统目录学习

    最近初学Linux 对linux的目录产生了很多疑问,看到这篇文章,让我顿时对目录有了一个清晰的认识!推荐给大家! ------------------------------------------ ...

  9. MongoTemplate聚合操作

    Aggregation简单来说,就是提供数据统计.分析.分类的方法,这与mapreduce有异曲同工之处,只不过mongodb做了更多的封装与优化,让数据操作更加便捷和易用.Aggregation操作 ...

  10. 修改rbd指定位置的数据

    标签(空格分隔): ceph,ceph实验 --- 我们通过查看index为0x01的小4M文件,得知了file2.txt这个文件内容在这个4M内保存的位置为0x9000,因为0x01前面还有一个4M ...