进程控制课件讲解-赖炜

上传人:小** 文档编号:88220230 上传时间:2019-04-21 格式:PPT 页数:36 大小:219.51KB
返回 下载 相关 举报
进程控制课件讲解-赖炜_第1页
第1页 / 共36页
进程控制课件讲解-赖炜_第2页
第2页 / 共36页
进程控制课件讲解-赖炜_第3页
第3页 / 共36页
进程控制课件讲解-赖炜_第4页
第4页 / 共36页
进程控制课件讲解-赖炜_第5页
第5页 / 共36页
点击查看更多>>
资源描述

《进程控制课件讲解-赖炜》由会员分享,可在线阅读,更多相关《进程控制课件讲解-赖炜(36页珍藏版)》请在金锄头文库上搜索。

1、进程控制,什么是进程,进程是一个程序的一次执行的过程,同时也是资源分配的最小单元。 程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念。 进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和消亡的整个过程,是程序执行和资源管理的最小单位。,后台进程,用户在Shell提示符处键入命令,执行一个程序的时候,它将启动一个进程。此后该进程接管终端,Shell中不能再有其它命令,直到进程执行完毕,才终端返回Shell并显示用户提示符。这种进程就是前台进程。 如果用户在输入Shell命令时,在命令串后面加入“&”,Shell将不等待进程执行完毕就直接返回,于是就可以同时运行

2、进程和执行Shell操作。这样的进程就是后台进程,后台进程并不接管终端,因此必须是非交互式的。,守护进程,守护进程是与终端无关,常驻后台执行的特殊进程。Linux中最著名的两个守护进程是: sysproc进程。Linux的第一个进程,标识号为0。它能合理地高度系统中运行的进程,负责将进程从硬盘交换区调入内存(换入),或者将进程从内存中调到硬盘交换区(换出)。 init进程。系统初始化进程,标识号为1,是除sysproc外所有进程的祖先。,进程状态,睡眠,调度,唤醒,系统调用 、中断,返回,进程标识,Linux系统中每个进程都有一个唯一的标识号,操作系统采用一个非负整数标识每个进程。 进程启动时

3、,系统为进程分配标识号(进程ID);进程中止后,标识号可以重新使用。但任意时刻,一个标识号只对应一个进程。 函数getpid当前进程ID;函数getppid返回父进程ID,获取进程ID,#include #include #include int main() /*获得当前进程的进程ID和其父进程ID*/ printf(“The PID of this process is %dn“, getpid(); printf(“The PPID of this process is %dn“, getppid(); ,启动进程,手工启动,由用户输入命令直接启动进程。 前台启动是手工启动一个进程的最常

4、用方式。一般地,当用户键入一个命令如“ls -l”时,就已经启动了一个进程,并且是一个前台的进程。 若进程非常耗时,且用户也不急着需要结果,可使用后台启动。后台启动是在命令后加“&”。 调度启动,系统根据用户的设置自行启动进程。 系统需要进行一些比较费时而且占用资源的维护工作,并且这些工作适合在深夜无人值守的时候进行,这时用户就可以事先进行调度安排,指定任务运行的时间或者场合,到时候系统就会自动完成这一切工作。 使用调度启动进程有几个常用的命令,如at命令在指定时刻执行相关进程,cron命令可以自动周期性地执行相关进程,fork函数,在Linux中创建一个子进程的惟一方法是使用fork()函数

5、。 fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。 使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等。,fork函数,和以往遇到的函数有一些区别,fork函数看起来执行一次却返回两个值。,创建进程,#include #include #include #include int main(void) pid_t resu

