进程控制(二)

5 wait和waitpid函数

  当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。

5.1调用wait或waitpid的进程可能会:

    阻塞(如果其子进程都还在运行)

    带子进程的终止状态立即返回

    出错立即返回

5.2wait和waitpid的区别: 

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

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

代码示例:

#include "ourhdr.h"
#include <sys/wait.h>

void pr_exit(int status)
{
	if (WIFEXITED(status))
		printf("normal termination, exit status = %d\n",
				WEXITSTATUS(status));
	else if (WIFSIGNALED(status))
		printf("abnormal termination, signal number = %d%s\n",
				WTERMSIG(status),
#ifdef	WCOREDUMP
				WCOREDUMP(status) ? " (core file generated)" : "");
#else
				"");
#endif
	else if (WIFSTOPPED(status))
		printf("child stopped, signal number = %d\n",
				WSTOPSIG(status));
}

int main(void)
{
	pid_t	pid;
	int		status;

	if ((pid = fork()) < 0)
		err_sys("fork error");
	else if (pid == 0)				/* child */
		exit(7);

	if (wait(&status) != pid)		/* wait for child */
		err_sys("wait error");
	pr_exit(status);				/* and print its status */

	if ((pid = fork()) < 0)
		err_sys("fork error");
	else if (pid == 0)				/* child */
		abort();					/* generates SIGABRT */

	if (wait(&status) != pid)		/* wait for child */
		err_sys("wait error");
	pr_exit(status);				/* and print its status */

	if ((pid = fork()) < 0)
		err_sys("fork error");
	else if (pid == 0)				/* child */
		status /= 0;				/* divide by 0 generates SIGFPE */

	if (wait(&status) != pid)		/* wait for child */
		err_sys("wait error");
	pr_exit(status);				/* and print its status */

	exit(0);
}

  打印结果:

[[email protected] fork]# gcc wait.c
wait.c: In function ‘main’:
wait.c:48: warning: division by zero

[[email protected] fork]# ./a.out
normal termination, exit status = 7
abnormal termination, signal number = 6
abnormal termination, signal number = 8

 5.3如果一个进程要 f o r k一个子进程,但不要求它等待子进程终止,也不希望子进程处于僵死状态直到父进程终止,实现这一要求的诀窍是调用 f o r k两次。

代码示例:

#include "ourhdr.h"
#include <sys/wait.h>
#include <sys/types.h>

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);
}

  

打印结果:

[[email protected] fork]# ./a.out
[[email protected] fork]# second child, parent pid = 1

  

6 wait3 和wait4函数

时间: 2024-10-05 05:06:59

进程控制(二)的相关文章

进程控制(二)与linux下的自有服务

一.进程动态信息查看top 第一部分 统计信息 [[email protected] ~]# top top - 19:22:52 up 1:32, 2 users, load average: 0.00, 0.00, 0.00 Tasks: 106 total, 1 running, 105 sleeping, 0 stopped, 0 zombie Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.6%id, 0.0%wa, 0.0%hi, 0.2%si, 0.0%st

进程控制(二)---进程标识符

Linux操作系统中为了区分每一个进程,为每个进程分配一个唯一的进程号,也称为进程ID.进程 ID 是保存在进程的 PCB 中,属于进程的内核资源. 每个进程的进程 ID 虽然是唯一的,但是进程 ID 是可以重用的,当一个进程被终止时,其所有的资源将会被释放,也包括进程 ID.当系统再次创建一个新的进程时,可以为其分配已经被释放的进程 ID .由于操作系统采用延迟重用算法,所以为刚创建的进程分配的进程 ID通常不会是刚被释放的进程 ID . 操作系统中有些进程的进程 ID 是固定的,比如 调度进

linux c编程:进程控制(二)_竞争条件

