2022年操作系统实验报告-实验四 .pdf

上传人:Che****ry 文档编号:25487007 上传时间:2022-07-11 格式:PDF 页数:15 大小:1.90MB
返回 下载 相关 举报
2022年操作系统实验报告-实验四 .pdf_第1页
第1页 / 共15页
2022年操作系统实验报告-实验四 .pdf_第2页
第2页 / 共15页
点击查看更多>>
资源描述

《2022年操作系统实验报告-实验四 .pdf》由会员分享,可在线阅读,更多相关《2022年操作系统实验报告-实验四 .pdf(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、实验四:进程管理二实验内容 : 1编写一个程序,打印进程的如下信息:进程标识符,父进程标识符,真实用户ID,有效用户ID,真实用户组ID,有效用户组ID。并分析真实用户ID 和有效用户ID 的区别。源代码及结果:真实用户 ID 和有效用户ID 的区别:真实用户ID :这个 ID 就是我们登陆unix 系统时的身份ID。有效用户ID :定义了操作者的权限。有效用户 ID 是进程的属性, 决定了该进程对文件的访问权限。2阅读如下程序, 编译并运行, 分析进程执行过程的时间消耗总共消耗的时间和CPU消耗的时间 ,并解释执行结果。再编写一个计算密集型的程序替代grep,比较两次时间的花销。注释程序主要

2、语句。/*process using time */#include#include#include#include#includevoid time_print(char *,clock_t);精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 1 页,共 15 页int main(void)/ 取得进程运行相关的时间clock_t start,end; struct tms t_start,t_end; start = times(&t_start);system( “ grep the /usr/doc/*/* /dev/null 2 /dev/

3、null” );/*command /dev/null的作用是将是command 命令的标准输出丢弃,而标准错误输出还是在屏幕上。一般来讲标准输出和标准错误输出都是屏幕,因此错误信息还是会在屏幕上输出。 /dev/null 2 /dev/null 标准输出与标准错误输出都会被丢弃*/ 0 1 2 标准输入标准输出错误输出/ 将信息放到该文件null 中end=times(&t_end);time_print(“ elapsed ” ,end-start);puts( “ parent times” );time_print(“ tuser CPU” ,);time_print(“ tsys C

4、PU” ,);puts( “ child times” );time_print(“ tuser CPU” ,);time_print(“ tsys CPU” ,);exit(EXIT_SUCCESS);void time_print(char *str, clock_t time)long tps = sysconf(_SC_CLK_TCK);/* 函数 sysconf()的作用为将时钟滴答数转化为秒数,_SC_CLK_TCK 为定义每秒钟精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 2 页,共 15 页有多少个滴答的宏*/ printf(“

5、%s: %6.2f secsn” ,str,(float)time/tps);程序运行结果:因为该程序计算量很小,故消耗的时间比较少,CPU消耗时间均为0.00secs 不足为奇。而进程的执行时间等于用户CPU时间和系统CPU时间加从硬盘读取数据时间之和。密集型的程序替代grep:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 3 页,共 15 页更改为计算密集型的之后就较容易观察出消耗时间的差异。3阅读以下程序,编译并多次运行,观察执行输出次序,说明次序相同或不同的原因;观察进程ID ,分析进程ID 的分配规律。总结fork() 的使用方法。注释

6、程序主要语句。/* fork usage */#include#include#includeint main(void)pid_t child;if(child=fork()=-1)perror(“ fork ” );exit(EXIT_FAILURE);else if(child=0)puts( “ in child” );printf(“ tchild pid = %dn” ,getpid();精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 4 页,共 15 页printf(“ tchild ppid = %dn” ,getppid();ex

