进程控制编程

虚拟内存

Linux采用虚拟内存管理技术,虚拟地址空间0~4G,用户空间(3G),内核空间(1G),访问内核空间的方式是通过系统调用。Linux内核由系统内所有进程共享。每个进程都有独立的进程地址空间,大小为3G。

作用:使用虚拟地址很好的保护内核空间不被用户空间破坏

进程的状态转换

在这里插入图片描述

fork()和vfork()函数

fork()函数通过系统调用创建一个与原来几乎完全相同的进程,俩个进程可以做完全相同的事,如果初始参数不同,俩个进程也可以做不同的事。系统先给新的进程分配存储数据和代码的空间,把原来的进程所有值 复制copy 到新的进程中,只有少数值与原来不同,相当于克隆了一个自己。
***大多数是父进程先运行,少数子进程先运行,由调度进程决定。

vfork()函数父子进程的内存数据share一起用。
***通常vofrk()函数和exec()函数搭配使用
***保证子进程先执行
***当子进程调用exit()或exec()后,父进程往下执行。

**有关进程的命令
查看进程:ps ajx
杀死进程kill -9 pid //给进程发送一个杀死信号

孤儿进程

父进程先结束,子进程变孤儿
解决方法:父进程sleep()等待一会。

#include <stdio.h>
#include <stdlib.h>

int main(){

	printf("start....\n");
	pid_t pid = fork();
	if(pid == -1){
		printf("fork error!\n");
		exit(1);
	}
	if(pid == 0){
		printf("child pid:%d,ppid:%d\n",getpid(),getppid());
	}else if(pid > 0){
		printf("parent pid:%d,ppid:%d\n",getpid(),getppid());
	}

	printf("end...\n");
	return 0;
}

执行结果:
start…
parent pid:17587,ppid:11964
end…
child pid:17588,ppid:1
end…

注:父进程先于子进程退出
子进程没有父进程获取自身的退出状态,也就变成了孤儿进程
但是,所有的孤儿进程都被一号(init)进程所收养,由一号进程作为所有孤儿进程的父进程,负责孤儿进程的资源释放。
*非孤儿进程:子进程的ppid为父进程的pid。

wait和waitpid函数

wait()函数用于使父进程(也就是调用wait()的进程)阻塞,知道一个子进程结束或者收到一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()函数就会立即返回。
waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程(它可以指定需要等待终止的子进程)。
在这里插入图片描述

僵尸进程

概念:
子进程退出了,但是父进程没有用wait或waitpid去获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称为僵死进程。

危害:
如果父进程不调用wait或waitpid的话,那么保留的信息就不会被释放,其进程号就会被一直占用,但是系统所能使用的进程号是有限的,如果大量产生僵死进程,将因没有可用的进程号而导致系统无法产生新的进程,这就是僵尸进程的危害。

解决方法:
1)kill杀死元凶父进程(一般不用)

严格的说,僵尸进程并不是问题的根源,罪魁祸首是产生大量僵死进程的父进程。因此,我们可以直接除掉元凶,通过kill发送SIGTERM或者SIGKILL信号。元凶死后,僵尸进程进程变成孤儿进程,由init充当父进程,并回收资源。

或者运行:kill -9 父进程的pid值、
2)父进程用wait或waitpid去回收资源(方案不好)

父进程通过wait或waitpid等函数去等待子进程结束,但是不好,会导致父进程一直等待被挂起,相当于一个进程在干活,没有起到多进程的作用。

3)通过信号机制,在处理函数中调用wait,回收资源

通过信号机制,子进程退出时向父进程发送SIGCHLD信号,父进程调用signal(SIGCHLD,sig_child)去处理SIGCHLD信号,在信号处理函数sig_child()中调用wait进行处理僵尸进程。什么时候得到子进程信号,什么时候进行信号处理,父进程可以继续干其他活,不用去阻塞等待。

2)代码

#include <stdio.h>
#include <stdlib.h>

int main(){

	printf("start....\n");
	pid_t pid,pw;
	pid = fork();
	if(pid == -1){
		printf("fork error!\n");
		exit(1);
	}
	if(pid == 0){
		printf("child process pid:%d\n",getpid());
		sleep(5);
		exit(0);
	}else if(pid > 0){
		pw = wait(NULL);//wait函数参数设置为NULL的时候,就可以销毁这个僵尸进程
		printf("I catch a child process and this pid is%d",pw);
	}

	exit(0);
	return 0;
}

3)代码

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <errno.h>
 4 #include <stdlib.h>
 5 #include <signal.h>
 6 
 7 static void sig_child(int signo);
 8 
 9 int main()
10 {
11     pid_t pid;
12     //创建捕捉子进程退出信号
13     signal(SIGCHLD,sig_child);
14     pid = fork();
15     if (pid < 0)
16     {
17         perror("fork error:");
18         exit(1);
19     }
20     else if (pid == 0)
21     {
22         printf("I am child process,pid id %d.I am exiting.\n",getpid());
23         exit(0);
24     }
25     printf("I am father process.I will sleep two seconds\n");
26     //等待子进程先退出
27     sleep(2);
28     //输出进程信息
29     system("ps -o pid,ppid,state,tty,command");
30     printf("father process is exiting.\n");
31     return 0;
32 }
33 
34 static void sig_child(int signo)
35 {
36      pid_t        pid;
37      int        stat;
38      //处理僵尸进程
39      while ((pid = waitpid(-1, &stat, WNOHANG)) >0)//参考上面的表格,这里是由pid指定的子进程结束标志
40             printf("child %d terminated.\n", pid);
41 }

exit()

1.exit()和wait()分别在子进程和父进程中配合使用。
2.exit()用于结束子进程,并把状态返回给父进程,父进程使用wait(&state)等待子进程结束,子进程结束后,可以通过state获得子进程之前通过exit()返回的状态,但是该状态必须左移8位才和exit()相同。

#include <stdio.h>
#include clude <stdlib.h>

int main(){

	pid_t pid;
	int i = 0;
	int state;

	pid = fork();
	if(pid == -1){
		printf("fork error!\n");
		exit(1);
	}
	if(pid == 0){
		printf("child:i=%d,pid=%d\n",i++,getpid());
		exit(5);
	}else if(pid > 0){
		wait(&state);
		printf("-------------\n");
		printf("child state:%d\n",state);
		printf("parent:i=%d,pid=%d\n",i++,getpid());
	}


	return 0;
}

结果:
child:i=0,pid=19431
//左移8位为5与exit(5)相同。
child state:1280
parent:i=0,pid=19430

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值