前面介绍了父子进程,如果当多个进程企图对共享数据进行处理.而最后的结果又取决于进程运行的顺序时,就认为发生了竞争关系.通过下面的例子来看下 在这里标准输出被设置为不带缓冲的,于是父子进程每输出一个字符就要进行一次write调用.这样做的目的是尽可能多次地在两个进程之间进行切换,以便演示竞争条件. static void charatatime(char *str){ char *ptr; int c; setbuf(stdout,NULL); for(ptr=str;(c=*ptr++)!='\

Linux进程控制(二)

1. 进程的创建 Linux下有四类创建子进程的函数:system(),fork(),exec*(),popen() 1.1. system函数 原型: #include <stdlib.h> int system(const char *string); system函数通过调用shell程序/bin/sh –c来执行string所指定的命令,该函数在内部是通过调用execve("/bin/sh",..)函数来实现的.通过system创建子进程后,原进程和子进程各自运行,

操作系统(二)进程控制

1 进程状态 1. 进程的三种基本状态 1) 就绪(Ready)状态 2) 执行状态3) 阻塞状态(请求I/O,申请缓冲空间等) 2. 挂起状态 引入挂起状态的原因有: (1)终端用户的请求.当终端用户在自己的程序运行期间发现有可疑问题时,希望暂时使自己的程序静止下来.亦即,使正在执行的进程暂停执行;若此时用户进程正处于就绪状态而未执行,则该进程暂不接受调度,以便用户研究其执行情况或对程序进行修改.我们把这种静止状态称为挂起状态. (2)父进程请求.有时父进程希望挂起自己的某个子进程,以便考查和

Linux进程控制编程

一.获取ID #include<sys/types.h> #include<unistd.h> pid_t getpid(void)    获取本进程ID pid_t getppid(void)  获取父进程ID 父进程:现有进程中,创建新的进程. 例:getpid.c #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() { printf("PID=%d\

APUE(8)---进程控制(1)

一.进程标识 每个进程都有一个非负整型标识的唯一进程ID.因为进程ID标识符总是唯一的,常将其用做其他标识符的一部分以保证其唯一性.进程ID虽然是唯一的, 但是却是可以复用的.ID为0的进程通常是调度进程,常常被称为交换进程(swapper).该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被称为系统进程.进程ID为1通常是init进程,在自举过程结束时由内核调用.此进程负责在自举内核后启动一个UNIX系统,init通常读取与系统有关的初始化文件,并将系统引导一个状态.init进程绝不会

进程控制在进程管理中的作用

 进程控制是进程管理中最基本的功能.它用于创建一个新进程,终止一个已完成的进程,或者去终止一个因出现某事件而使其无法运行下去的进程,还可负责进程运行中的状态转换. 一.创建进程 1.引起创建进程的事件 在多道程序环境中,只有(作为)进程(时)才能在系统中运行.因此,为使程序能运行,就必须为它创建进程.导致一个进程去创建另一个进程的典型事件,可以有以下四类: 1) 用户登录 在分时系统中,用户在终端键入登录命令后,如果是合法用户,系统将为该终端建立一个进程,并把它插入到就绪队列中. 2)作业调

Linux进程控制知识总结

目录 一:进程标识符(ID) 二:进程操作 2.1创建一个进程 2.2 fork函数出错情况 2.3创建一个共享空间的子进程 2.4退出程序 2.5设置进程所有者 三:执行程序 3.1 exec函数 3.2 执行解释器文件 3.3在程序中执行Shell命令 四:关系操作符 4.1等待进程退出 4.2 等待指定的进程 进程控制 -- 一步 一:进程标识符(ID) 进程ID是用来标识进程的编号,就像身份证一样.不同的进程有不同的ID,可以通过ID来查询进程.进程标识符的类型是pit_t,其本质是一个

Unix高级编程之进程控制

进程控制 ps auxps axjps axfps axm 一.进程标识符 pid_t ---->long int 进程的独一无二的标识 0 调用进程(内核) 1 init进程(用户态所有进程的祖先进程) getpid(2); getppid(2); 进程的状态 S 可中断的睡眠态 R 运行态 D 不可中断的睡眠态 T 停止态 X 终止态 Z 僵尸态进程优先级 s 会话组长 l 多线程 < 高优先级 N 低优先级 + 在前台进程组 二.fork(2)父子进程之间的不同: <1>pi