进程创建,父子进程,进程回收,进程结束

(一)进程的创建-fork
头文件 #include <unistd.h>
pid_t fork(void);

a)用来创建一个新的进程,调用成功后,将存在两个进程,每个进程都从fork()的返回处继续执行。两个进程执行相同的程序文本段,但各自拥有不同的栈段、数据段和堆段,因为子进程对其父进程的堆段、栈段以及数据段进行了拷贝。

b)fork() 调用成功后,在父进程中返回 子进程的 PID,在子进程中返回 0 。如果调用失败,在父进程中返回 -1,不创建进程。

c)fork() 调用成功创建子进程后,究竟是父进程先于子进程执行,还是子进程先于父进程执行,这取决于内核的调度。

注:
(1)将子进程ID(pid)返回给父进程的理由是:因为一个进程的子进程可以多个,并且没有任何一个函数可以使一个进程获得其所有子进程的进程ID。
(2)fork() 使子进程返回 0 的理由是:一个进程只会有一个父进程,所以子进程总是可以通过 getppid() 以获得其父进程的进程ID。

应用:

1 #include <stdio.h>
2 #include <unistd.h>
3 int main(int argc, const char *argv[])
4 {
5 pid_t pid;
6
7 pid = fork();
8 if(pid < 0)
9 {
10 perror(“fork fail”);
11 return -1;
12 }
13 else if(pid == 0) //子进程
14 {
15 printf(“this is the child\n”);
16 while(1)
17 {
18 sleep(1); //休眠1s
19 }
20 }
21 else //父进程
22 {
23 printf(“this is the father\n”);
24 while(1)
25 {
26 sleep(1);
27 }
28 }
29 return 0;
30 }
注:或者把父子进程的 写一遍在return之前;防止对cpu的过度占用
while(1)
25 {
26 sleep(1);
27 }

(二)父子进程
子进程继承了父进程的所有内容(相当于拷贝),父子进程都有相互独立的运行空间,互不影响。
但是父子进程运行结束的先后顺序,互相影响

(1)孤儿进程
a)父进程先结束,子进程变成孤儿进程被init进程收养
b)子进程变成后台进程

(2)僵尸进程
子进程先结束,父进程 没有对 子进程 进行(pcb)资源回收,此时子进程变为僵尸进程

(三)进程的回收 - wait/waitpid
3.1 wait
头文件: #include <sys/types.h>
#include <sys/wait.h>
函数:
pid_t wait(int *status);
进程一旦调用了wait函数,就立即阻塞标记,用wait自动分析是否当前的进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的消息,并回收子进程的资源;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个子进程出现为止。
wait会暂时停止当前的进程继续执行,直到有信号来到或者子进程结束。如果在调用wait时子进程已经结束,则wait会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回。而子进程的进程ID也会一块返回。如果不需要状态值,则将参数status设置成NULL。

(1)status是结构体的一个成员,指定保存子进程的返回值和结束方式的地址。
status = NULL:直接释放子进程,不接受返回值。
wait(&status)接收exit(status)传过来的参数,还需要进行别的操作,wait里面的status并不只是exit传递过来的参数。

(2)wait/waitpid 函数必须放在子进程结束后,父进程可以执行到的地方。
(3)获取子进程状态的几个宏:

WIFEXITED(status) 判断子进程是否正常结束

WEXITSTATUS(status) 获取子进程返回值

WIFSIGNALED(status) 判断子进程是否被信号结束

WTERMSIG(status) 获取结束子进程的信号类型

3.2 pid_t waitpid(pid_t pid, int *status, int options);
参数: 返回值和第二个参数和wait一样。

 第一个参数:pid 表示指定回收的子进程号,如果回收任意一个子进程则参数写-1。

 第三个参数:阻塞和非阻塞两个模式
 			WNOHANG :非阻塞
 			     			  0:阻塞
			**waitpid(-1, &status,0 );//等价于wait(&status);**

(四)进程结束 - exit/_exit
exit()函数属于系统调用,表示进程的结束,取值范围是 0-255。
0 EXIT_SUCCESS 正常退出
1 EXIT_FAILURE 异常退出

		 #include <stdlib.h>
		 void   exit(int status);	 	//  exit会刷新缓冲区
		 
		 #include <unistd.h>
		 void _exit(int status);		// _exit不会刷新缓冲区		

(1)结束当前进程返回参数status传出退出时的状态值,传参给进程回收函数 wait(&status) ;
(2)子函数中有exit(0)是将整个程序退出, 即无论exit(0)在程序的什么位置,都是使其所在的进程结束,子函数里面的return 0是不调用exit()函数的,其作用之一就是跳转到主函数调用的位置。

发布了13 篇原创文章 · 获赞 0 · 访问量 135

猜你喜欢

转载自blog.csdn.net/m0_46170433/article/details/104820021