7、it(EXIT_SUCCESS);elseputs( “ in parent” );printf(“ tparent pid = %dn” ,getpid();printf(“ tparent ppid = %dn” ,getppid();exit(EXIT_SUCCESS);程序运行结果:?创建进程ID 开始时一般随机分配,但假设多次运行,或创建子进程时,会顺序分配内存。此外,当父进程结束时,子进程尚未结束,则子进程的父进程ID 变为 1。fork() 函数的实质是一个系统调用(和 write 函数类似 ),其作用是创建一个新的进程,当一个进程调用它 ,完成后就出现两个几乎一模一样的进程,其

8、中由 fork() 创建的新进程被称为子进精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 5 页,共 15 页程,而原来的进程称为父进程。子进程是父进程的一个拷贝,即子进程从父进程得到了数据段和堆栈的拷贝,这些需要分配新的内存;而对于只读的代码段,通常使用共享内存方式进行访问。4阅读以下程序,编译并运行,等待或者按C,分别观察执行结果并分析,注释程序主要语句。 flag 有什么作用?通过实验说明。/* usage of kill,signal,wait */#include#include#include#includeint flag;void

9、stop(); /自定义函数,使flag=0,供 signal 调用int main(void)int pid1,pid2;signal(3,stop); / signal() 依参数 3 指定的信号编号来设置该信号的处理函数while(pid1=fork() =-1); /程序等待成功创建子进程事件的发生if(pid10)/当前进程为父进程while(pid2=fork() =-1);if(pid20)/当前进程为父进程,父进程发出两个中断信号Kill 子进程flag=1;sleep(5);kill(pid1,16); /将 16 指定的信号传给进程ID 为 pid1 的进程kill(pid

10、2,17); /将 17 指定的信号传给进程ID 为 pid2 的进程wait(0); /暂时停止目前进程的执行,直到有信号来到或子进程结束wait(0);printf(“ n parent is killedn” );精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 6 页,共 15 页exit(EXIT_SUCCESS);else/当前进程为子进程,则发送子进程kill 信号,杀死该子进程2flag=1;signal(17,stop);printf(“ n child2 is killed by parentn” );exit(EXIT_SUCC

11、ESS);else/当前进程为子进程,则发送子进程kill 信号,杀死该子进程1flag=1;signal(16,stop);printf(“ n child1 is killed by parentn” );exit(EXIT_SUCCESS);void stop()flag = 0;程序运行结果:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 7 页,共 15 页每个进程父进程,子进程都有一个flag,起状态标志作用,flag=1 时,表示进程在运行, flag=0,表示进程结束。5编写程序,要求父进程创建一个子进程,使父进程和个子进程各自在屏

12、幕上输出一些信息,但父进程的信息总在子进程的信息之后出现。程序源代码:程序运行结果:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 8 页,共 15 页6编写程序,要求父进程创建一个子进程,子进程执行shell 命令 find / -name hda* 的功能,子进程结束时由父进程打印子进程结束的信息。执行中父进程改变子进程的优先级。程序源代码:程序运行结果:精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 9 页,共 15 页精选学习资料 - - - - - - - - - 名师归纳总结 - - - -

13、 - - -第 10 页,共 15 页7/* 编写程序,要求父进程创建一个子进程,子进程对一个50*50 的字符数组赋值,由父进程改变子进程的优先级,观察不同优先级进程使用CPU 的时间。 */8查阅 Linux 系统中 struct task_struct 的定义,说明每项成员的作用。注: search in /usr/srclinux/广义上, 所有的进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。每个进程在内核中都有一个进程控制块(PCB) 来维护进程相关的信息,Linux 内核的进程控制块是task_struct 结构体。 task_struct 是 Linux

14、 内核的一种数据结构,它会被装载到 RAM里并且包含着进程的信息。每个进程都把它的信息放在task_struct 这个数据结构里, task_struct 包含了这些内容:1标示符:描述本进程的唯一标示符,用来区别其他进程。2状态:任务状态,退出代码,退出信号等。3优先级:相对于其他进程的优先级。4程序计数器:程序中即将被执行的下一条指令的地址。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 11 页,共 15 页5内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。6上下文数据:进程执行时处理器的寄存器中的数据。7IO

15、状态信息:包括显示的I/O 请求 ,分配给进程的IO 设备和被进程使用的文件列表。8记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号。 保存进程信息的数据结构叫做task_struct,并且可以在include/linux/ 里找到它。所有运行在系统里的进程都以task_struct 链表的形式存在内核里。进程的信息可以通过/proc 系统文件夹查看。task_struct一些字段的介绍:1. 调度数据成员(1) volatile long states;表示进程的当前状态(2) unsigned long flags;进程标志(3) long priority;进程优先级

16、。优先级可通过系统调用sys_setpriorty 改变。(4) unsigned long rt_priority;rt_priority 给出实时进程的优先级,rt_priority+1000给出进程每次获取CPU 后可使用的时间(同样按jiffies计 )。实时进程的优先级可通过系统调用sys_sched_setscheduler()改变 (见kernel/)。(5) long counter;在轮转法调度时表示进程当前还可运行多久。在进程开始运行是被赋为priority 的值,以后每隔一个tick(时钟中断 )递减 1,减到 0 时引起新一轮调度。重新调度将从run_queue 队列选

17、出 counter 值最大的就绪进程并给予CPU 使用权,因此counter 起到了进程的动态优先级的作用 (priority 则是静态优先级)。(6) unsigned long policy;该进程的进程调度策略,可以通过系统调用sys_sched_setscheduler()更改 (见 kernel/)。调度策略有 :?SCHED_OTHER0非实时进程,基于优先权的轮转法(round robin) 。?SCHED_FIFO1实时进程,用先进先出算法 。?SCHED_RR2实时进程,用基于优先权的轮转法。2. 信号处理(1) unsigned long signal;进程接收到的信号。每

18、位表示一种信号,共32 种。置位有效。(2) unsigned long blocked;进程所能接受信号的位掩码。置位表示屏蔽,复位表示不屏蔽。(3) struct signal_struct *sig;因为 signal 和 blocked 都是 32 位的变量, Linux 最多只能接受32 种信号。对每种信号,各进程可以由PCB 的 sig 属性选择使用自定义的处理函数,或是系统的缺省处理函数。指派各种信息处理函数的结构定义在include/linux/ 中。对信号的检查安排在系统调用结束后,以及“ 慢速型 ” 中断服务程序结束后(IRQ#_interrupt() 。精选学习资料 -

19、- - - - - - - - 名师归纳总结 - - - - - - -第 12 页,共 15 页3. 进程队列指针(1) struct task_struct *next_task ,*prev_task;所有进程 (以 PCB 的形式 )组成一个双向链表。next_task 和就是链表的前后指针。链表的头和尾都是init_task( 即 0 号进程 )。(2) struct task_struct *next_run ,*prev_run;由正在运行或是可以运行的,其进程状态均为TASK_RUNNING的进程所组成的一个双向循环链表,即run_queue 就绪队列。该链表的前后向指针用ne

20、xt_run 和 prev_run,链表的头和尾都是init_task( 即 0 号进程 )。(3) struct task_struct *p_opptr ,*p_pptr; 和 struct task_struct *p_cptr ,*p_ysptr , *p_osptr;以上分别是指向原始父进程(original parent)、父进程 (parent)、子进程 (youngest child)及新老兄弟进程 (younger sibling , older sibling) 的指针。4. 进程标识(1) unsigned short uid, gid;uid 和 gid 是运行进程的用

21、户标识和用户组标识。(2) int groupsNGROUPS;与多数现代UNIX操作系统 一样, Linux 允许进程同时拥有一组用户组号。在进程访问文件时,这些组号可用于合法性检查。(3) unsigned short euid,egid;euid 和 egid 又称为有效的uid 和 gid。出于系统安全的权限的考虑,运行程序时要检查euid和 egid 的合法性。通常,uid 等于 euid,gid 等于 egid。有时候,系统会赋予一般用户暂时拥有 root 的 uid 和 gid(作为用户进程的euid 和 egid),以便于进行运作。(4) unsigned short fsui

22、d ,fsgid;fsuid 和 fsgid 称为文件系统的uid 和 gid,用于文件系统操作时的合法性检查,是 Linux 独特的标识类型。它们一般分别和euid 和 egid 一致,但在NFS 文件系统中NFS 服务器需要作为一个特殊的进程访问文件,这时只修改客户进程的fsuid 和 fsgid。(5) unsigned short suid,sgid;suid 和 sgid 是根据 POSIX 标准引入的,在系统调用改变uid 和 gid 时,用于保留真正的uid和 gid。(6) int pid ,pgrp,session;进程标识号、进程的组织号及session标识号,相关系统调用

23、(见程序 kernel/)有 sys_setpgid、sys_getpgid、sys_setpgrp、 sys_getpgrp、sys_getsid 及 sys_setsid几种。(7) int leader;是否是 session的主管,布尔量。5. 时间数据成员(1) unsigned long timeout;用于软件定时,指出进程间隔多久被重新唤醒。采用tick 为单位。(2) unsigned long it_real_value ,it_real_iner;用于 itimer(interval timer)软件定时。采用jiffies 为单位,每个tick 使 it_real_va

24、lue 减到 0 时向进程发信号SIGALRM ,并重新置初值。初值由 it_real_incr 保存。具体代码见kernel/中的函数 it_real_fn() 。(3) struct timer_list real_timer;一种定时器结构(Linux共有两种定时器结构,另一种称作old_timer) 。 数据结构 的定义在include/linux/ 中,相关操作函数见kernel/中 add_timer() 和 del_timer() 等。(4) unsigned long it_virt_value ,it_virt_incr;精选学习资料 - - - - - - - - - 名师

25、归纳总结 - - - - - - -第 13 页,共 15 页关于进程用户态执行时间的itimer 软件定时。采用jiffies 为单位。进程在用户态运行时,每个 tick 使 it_virt_value 减 1,减到 0 时向进程发信号SIGVTALRM ,并重新置初值。初值由it_virt_incr 保存。具体代码见kernel/中的函数do_it_virt() 。(5) unsigned long it_prof_value ,it_prof_incr;同样是 itimer 软件定时。采用jiffies 为单位。不管进程在用户态或内核态运行,每个tick 使it_prof_value 减

26、 1,减到0 时向进程发信号SIGPROF,并重新置初值。初值由it_prof_incr保存。具体代码见kernel/中的函数 do_it_prof 。(6) long utime ,stime, cutime,cstime,start_time;以上分别为进程在用户态的运行时间、进程在内核态的运行时间、所有层次子进程在用户态的运行时间总和、所有层次子进程在核心态的运行时间总和,以及创建该进程的时间。6. 信号量数据成员(1) struct sem_undo *semundo;进程每操作一次信号量,都生成一个对此次操作的undo 操作,它由sem_undo 结构描述。这些属于同一进程的undo

27、 操作组成的链表就由semundo 属性指示。当进程异常终止时,系统会调用undo 操作。 sem_undo的成员 semadj 指向一个数据数组,表示各次undo 的量。结构定义在include/linux/ 。(2) struct sem_queue *semsleeping;每一信号量集合对应一个sem_queue等待队列 (见 include/linux/) 。进程因操作该信号量集合而阻塞时,它被挂到semsleeping 指示的关于该信号量集合的sem_queue 队列。反过来,semsleeping。sleeper 指向该进程的PCB。7. 进程上下文环境(1) struct de

28、sc_struct *ldt;进程关于 CPU 段式存储管理的局部描述符表的指针,用于仿真WINE Windows 的程序。其他情况下取值NULL ,进程的 ldt 就是 arch/i386/ 定义的 default_ldt 。(2) struct thread_struct tss;任务状态段,其内容与INTEL CPU 的 TSS 对应,如各种通用寄存器.CPU 调度时,当前运行进程的TSS 保存到 PCB 的 tss,新选中进程的tss 内容复制到CPU 的 TSS。结构定义在include/linux/ 中。(3) unsigned long saved_kernel_stack;为

29、MS-DOS 的仿真程序 (或叫系统调用vm86)保存的堆栈指针。(4) unsigned long kernel_stack_page;在内核态运行时,每个进程都有一个内核堆栈,其基地址就保存在kernel_stack_page 中。8. 文件系统数据成员(1) struct fs_struct *fs;fs 保存了进程本身与VFS 的关系消息, 其中 root 指向根目录结点,pwd 指向当前目录结点,umask 给出新建文件的访问模式(可由系统调用umask 更改 ),count 是 Linux 保留的属性, 如下页图所示。结构定义在include/linux/ 中。(2) struct

30、 files_struct *files;files 包含了进程当前所打开的文件(struct file *fdNR_OPEN) 。在 Linux 中,一个进程最多只能同时打开NR_OPEN 个文件。 而且, 前三项分别预先设置为标准输入、标准输出和出错消息输出文件。(3) int link_count;文件链 (link) 的数目。Array. 内存数据成员精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 14 页,共 15 页(1) struct mm_struct *mm;在 linux 中,采用按需分页的策略解决进程的内存需求。task_struct 的数据成员mm 指向关于存储管理的mm_struct 结构。其中包含了一个虚存队列mmap, 指向由假设干vm_area_struct描述的虚存块。 同时,为了加快访问速度,mm 中的 mmap_avl 维护了一个AVL 树。在树中,所有的 vm_area_struct 虚存块均由左指针指向相邻的低虚存块,右指针指向相邻的高虚存块。结构定义在include/linux/ 中。精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 15 页,共 15 页

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