您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 咨询培训 > UNIX操作系统实验3
UNIX操作系统实验首都师范大学信息工程学院系统分析与管理实验室12目录1、UNIX安装及基本操作………………………………………2、UNIX编程基础……………………………………….3、UNIX进程实验……………………………………….4、UNIX进程间通信……………………………………..5、UNIX文件系统实验………………………………………..6、UNIX综合实验………………………………………..19223346491实验三UNIX进程实验一、背景知识1、进程的基本概念进程是正在执行的一个程序的实例,通常是由程序,数据集合和进程控制块(ProcessControlBlock简称PCB)三个部分组成。程序部分:描述了进程所要完成的功能;数据集合:包括两个方面的内容,即程序运行时所需要的数据部分和工作区;进程控制块含有进程的描述信息和控制信息,是进程动态特性的集中反映,它是系统对进程施行识别和控制的依据。2、进程和程序的区别程序是静态概念,本身可以作为一种软件资源长期保存;而进程是程序的执行过程,它是动态概念,有一定的生命期,是动态地产生和消亡的。进程是一个能独立运行的单位,能与其他进程并发执行,进程是作为资源申请调度单位存在的,而通常的程序段是不能作为一个独立运行的单位的。程序和进程无一一对应关系。一个程序可以由多个进程共用;另一方面,一个进程在活动中有可顺序地执行若干个程序。进程不能脱离具体程序而虚设,程序规定了相应进程所要完成的动作。3、父进程与子进程子进程是由另外一个进程所产生的进程,产生这个子进程的进程称为父进程。子进程继承某些父进程的环境,但子进程作为几个独立的进程也有它自己的环境。在UNIX系统中,使用系统调用fork创建进程。fork复制的内容包括父进程的数据和堆栈段以及父进程的进程环境。子进程共享父进程的文本段即代码段。父进程和子进程以并行的方式执行同一程序的不同分支。4、UNIX进程种类UNIX系统中将进程分为两大类:系统进程SYS和用户进程系统进程SYS:系统进程与终端无关,不由用户启动,通常也叫做守护进程,是核心专用的特殊程序。进程0:sysproc进程。管理换入与换出的进程,对系统中运行的进程进行合理地调度。将进程从硬盘交换区调入内存的过程称为换入;将进程从内存调到硬盘交换区的过程称为换出。该进程是unix核心创建的第一个进程。进程1:init进程。系统初始化进程,是所有用户进程和非sysproc进程的祖先。2用户进程:用户进程与特定的用户标识和终端相关联。通过在ps命令行指定用户名或终端ID很容易将用户进程和系统进程区分开。例如,要列出除root用户进程之外的其它所有用户进程,执行如下命令:ps–ef|grep–v“^root”死进程:死进程是已经终止,但没有从进程表中清除的进程。可能由下列情况之一产生:一、父进程在子进程终止之前先终止;二、父进程没有等待子进程终止。如果系统存在大量死进程,就会过多占用进程表空间,影响新进程的产生。这时,我们需要重新启动系统以清除死进程。5、查看当前进程ps命令:PS命令可以检查系统中正在运行的进程的状态,可以把系统中全部的活动进程列出来,这些进程既包括在后台运行的,也包括在前台运行的。ps的命令行结构:ps[-edalf][-nname][-tttys][-ppids][-uusers][-ggroups]当ps命令行没有选项时,只显示与控制终端相关进程的基本信息。ps(C)命令一些常用选项定义如下:-f:产生某个进程的一个完整清单;-u:产生属于某个特定用户进程的一个清单;-t:产生与特定终端联系的进程的一个清单;-e:显示进程的完整清单终止进程:kill命令,使用命令kill(C)来终止进程。命令行结构:kill[-signal]PIDsignal是信号,PID是进程号。kill命令向指定的进程发出一个信号signal。在默认的情况下,kill命令向指定进程发出信号15。正常情况下,将杀死那些不捕捉或不忽略这个信号的进程。关于kill命令的两个说明一、高优先级进程除非重新启动系统,否则不能被终止。二、kill–1PID,一些程序使用它作为重读它们的配置文件的信号。三、kill–2PID,功能同按“Delete”键,用来终止一个进程。四、kill–3PID,功能同按“Ctrl;+\”键,比“kill-2”功能强大。通常产生一个包含程序内存转储信息的core文件。五、kill–9PID,在某些特殊的情况下,比如使用kill的普通形式无法杀死的进程,要使用该命令。信号9是不能被捕捉也不能被忽略的。因此,它可以强行终止进程的运行。3二、进程实验fork系统调用:功能:建立子进程返回值:对子进程返回0,对父进程返回子进程号具体描述:新进程由父进程(老进程)的地址空间(包括代码、数据、栈、现场、管理信息等)的一个复制构成。vfork系统调用:其功能,调用参数和返回值与fork相同,但它并不将父进程的地址空间完全复制到子进程。exec系统调用:输入参数:新程序名功能:以指定程序覆盖当前进程的程序代码wait系统调用:输入参数:进程号功能:等待指定进程结束典型地,子进程在fork后用exec使新程序覆盖进程空间1、创建进程—fork()在UNIX系统中,用户创建一个新进程的唯一方法就是调用系统调用fork。语法格式:pid=fork();当一个进程调用fork,完成后就出现两个几乎一模一样(除pid不同,具有完全一样的用户级上下文)的进程,我们也由此得到了一个新进程。据说fork的名字就是来源于这个与叉子的形状颇有几分相似的工作流程。在系统启动时由核心内部地创建的进程0是唯一不通过系统调用fork而创建的进程。2、创建进程—“建立进程”图请见图1.3、创建进程—fork()例子/*fork_test.c*/#includesys/types.h#inlcudeunistd.hintmain(){pid_tpid;/*此时仅有一个进程*/pid=fork();/*此时已经有两个进程在同时运行*/4if(pid0)printf(errorinfork!);elseif(pid==0)printf(Iamthechildprocess,myprocessIDis%d,getpid());elseprintf(Iamtheparentprocess,myprocessIDis%d,getpid());}图1进程创建流程编译并运行:申请PCB表空间申请内存空间查找外存程序申请到申请到找到装入栈初始化等准备工作分配其他资源建立PCB表信息、进程状态(就绪态)进程主程序名,进入调度队列等调用调度程序(父子进程都就绪)或:返回父进程(子进程就绪)或:直接将新进程投入运行(即直接建立现场)(父进程就绪)拒绝建立进程或等待无此文件5$gccfork_test.c-ofork_test$./fork_test将结果填入下表。4、创建进程—exec()既然所有新进程都是由fork产生的,而且由fork产生的子进程和父进程几乎完全一样,那岂不是意味着系统中所有的进程都应该一模一样了吗??!exec系统调用!exec()的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Unix下可执行的脚本文件。与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,颇有些神似“三十六计”中的“金蝉脱壳”。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。5、exec与fork结合图2进程创建与独立运行实际上在Unix中,并不存在一个exec()的函数形式,exec指的是一组函数:Thebasicdifferencesareinwhattheytakeasarguments.Theexec(2)callsvaryinwhethertheytakeapathnameorfilenameasthefirstargument(whichspecifiesthenewexecutableprogramtostart),whethertheyrequireacomma-separatedlistofargumentsoranargv[]array,andwhetherthe6existingenvironmentisusedoranenvp[]arrayispassed.6、创建进程—效率问题fork会将调用进程的所有内容原封不动的拷贝到新产生的子进程中去,这些拷贝的系统开销很大,而如果fork完之后我们马上就调用exec或exit,这些辛辛苦苦拷贝来的东西又会被立刻抹掉,这看起来非常不划算!!!解决方式是采用fork1()或vfork(),fork1()仅创建父进程中的一个线程,vfork()将拷贝的过程拖延到真正需要的时候。vfork()只是借用父进程的地址空间,这个奇特状态将持续直到子进程要么退出,要么调用“execve()”,至此父进程才继续执行。这意味着一个由“vfork()”创建的子进程必须小心以免出乎意料地改变父进程的变量。特别的,子进程必须不从包含“vfork()”调用的函数返回,而且必须不调用“exit()”(如果它需要退出,它需要使用“_exit()”;事实上,对于使用正常“fork()”创建的子进程这也是正确的。图3fork-exec前后内存空间变化7、进程终止—正常/异常终止正常终止:从main函数返回;调用exit函数或调用_exit系统调用函数;异常终止:调用abort函数;或者进程接收到某信号而终止。exit这个系统调用是用来终止一个进程的。无论在程序中的什么位置,只要执行到exit系统调用,进程就会停止剩下的所有操作,清除包括PCB在内的各种数据结构,并终止本进程的运行。进程终止-exit例子/*exit_test1.c*/#includestdlib.hmain(){printf(thisprocesswillexit!);exit(0);7printf(neverbedisplayed!);}编译后运行:$gccexit_test1.c-oexit_test1$./exit_test1将结果填入空白处。分析:,为什么程序并没有打印后面的“neverbedisplayed!”。exit系统调用带有一个整数类型的参数status,我们可以利用这个参数传递进程结束时的状态,比如说,该进程是正常结束的,还是出现某种意外而结束的,一般来说,0表示没有意外的正常结束;其他的数值表示出现了错误,进程非正常结束。我们在实际编程时,可以用wait系统调用接收子进程的返回值,从而针对不同的情况进行不同的处理。exit()函数与_exit()函数最大的区别:exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是“清理I/O缓冲”一项。用_exit()函数直接将进程关闭,该进程缓冲区中的数据就会丢失,反之,如果想保证数据的完整性,就一定要使用exit()函数。进程终止-exitvs_exit例子/*exit2.c*/#includestdlib.hmain(){printf(outputbegin);printf(contentinbuffer);exit(0);}8编译并运行:$gccexit2.c-oexit2$./exit2请将结果填入空白处。/*_exit1.c*/#includeunistd.hmain(){printf(outputbegin);printf(contentinbuffer);_exit(0);}编译并运行:$gcc_exit1.c-o_exit1$./_exit1请将结果填入空白处。8、进程终止—僵尸进程zombie什么是僵尸
本文标题:UNIX操作系统实验3
链接地址:https://www.777doc.com/doc-3368399 .html