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

简介: 进程控制

实验三:进程控制

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

803020b7e8ad478f9c20c1eff218d0d6.jpg

【实验前的准备】

先来点**必读材料**

一、进程的控制


进程因创建而存在,因执行完成或异常原因而终止.在进程的生命周期中,进程在内存中有三种基本状态:**就绪,执行,阻塞**.进程状态的转换是通过进程控制原语来实现的。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  4月  3 11:03 def
-rw-rw-r-- 1 yzy yzy   530  4月  3 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  4月  3 11:16 def
-rw-rw-r-- 1 yzy yzy   531  4月  3 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秒,由执行态转换成阻塞态,所以从正在运行的进程中收回处理器,让等待运行的就绪态的进程来占有处理器运行。等中断处理完后,再继续恢复原进程处理


7c20e7d1449345b7b1e189368cb367d5.jpg

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



相关文章
|
19天前
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
12天前
|
消息中间件 安全 算法
深入理解操作系统:进程管理的艺术
【10月更文挑战第38天】在数字世界的心脏,操作系统扮演着至关重要的角色。它不仅是硬件与软件的桥梁,更是维持计算机运行秩序的守夜人。本文将带你走进操作系统的核心——进程管理,探索它是如何协调和优化资源的使用,确保系统的稳定与高效。我们将从进程的基本概念出发,逐步深入到进程调度、同步与通信,最后探讨进程安全的重要性。通过这篇文章,你将获得对操作系统进程管理的全新认识,为你的计算机科学之旅增添一份深刻的理解。
|
16天前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第34天】本文旨在探讨操作系统中至关重要的一环——进程管理及其调度策略。我们将从基础概念入手,逐步揭示进程的生命周期、状态转换以及调度算法的核心原理。文章将通过浅显易懂的语言和具体实例,引导读者理解操作系统如何高效地管理和调度进程,保证系统资源的合理分配和利用。无论你是初学者还是有一定经验的开发者,这篇文章都能为你提供新的视角和深入的理解。
38 3
|
18天前
|
Linux 调度 C语言
深入理解操作系统:进程和线程的管理
【10月更文挑战第32天】本文旨在通过浅显易懂的语言和实际代码示例,带领读者探索操作系统中进程与线程的奥秘。我们将从基础知识出发,逐步深入到它们在操作系统中的实现和管理机制,最终通过实践加深对这一核心概念的理解。无论你是编程新手还是希望复习相关知识的资深开发者,这篇文章都将为你提供有价值的见解。
|
20天前
|
算法 调度 UED
深入理解操作系统的进程调度机制
本文旨在探讨操作系统中至关重要的组成部分之一——进程调度机制。通过详细解析进程调度的概念、目的、类型以及实现方式,本文为读者提供了一个全面了解操作系统如何高效管理进程资源的视角。此外,文章还简要介绍了几种常见的进程调度算法,并分析了它们的优缺点,旨在帮助读者更好地理解操作系统内部的复杂性及其对系统性能的影响。
|
21天前
深入理解操作系统:进程与线程的管理
【10月更文挑战第30天】操作系统是计算机系统的核心,它负责管理计算机硬件资源,为应用程序提供基础服务。本文将深入探讨操作系统中进程和线程的概念、区别以及它们在资源管理中的作用。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程和线程的管理技巧。
36 2
|
20天前
|
消息中间件 算法 Linux
深入理解操作系统之进程管理
【10月更文挑战第30天】在数字时代的浪潮中,操作系统作为计算机系统的核心,扮演着至关重要的角色。本文将深入浅出地探讨操作系统中的进程管理机制,从进程的概念入手,逐步解析进程的创建、调度、同步与通信等关键过程,并通过实际代码示例,揭示这些理论在Linux系统中的应用。文章旨在为读者提供一扇窥探操作系统深层工作机制的窗口,同时激发对计算科学深层次理解的兴趣和思考。
|
22天前
|
消息中间件 算法 调度
深入理解操作系统:进程管理与调度策略
【10月更文挑战第29天】本文将带领读者深入探讨操作系统中的核心组件之一——进程,并分析进程管理的重要性。我们将从进程的生命周期入手,逐步揭示进程状态转换、进程调度算法以及优先级调度等关键概念。通过理论讲解与代码演示相结合的方式,本文旨在为读者提供对进程调度机制的全面理解,从而帮助读者更好地掌握操作系统的精髓。
31 1
|
22天前
|
算法 调度 UED
深入理解操作系统中的进程调度
【10月更文挑战第29天】探索进程调度的奥秘,本文将带你深入了解在操作系统中如何管理和控制多个并发执行的程序。从简单的调度算法到复杂的多级反馈队列,我们将逐步揭示如何优化系统性能和提高资源利用率。准备好一起揭开进程调度的神秘面纱吧!
|
22天前
|
调度 Python
深入浅出操作系统:进程与线程的奥秘
【10月更文挑战第28天】在数字世界的幕后,操作系统悄无声息地扮演着关键角色。本文将拨开迷雾,深入探讨操作系统中的两个基本概念——进程和线程。我们将通过生动的比喻和直观的解释,揭示它们之间的差异与联系,并展示如何在实际应用中灵活运用这些知识。准备好了吗?让我们开始这段揭秘之旅!
下一篇
无影云桌面