6、lt; int count=0; result = fork(); /通过result的值来判断fork()函数的返回情况,首先进行出错处理 if(result = -1) printf(“Fork errorn“); else if (result = 0) /返回值为0代表子进程 printf(“Im child process!nMy PID is %dn“, getpid(); else /返回值大于0代表父进程 printf(“Im father process!nMy PID is %dn“, getpid(); count+; printf(“the count is:%dn“,

7、count); return result; ,fork函数,fork在英文中是叉子,分叉的意思,在函数fork中,取后面的意思。很形象的表示程序从这里分叉,fork函数创建了子进程。 在父进程中执行fork()函数时,父进程会复制出一个子进程,而且父子进程的代码从fork()函数的返回开始分别在两个地址空间中同时运行(其实是cpu分时处理)。 两个进程分别获得其所属fork()的返回值,其中在父进程中的返回值是子进程的进程号,而在子进程中返回0。因此,可以通过返回值来判定该进程是父进程还是子进程。,说明,fork()函数使用一次就创建一个进程,所以若把fork()函数放在了if else判断

8、语句中则要小心,不能多次使用fork()函数。 由于fork()完整地复制了父进程的整个地址空间,因此执行速度较慢。为了加快fork()的执行速度,有些UNIX系统设计者创建了vfork()。vfork()也能创建新进程,但它不产生父进程的副本,而是通过允许父子进程可访问相同物理内存从而伪装了对进程地址空间的真实拷贝,当子进程需要改变内存中数据时才复制父进程。这就是著名的“写操作时复制”(copy-on-write)技术。 现在很多嵌入式Linux系统的fork()函数调用都采用vfork()函数的实现方式。,思考,#include #include #include #include int

9、 main(void) int i=0; printf(“i son/pa ppid pid fpidn“); for(i=0;i2;i+) pid_t fpid=fork(); if(fpid=0) printf(“%d child %4d %4d %4dn“,i,getppid(),getpid(),fpid); else printf(“%d parent %4d %4d %4dn“,i,getppid(),getpid(),fpid); return 0; ,执行程序,Linux系统提供了exec函数族,用于一个在进程中启动另一个程序执行。 exec函数族可以根据指定的文件名或目录名找

10、到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。exec后面的语句将不执行,系统跳到新进程的main()开始执行。 在执行完之后,原调用进程的内容除了进程号外,其他全部被新的进程替换了。 这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行的脚本文件。 实际上,在Linux中并没有exec()函数,而是有6个以exec开头的函数,它们之间语法有细微差别,exec函数族,环境变量,exec函数族可以默认系统的环境变量,也可以传入指定的环境变量。 上列中,以“e”(environment)结尾的两个函数execle()和execve()就可以在envp中指定当前进程所使

11、用的环境变量。 事实上,这6个函数中真正的系统调用只有execve(),其他5个都是库函数,它们最终都会调用execve()这个系统调用。,执行程序,#include #include #include int main() if (fork() = 0) /*调用execlp()函数,这里相当于调用了“ps -ef“命令*/ if (ret = execlp(“ps“, “ps“, “-ef“, NULL) 0) printf(“Execlp errorn“); ,进程休眠,函数sleep使进程进入休眠状态: 此函数使调用进程被挂起,直到满足以下条件之一: 已经过了seconds所指定的墙上

12、时钟时间 调用进程捕捉到一个信号并从信号处理程序返回,终止进程,程序执行到exit()或_exit()时,进程会无条件地停止剩下的所有操作,清除包括PCB在内的各种数据结构,并终止本进程的运行。,exit(),_exit(),两种退出函数区别,_exit()函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构;exit()函数则在调用exit系统之前要检查文件的打开情况,把文件缓冲区中的内容写回文件。 由于在Linux的标准函数库中,有一种被称作“缓冲I/O(buffered I/O)”操作,其特征是对应每一个打开的文件,在内存中都有一片缓冲区。执行读写时仅操

13、作缓冲区,等满足了一定的条件(如达到一定数量或遇到特定字符等),再将缓冲区中的内容一次性写入文件。 这种技术大大增加了文件读写的速度,但也为编程带来了一些麻烦。比如有些数据,可能因为没有满足条件,只是被保存在缓冲区内,这时用_exit()函数直接将进程关闭,缓冲区中的数据就会丢失。因此,若想保证数据的完整性,就一定要使用exit()函数。,exit函数,终止进程,#include #include int main() printf(“Using _exit.n“); printf(“This is the content in buffer”); / 加上回车符之后结果又如何 _exit(0

14、); / 若换成exit(0),结果又如何? ,僵尸进程,在一个进程调用了exit()之后,该进程并不会立刻完全消失,而是留下一个称为僵尸进程(Zombie)的数据结构。 僵尸进程是一种非常特殊的进程,它已经放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。,进程同步,系统调用wait可以实现父子进程之间的同步。 wait()函数是用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。如果该父进程没有子进程或者他的子进程已经

15、结束,则wait()就会立即返回。 waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的wait()功能,也能支持作业控制。实际上wait()函数只是waitpid()函数的一个特例,在Linux内部实现wait()函数时直接调用的就是waitpid()函数。,wait函数,waitpid函数,守护进程,守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。 守护进程常常在系统引导载入时启动,在系统关闭时终止。

16、在Linux中,系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,当控制终端被关闭时,相应的进程都会自动关闭。 但是守护进程却能够突破这种限制,它从被执行开始运转,直到整个系统关闭时才会退出。如果想让某个进程不因为用户、终端或者其他的变化而受到影响,那么就必须把这个进程变成一个守护进程。,实现守护进程基本流程,后台运行,由于守护进程是脱离控制终端的,可以通过托管法实现,即创建子进程,父进程退出。 由于父进程已经先于子进程退出,会造成子进程没有父进程,从而变成一个孤儿进程。在Linux中,每当系统发现一个孤儿进程,就会自动由1号进程(也就是init进程)收养它,这样,原先的子进程就会变成init进程的子进程了。 pid = fork(); if (pid 0) exit(0); /*父进程退出*/ ,独立于终端,进程组是一个或多个进程的集合。会话组是一个或多个进程组的集合。通常,一个会话(sess

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 管理学资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号