作业必备:操作系统实验三:【进程控制】

作业必备:操作系统实验三:【进程控制】操作系统:进程控制_5、修改程序fork_1.c,在父进程执行”while(1)”之前,添加代码”wait(0);”

实验三:进程控制

红体字依然是懒懒的小白必看内容~~

请添加图片描述

【实验前的准备】

先来点**必读材料**
一、进程的控制

进程因创建而存在,因执行完成或异常原因而终止.在进程的生命周期中,进程在内存中有三种基本状态:**就绪,执行,阻塞**.进程状态的转换是通过进程控制原语来实现的。Linux操作系统提供了相应功能的系统调用及命令,来实现用户层的进程控制。

二、相关命令:

(1)睡眠指定时间
执行格式:# sleep x,x为指定睡眠的秒数。
(2)结束或终止进程 kill
执行格式: # kill [-9] PID (PID为利用ps命令所查出的process ID)
(3)查看正在background中执行的process
执行格式:# jobs
(4)用户在终端输入Linux命令时,对应的shell通常会建立子进程来运行该命令。通过ps命令可以查看用户空间的当前进程。
执行格式: # ps [-auf]
-a 列出当前终端上启动的所有进程;
-u 按用户名和启动时间的顺序来显示进程;
-f 以全格式列出

三、系统调用:

1、exec( )系列:
如果exec( )调用成功,调用进程将被覆盖,然后从新程序的入口开始执行。exec( )没有建立一个与调用进程并发的子进程,而是用**新进程取代了原来进程**。所以exec( )调用成功后,没有任何数据返回。
2、exec( )和fork( )联合使用
系统调用exec和fork( )联合使用能为程序开发提供有力支持。用fork( )建立子进程,然后在子进程中使用exec( ),这样就实现了父进程与一个与它完全不同子进程的并发执行。

更多关于exec()系列函数,请见这位大佬的博文:

https://blog.csdn.net/amoscykl/article/details/80354052?utm_source=app&app_version=5.3.0&code=app_1562916241&uLinkId=usr1mkqgl919blen

3、wait()
等待子进程运行结束。如果子进程没有完成,父进程一直等待
4、sleep()
睡眠指定时间。该函数使得当前进程自我阻塞second秒,由执行态转换成阻塞态,直到系统唤醒。
5、exit()
终止进程的执行。为了及时回收进程所占用的资源并减少父进程的干预,LINUX/LINUX利用exit( )来实现进程的自我终止,通常父进程在创建子进程时,应在进程的末尾安排一条exit( ),使子进程自我终止。exit(0)表示进程正常终止,exit(1)表示进程运行有错,异常终止。

掌握了以上知识点,就可以开始实验了~

【实验目的】

1、了解进程创建后对进程控制的系统调用,可实现对进程的有效控制
2、掌握进程的睡眠、同步、撤消等进程控制方法

【实验内容】

0、阅读实验相关资料。
1、通过相关命令,对进程的状态进行控制。
2、编写程序,使用fork( )创建一个子进程。使用相关的系统调用控制进程的状态。观察并分析多进程的执行次序及状态转换。

【实验步骤】:

1、参考程序:

#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
int main( )
{ 
         
	int pid;    
	pid=fork( );        /*创建子进程*/
	switch(pid) 
	{ 
   
      	   case  -1:                          /*创建失败*/
		printf("fork fail!\n");
		exit(1); 
  	   case  0:/*子进程*/
		printf("Is son:\n"); 
		execl("/bin/ls","ls","-l",NULL); 
		printf("exec fail!\n");
		exit(1);
   	   default:/*父进程*/
		printf("ls parent:\n");
		while(1)  sleep(1);
		exit(0);
    	}
	return 0;
}

2、运行结果:

yzy@yzy-virtual-machine:~/123$ gcc fork_exec.c -o def
yzy@yzy-virtual-machine:~/123$ ./def&
[2] 2318
yzy@yzy-virtual-machine:~/123$ ls parent:
Is son:
总用量 24
-rwxrwxr-x 1 yzy yzy 16992  4月  3 10:12 def
-rw-rw-r-- 1 yzy yzy   502  4月  3 10:09 fork_exec.c

3、解释:子进程用exec( )装入命令ls,exec( )后,子进程的代码被ls的代码取代,这时子进程的PC指向ls的第1条语句,开始执行ls的命令代码。

4、用 jobs命令查看后台运行的process 。

yzy@yzy-virtual-machine:~/123$ jobs
[1]+  运行中               ./def &

5、用ps 命令显示当前终端上启动的所有进程

