进程管理之(二)进程的控制实验

实验目的

1、掌握进程另外的创建方法

2、熟悉进程的睡眠、同步、撤消等进程控制方法

 

实验内容

    1、用fork( )创建一个进程,再调用exec( )用新的程序替换该子进程的内容

2、利用wait( )来控制进程执行顺序

 

实验指导

一、所涉及的系统调用

在UNIX/LINUX中fork( )是一个非常有用的系统调用,但在UNIX/LINUX中建立进程除了fork( )之外,也可用与fork( ) 配合使用的exec( )。

1、exec(  )系列

系统调用exec( )系列,也可用于新程序的运行。fork( )只是将父进程的用户级上下文拷贝到新进程中,而exec( )系列可以将一个可执行的二进制文件覆盖在新进程的用户级上下文的存储空间上,以更改新进程的用户级上下文。exec( )系列中的系统调用都完成相同的功能,它们把一个新程序装入内存,来改变调用进程的执行代码,从而形成新进程。如果exec( )调用成功,调用进程将被覆盖,然后从新程序的入口开始执行,这样就产生了一个新进程,新进程的进程标识符id 与调用进程相同。

exec( )没有建立一个与调用进程并发的子进程,而是用新进程取代了原来进程。所以exec( )调用成功后,没有任何数据返回,这与fork( )不同。exec( )系列系统调用在UNIX系统库unistd.h中,共有execl、execlp、execle、execv、execvp五个,其基本功能相同,只是以不同的方式来给出参数。

一种是直接给出参数的指针,如:

int execl(path,arg0[,arg1,...argn],0);

char *path,*arg0,*arg1,...,*argn;

另一种是给出指向参数表的指针,如:

int execv(path,argv);

char *path,*argv[ ];

具体使用可参考有关书。

2、exec( )和fork( )联合使用

系统调用exec和fork( )联合使用能为程序开发提供有力支持。用fork( )建立子进程,然后在子进程中使用exec( ),这样就实现了父进程与一个与它完全不同子进程的并发执行。

一般,wait、exec联合使用的模型为:

int status;

      ............

if (fork( )= =0)

 {

      ...........;

      execl(...);

      ...........;

 }

wait(&status);

3、wait

等待子进程运行结束。如果子进程没有完成,父进程一直等待。wait( )将调用进程挂起,直至其子进程因暂停或终止而发来软中断信号为止。如果在wait( )前已有子进程暂停或终止,则调用进程做适当处理后便返回。

系统调用格式:

int  wait(status) 

int  *status;

其中,status是用户空间的地址。它的低8位反应子进程状态,为0表示子进程正常结束,非0则表示出现了各种各样的问题;高8位则带回了exit( )的返回值。exit( )返回值由系统给出。

核心对wait( )作以下处理:

(1)首先查找调用进程是否有子进程,若无,则返回出错码;

(2)若找到一处于“僵死状态”的子进程,则将子进程的执行时间加到父进程的执行时间上,并释放子进程的进程表项;

(3)若未找到处于“僵死状态”的子进程,则调用进程便在可被中断的优先级上睡眠,等待其子进程发来软中断信号时被唤醒。

4、exit

终止进程的执行。

系统调用格式:

    void exit(status)

     int status;

其中,status是返回给父进程的一个整数,以备查考。

为了及时回收进程所占用的资源并减少父进程的干预,UNIX/LINUX利用exit( )来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条exit( ),使子进程自我终止。exit(0)表示进程正常终止,exit(1)表示进程运行有错,异常终止。

如果调用进程在执行exit( )时,其父进程正在等待它的终止,则父进程可立即得到其返回的整数。核心须为exit( )完成以下操作:

(1)关闭软中断

(2)回收资源

(3)写记帐信息

(4)置进程为“僵死状态”

    二、参考程序

#include<stdio.h>

#include<unistd.h>

main( )

{     

        int pid;   

        pid=fork( );         /*创建子进程*/

switch(pid)

{

               case -1:                          /*创建失败*/

                       printf("fork fail!/n");

                       exit(1);

               case 0:                                 /*子进程*/

                       execl("/bin/ls","ls","-1","-color",NULL);  

                       printf("exec fail!/n");

                       exit(1);

               default:                                 /*父进程*/

                       wait(NULL);                  /*同步*/

                       printf("ls completed !/n");

          ,              exit(0);

          }

}

三、运行结果

执行命令ls -l -color ,(按倒序)列出当前目录下所有文件和子目录;

ls completed!

四、分析原因

程序在调用fork( )建立一个子进程后,马上调用wait( ),使父进程在子进程结束之前,一直处于睡眠状态。子进程用exec( )装入命令ls ,exec( )后,子进程的代码被ls的代码取代,这时子进程的PC指向ls的第1条语句,开始执行ls的命令代码。

注意在这里wait( )给我们提供了一种实现进程同步的简单方法。

五、思考

(1)可执行文件加载时进行了哪些处理?

(2)什么是进程同步?wait( )是如何实现进程同步的?

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值