Linux 进程管理实验Word文件下载.docx
《Linux 进程管理实验Word文件下载.docx》由会员分享,可在线阅读,更多相关《Linux 进程管理实验Word文件下载.docx(9页珍藏版)》请在冰豆网上搜索。
![Linux 进程管理实验Word文件下载.docx](https://file1.bdocx.com/fileroot1/2023-1/21/e1ff7dbb-d5a1-49d7-b577-fce896175dda/e1ff7dbb-d5a1-49d7-b577-fce896175dda1.gif)
一个叫做用户堆栈,它是进程运行在用户空间时使用的堆栈;
另一个叫做系统堆栈,它是用户进程运行在系统空间时使用的堆栈。
1.Linux进程的状态:
Linux进程用进程控制块的state域记录了进程的当前状态,一个Linux进程在它的生存期中,可以有下面6种状态。
1。
就绪状态(TASK_RUNNING):
在此状态下,进程已挂入就绪队列,进入准备运行状态.
运行状态(TASK_RUNNING):
当进程正在运行时,它的state域中的值不改变。
但是Linux会用一个专门指针(current)指向当前运行的任务。
可中断等待状态(TASK_INTERRUPTIBLE):
进程由于未获得它所申请的资源而处在等待状态。
不管是资源有效或者中断唤醒信号都能使等待的进程脱离等待而进入就绪状态。
即”浅睡眠状态”。
4.不可中断等待状态(TASK_UNINTERRUPTIBLE):
这个等待状态与上面等待状态的区别在于只有当它申请的资源有效时才能被唤醒,而其它信号不能.即“深睡眠状态"
。
5.停止状态(TASK_STOPPED):
当进程收到一个SIGSTOP信号后就由运行状态进入停止状态,当收到一个SINCONT信号时,又会恢复运行状态.挂起状态。
6。
终止状态(TASK_ZOMBIE):
进程因某种原因终止运行,但进程控制块尚未注销。
即“僵死状态”.
状态图如下所示:
2.Linux进程控制块:
在Linux中,进程控制块为数据结构task_struct,它包含了大量该进程的信息,这些信息大致为以下几类:
1)。
进程的当前状态
2)。
调度信息
3)。
进程标识
4).进程的通信信息
5).进程与其它进程之间关系的信息
6)。
使用文件的信息
7)。
虚拟内存与物理内存的关系
8).计时器
9).处理器与进程的有关信息
3.Fork函数:
父进程创建一个子进程最方便快捷的方式就是把父进程的控制块照原样复制一个,然后再根据子进程的修改特点对它进行必要的修改,形成子进程的控制块。
系统调用fork()通过调用find_empty_process及copy_process等函数复制一个当前进程的进程控制块,然后用新进程标识修改旧标识,填写子进程与父进程关系,创建子进程堆栈和数据区.
因此,fork()执行后,父子进程共享同一个存储空间,父进程的所有可共享资源都被子进程通过数据结构的复制继承了过来.
在父进程调用fork()与在子进程中调用fork(),fork()的返回值不同!
如果是在父进程调用fork(),则fork()就复制出一个子进程,并返回子进程的标识ID,如果创建子进程失败,则fork()的返回值为-1;
而如果在子进程调用fork(),则它返回的是0。
三、实验步骤及结果
在安装目录下双击bochs。
exe,选择提供好的linux0。
11配置文件,点击start,启动虚拟机,如下图所示:
一、利用bochs观测linux0.11下的PCB进程控制结构
1.切换工作目录到/usr/src/linux/include/linux文件夹,如下所示:
利用vi编辑器打开sched.h头文件,寻找structtask_struct结构体的定义,如下:
观察进程控制块的内容,对里面的一些变量分析:
Longstate:
表示当前进程所处的状态。
—1为不可运行,0可运行(就绪),>
0已停止.进程执行时,它会根据具体情况改变状态.Linux中的进程主要有如下状态,如下所示:
内核表示
含义
TASK_RUNNING
可运行
TASK_INTERRUPTIBLE
可中断的等待状态
TASK_UNINTERRUPTIBLE
不可中断的等待状态
TASK_ZOMBIE
僵死
TASK_STOPPED
暂停
TASK_SWAPPING
换入/换出
Longcounter:
表示当前进程所剩余的时间片
Longpriority:
表示当前进程的优先级。
Longsignal:
存储进程收到的信号。
Unsignedshortuid:
用户ID,指的是进程执行者是谁。
Structfile*filp[NR_OPEN]:
进程打开的文件列表:
进程可以打开或关闭文件,文件属于系统资源,Linux内核要对进程使用文件的情况进行记录。
task_struct结构中有两个数据结构用于描述进程与文件相关的信息。
其中,fs_struct中描述了两个VFS索引节点(VFSinode),这两个索引节点叫做root和pwd,分别指向进程的可执行映象所对应的根目录和当前目录或工作目录。
file_struct结构用来记录了进程打开的文件的描述符。
二、利用bochs观测linux0。
11下的fork.c源代码文件,分析其中的重要函数:
1.切换工作目录到/usr/src/linux/kernel文件夹,利用vi编辑打开fork.c文件:
通过观察该程序主要实现了以下几个函数:
find_empty_process,copy_mem,copy_process等,其中,调用关系大体如下所示:
Fork调用find_empty_process,而后者又调用copy_process;
然后
Copy_process调用copy_mem,Copy_mem调用copy_page_tables,下面找到copy_process函数,如下:
在该函数中有*p=*current代码,这句代码表示:
current是指向父进程PCB结构体的指针,p是指向子进程PCB结构体的指针,操作系统先把父进程的PCB结构体完完整整的复制了一份给子进程。
2.找到copy_mem函数,发现其调用copy_page_tables.其中,copy_page_tables的实现在/usr/src/linux/mm/memory。
c文件中,其代码截图如下:
上述代码表明把两个进程的不同线性空间映射到同一片物理内存上。
2.当copy_process调用结束后,整个创建进程的过程就已经完成了大半部分,此后,再对子进程的信息做必要修改后,子进程就可以像父进程一样被执行了。
三、在fork.c适当位置添加代码,以验证fork函数的工作原理
1.fork函数复制了父进程的PCB,这里验证一下具有父子关系的两个进程,是否一致。
2.打开/usr/src/linux/kernel/fork。
c文件,找到其中copy_process函数如下,在函数的最后,加入相关打印信息代码在程序的后面,并去除注释:
程序中if(p-pid〉5&&p->
father!
=4)是为了区别系统进程与用户进程而设置的。
因为,如果不这样区分,会导致打印出一些我们不想看到的信息,造成混乱,不方便实验观察。
p->
start_code是p所指向进程的页目录信息。
exper_page_table是p所指向进程的页表信息.For(k1=0;
k1<
NR_TASKS;
k1++)循环是在系统的进程槽中找到p所指向进程的父进程,然后,将父进程相关页目录,页表信息打印。
保存并退出vi编辑器,切换工作目录到/usr/src/linux执10行。
makeclean命令,将系统以前的编译信息清除掉.
4。
然后执行make命令,重新编译linux0。
11内核
5。
编译完成后,输入ddbs=8192if=Imageof=/dev/fd0,用新生成的内核替换掉旧的内核.
6.点击bochs中中的reset按钮,重启虚拟机;
重启后,编译运行experiment。
c文件,观察实验效果,其中experiment。
c程序代码如下图所示:
编译运行结果显示如下:
由运行结果可以看出,父子进程的页表指向了同一个物理地址,从而验证了我们之前的理论,子进程会复制父进程的PCB,共享其内存
空间。
四、实验结果与心得
本次实验主要通过学习Linux系统进程管理机制,并通过Bochs进行验证.实验中通过初步阅读linux0。
11操作系统源代码,了解其创建进程的大体流程。
另外,通过修改源代码,验证了fork函数的工作原理。
实验中首先要比较深入的理解进程控制块以及fork函数,我觉得自己理解起来还是有点困难。
不过通过实验,阅读内核代码的能力有所提高,并初步学会如何去修改代码并实现验证.为以后的学习打下一个良好的基础,所以收获颇多。