yzy@yzy-virtual-machine:~/123$ ps -af
UID          PID    PPID  C STIME TTY          TIME CMD
yzy         1612    1609  1 10:08 tty2     00:00:11 /usr/lib/xorg/Xorg vt2 -disp
yzy         1626    1609  0 10:08 tty2     00:00:00 /usr/libexec/gnome-session-b
yzy         2422    2416  0 10:18 pts/0    00:00:00 ./def
yzy         2423    2422  0 10:18 pts/0    00:00:00 [ls] <defunct>
yzy         2425    2416  0 10:20 pts/0    00:00:00 ps -af

解释:倒数第二行,[ls] defunct 说明进程”ls”是一个僵死进程。父进程创建一个子进程后,可以用wait()等待回收其子进程的资源,也可以正常终止后由系统回收其子进程的资源。

6、用kill命令直接杀死该子进程。

yzy@yzy-virtual-machine:~/123$ kill -9 2423
yzy@yzy-virtual-machine:~/123$ ps -af
UID          PID    PPID  C STIME TTY          TIME CMD
yzy         1612    1609  1 10:08 tty2     00:00:12 /usr/lib/xorg/Xorg vt2 -disp
yzy         1626    1609  0 10:08 tty2     00:00:00 /usr/libexec/gnome-session-b
yzy         2422    2416  0 10:18 pts/0    00:00:00 ./def
yzy         2423    2422  0 10:18 pts/0    00:00:00 [ls] <defunct>
yzy         2442    2416  0 10:25 pts/0    00:00:00 ps -af

解释:未能成功,因为父进程还没结束

7、kill命令杀死父进程之后,成功。

yzy@yzy-virtual-machine:~/123$ kill -9 2422
yzy@yzy-virtual-machine:~/123$ ps -af
UID          PID    PPID  C STIME TTY          TIME CMD
yzy         1612    1609  1 10:08 tty2     00:00:13 /usr/lib/xorg/Xorg vt2 -disp
yzy         1626    1609  0 10:08 tty2     00:00:00 /usr/libexec/gnome-session-b
yzy         2459    2416  0 10:27 pts/0    00:00:00 ps -af
[1]+  已杀死               ./def

解释:但是如果父子进程都异常终止,则shell进程将回收其资源。Init进程回收所有僵死进程资源。

8、修改程序fork_ececl.c,在父进程执行” while(1)”之前,添加代码”wait(0);”。在后台执行该程序。显示当前终端上启动的所有进程。

yzy@yzy-virtual-machine:~/123$ Is son:
总用量 24
-rwxrwxr-x 1 yzy yzy 17032  43 11:03 def
-rw-rw-r-- 1 yzy yzy   530  43 11:03 fork_exec.c
ls parent:

解释:子进程结束后,它的父进程在等待(调用wait函数)它,所以Is son先显示。Wait函数:若未找到处于“僵死状态”的子进程,则调用进程便在可被中断的优先级上睡眠,等待其子进程发来软中断信号时被唤醒。

9、修改以上程序,在子进程执行”printf(“Is son:\n”);”之前添加代码“sleep(1);”。(若父进程先输出,则在父进程执行printf(“ls parent:\n”);之前添加代码“sleep(1);”)观察多进程的执行序列,解释原因。

yzy@yzy-virtual-machine:~/123$ ls parent:
Is son:
总用量 24
-rwxrwxr-x 1 yzy yzy 16992  43 11:16 def
-rw-rw-r-- 1 yzy yzy   531  43 11:16 fork_exec.c

解释:sleep函数:second为指定睡眠的秒数。该函数使得当前进程自我阻塞second秒,由执行态转换成阻塞态,直到系统唤醒。
多次执行,都为上述结果,屏幕输出is parent后,停顿约1秒后才显示后续内容。

【实验感想】:

(1)可执行文件加载时进行了哪些处理?参考程序中,什么时候执行语句”printf(“exec fail!\n”);”?

经过这些处理:C源程序一>编译预处理一>编译一>优化程序一>汇编程序一>链接程序一>可执行文件。
execl(“/bin/ls”,“ls”,”-l”,NULL);在这个语句中,“bin/ls”为文件目录路径;“ls”、“-l”代表执行文件传递过去的参数;Null为结束符。。如果exec( )调用成功,调用进程将被覆盖,然后从新程序的入口开始执行。
若execl()没有调用成功,失败原因记录在error中,执行下一条语句:printf("exec fail!\n")

(2)实验指导中的第5步,wait( )是如何实现进程同步的?

首先,程序在调用fork()那里创建了一个子进程后,马上调用wait(),使父进程在子进程调用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步

(3)实验指导中的第6步,sleep(1)为什么能导致进程切换?

Sleep函数使得当前进程自我阻塞1秒,由执行态转换成阻塞态,所以从正在运行的进程中收回处理器,让等待运行的就绪态的进程来占有处理器运行。等中断处理完后,再继续恢复原进程处理

请添加图片描述

喜欢的朋友可以留下你的赞哦~~~

今天的文章作业必备:操作系统实验三:【进程控制】分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/59797.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注