西北工业大学操作系统实验_OS3(10)

合集下载

哈工大《操作系统》实验3

哈工大《操作系统》实验3

向kernel/printk.c中添加日志打印功能,将以下代码添加到原文件中:
在kernel/fork.c、kernel/sched.c和kernel/exit.c中,找到正确的状态转换点,并添加合适的状态信息,把它输出到log文件之中。

fork.c的修改如下:
exit.c的修改如下:
sched.c的修改如下:
在虚拟机上运行ls -l /var”或“ll /var”查看process.log是否建立,及它的属性和长度;
修改时间片
include/linux/sched.h宏INIT_TASK中定义的:
0,15,15, 分别对应state、counter和priority,将priority值修改,即可实现对时间片大小的调整。

0,15,15, 分别对应state、counter和priority,
priority值修改,即可实现对时间片大小的调整。

在修改时间片将priority由15改为150后,Process 9~20 中Turnaround, Waiting, CPU Burst, I/O Burst变化不大,原因可能是程序中I/O操作占用的时间对于总时间影响的权重过大,导致处理时间体现的并不明显。

或者变化不大的原因是,子进程连续占用cpu的时间要比时间片大很多。

西北工业大学软件与微电子学院Windows程序设计综合训练实验报告实验一

西北工业大学软件与微电子学院Windows程序设计综合训练实验报告实验一

西北⼯业⼤学软件与微电⼦学院Windows程序设计综合训练实验报告实验⼀西北⼯业⼤学《综合创作训练》实验报告学院:软件与微电⼦学院学号:2011303503 2011303513姓名:苗寨⽂张忠钢专业:软件⼯程实验时间: 2014.2.24实验地点:毅字楼310指导教师:西北⼯业⼤学2014 年 2 ⽉⼀、实验⽬的及要求实验⽬的:1)掌握Windows程序设计的相关知识;2)了解使⽤VC++开发Windows程序。

实验要求:1)学会如何使⽤VC++开发windows应⽤程序;2)培养良好的C++代码书写风格;⼆、实验设备(环境)及要求1)P C机最低配置:2G Hz以上CPU;1G以上内存;1G⾃由硬盘空间;2)V C++6.0或者更⾼版本VC++;三、实验内容与步骤1、Windows系统API和SDK(1)CreateDialog:(2) MessageBox:(3) CheckDlgButton(4) CreateBitmap(5) CreateHatchBrush2、VC++调⽤Win32API源程序如下:运⾏之后:选择确认:选择取消:3、代码编写风格(1)变量的命名a.变量名应简短且富于描述。

变量名的选⽤应该易于记忆,即能够指出其⽤途。

b.变量的名字应该是⾮形式的、简单的、容易记忆的。

c. 作为⾮明⽂的规定,局部变量应⽤⼩写字母(如i,j),常量名应全⼤写(如MAX_BUFFER),函数名应该写为动作性的(如CreateDirectory),结构名(类名)应该带有整体性(如class CRaster)。

(2)代码的对齐⽅式“{”、“}”表⽰⼀个块,是⼀个相对独⽴的语义单元。

代码的⾏与⾏之间应该按块对齐,⽽各块之间⼜应当有适当的缩进。

合理使⽤空格也⾮常重要,⼀般在分隔参数、赋值语句和表达式等需要清晰明了的地⽅使⽤空格。

(3)代码的注释注释的所选⽤的风格⼀定要让其他⼈接受,尽量和其他⼈保持风格的⼀致性。

操作系统原理实验

操作系统原理实验

操作系统原理实验一、实验目的本实验旨在通过实际操作,加深对操作系统原理的理解,掌握操作系统的基本功能和调度算法。

二、实验环境1. 操作系统:Windows 102. 虚拟机软件:VirtualBox3. 实验工具:C语言编译器(如gcc)、汇编语言编译器(如nasm)、调试器(如gdb)三、实验内容1. 实验一:进程管理在这个实验中,我们将学习如何创建和管理进程。

具体步骤如下:a) 创建一个C语言程序,实现一个简单的计算器功能。

该计算器能够进行基本的加减乘除运算。

b) 使用fork()系统调用创建一个子进程,并在子进程中执行计算器程序。

c) 使用wait()系统调用等待子进程的结束,并获取子进程的退出状态。

2. 实验二:内存管理在这个实验中,我们将学习如何进行内存管理。

具体步骤如下:a) 创建一个C语言程序,模拟内存分配和释放的过程。

该程序能够动态地分配和释放内存块。

b) 使用malloc()函数分配一块内存,并将其用于存储数据。

c) 使用free()函数释放已分配的内存块。

3. 实验三:文件系统在这个实验中,我们将学习如何进行文件系统的管理。

具体步骤如下:a) 创建一个C语言程序,实现一个简单的文件系统。

该文件系统能够进行文件的创建、读取、写入和删除操作。

b) 使用open()系统调用打开一个文件,并进行读取和写入操作。

c) 使用unlink()系统调用删除一个文件。

四、实验步骤1. 安装虚拟机软件VirtualBox,并创建一个虚拟机。

2. 在虚拟机中安装操作系统Windows 10。

3. 在Windows 10中安装C语言编译器、汇编语言编译器和调试器。

4. 根据实验内容,编写相应的C语言程序并保存。

5. 在命令行中使用gcc编译C语言程序,并生成可执行文件。

6. 运行可执行文件,观察程序的执行结果。

7. 根据实验要求,进行相应的操作和测试。

8. 完成实验后,整理实验报告,包括实验目的、实验环境、实验内容、实验步骤和实验结果等。

实验报告模板

实验报告模板

西北工业大学操作系统实验实验报告班号:1001040×姓名: ******学号: *********/*文件名请使用“bh”+班号后两位+“xh”+学号+姓名+项目号命名,如10010401班同学张三,学号041234,则其项目0实验报告的文件名是bh01xh041234张三0.doc。

请大家严格遵守。

实验报告提交时请删除本注释*/实验日期: 2007.12.31 实验名称: GeekOS字符回显功能实现一、实验目的1、熟悉GeekOs的项目编译、调试和运行环境,掌握GeekOs运行工作过程三、实验内容1、搭建GeekOS的编译和调试平台,掌握GeekOS的内核进程工作原理完成系统的配置,调试project0并添加输入字符并回显功能2、熟悉键盘操作函数,编程实现新建一个内核进程。

该进程的功能是:接受键盘输入的字符并显示到屏幕,当输入ctrl+d时,结束进程。

四、项目要求及分析熟悉键盘操作函数,编程实现新建一个内核进程。

该进程的功能是:接受键盘输入的字符并显示到屏幕,当输入ctrl+d时,结束进程。

此项目要求掌握如何新建一个内核进程并了解键盘处理函数。

需要了解Start_Kernel_Thread函数struct Kernel_Thread* Start_Kernel_Thread(Thread_Start_Func startFunc,ulong_t arg,int priority,bool detached){struct Kernel_Thread* kthread = Create_Thread(priority, detached);if (kthread != 0) {Setup_Kernel_Thread(kthread, startFunc, arg);Make_Runnable_Atomic(kthread);}return kthread;}该函数的主要功能是以参数startFunc指向的代码为进程体生成一个内核进程。

华科操作系统实验报告

华科操作系统实验报告

华科操作系统实验报告一、实验目的操作系统是计算机系统的核心组成部分,对于理解计算机的工作原理和提高计算机应用能力具有重要意义。

本次华科操作系统实验的主要目的是通过实际操作和实践,深入理解操作系统的基本概念、原理和功能,掌握操作系统的核心技术和应用方法,提高我们的实践能力和问题解决能力。

二、实验环境本次实验使用的操作系统为Windows 10 和Linux(Ubuntu 2004),开发工具包括 Visual Studio Code、GCC 编译器等。

实验硬件环境为个人计算机,配置为英特尔酷睿 i7 处理器、16GB 内存、512GB 固态硬盘。

三、实验内容1、进程管理进程创建与销毁进程调度算法模拟进程同步与互斥2、内存管理内存分配与回收算法实现虚拟内存管理3、文件系统文件操作与管理文件系统的实现与优化4、设备管理设备驱动程序编写设备分配与回收四、实验步骤及结果1、进程管理实验进程创建与销毁首先,使用 C 语言编写程序,通过系统调用创建新的进程。

在程序中,使用 fork()函数创建子进程,并在子进程和父进程中分别输出不同的信息,以验证进程的创建和执行。

实验结果表明,子进程和父进程能够独立运行,并输出相应的信息。

进程调度算法模拟实现了先来先服务(FCFS)、短作业优先(SJF)和时间片轮转(RR)三种进程调度算法。

通过模拟多个进程的到达时间、服务时间和优先级等参数,计算不同调度算法下的平均周转时间和平均等待时间。

实验结果显示,SJF 算法在平均周转时间和平均等待时间方面表现较好,而 RR 算法能够提供较好的响应时间和公平性。

进程同步与互斥使用信号量和互斥锁实现了进程的同步与互斥。

编写了生产者消费者问题的程序,通过信号量控制生产者和消费者对缓冲区的访问,避免了数据竞争和不一致的情况。

实验结果表明,信号量和互斥锁能够有效地实现进程间的同步与互斥,保证程序的正确性。

2、内存管理实验内存分配与回收算法实现实现了首次适应(First Fit)、最佳适应(Best Fit)和最坏适应(Worst Fit)三种内存分配算法。

西北工业大学-操作系统实验报告-实验七

西北工业大学-操作系统实验报告-实验七

实验七消息及其传送机制一、实验目的(1)了解什么是消息。

(2)熟悉消息传送的机理。

二、实验内容与要求1、消息的创建、发送和接收。

使用系统调用msgget( ),msgsnd( ),msgrev( ),及msgctl( )编制一长度为256Bytes的消息发送和接收的程序,将自己的进程号传递给对方,并输出至屏幕。

2、对整个实验过程进行分析总结,给出详细步骤。

三、实验过程1、编写程序实现消息的创建、发送和接收。

将参考程序用vi编辑器录入,然后编译执行。

1、client.c#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#define MSGKEY 75 /*定义一个消息关键字*/struct msgform /*定义一个结构,它是一个消息的模式,只说明结构的形式*/{ long mtype; /*消息类型*/char mtext[256]; /*消息正文数组*/};int main(){{struct msgform msg; /*定义msg是前面说明的消息结构类型的变量*/int msggid,pid,*pint;msggid=msgget(MSGKEY,0777); /*用系统调用创建一个消息队列*/pid=getpid(); /*获得当前进程的PID*/printf(“client:pid=%d\n”, pid);pint=(int*)msg.mtext; /*将消息正文的头指针赋给指针变量pint*/*pint=pid;msg.mtype=1; /*指定客户进程的消息类型为1*/msgsnd(msggid,&msg,sizeof(int),0); /*向msggid的消息队列发送消息msg*/msgrcv(msggid,&msg,256,pid,0); /*接收pid类型的消息 */printf(“client:receive from pid %d\n”,*pint);return 0;}2、server.c#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include < signal.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#define MSGKEY 75 /*定义一个消息关键字*/struct msgform /*定义一个与客户端相同的消息关键字*/{ long mtype; /*消息类型*/char mtext[256]; /*消息正文数组*/}msg; /*也可以使用这种方式说明消息结构变量*/void cleanup(int signo); /*说明一个外部函数*/int msgqid;int main(){int i,pid,*pint;for ( i=0; i<23; i++) /*对22个软中断的特殊处理*/signal(i, cleanup); /*若收到22个软中断,转向执行cleanup*/msggid=msgget(MSGKEY,0777|IPC_CREAT); /*创建一个与客户程序相同关键字的消息队列,但它的标志是0777与IPC_CREAT 做“或”操作的结果*/ printf(“server:pid=%d\n”, getpid()); /*输出服务端的进程ID*/for(;;) /*用无限循环完成下列语句*/{ msgrcv(msggid,&msg,256,1,0); /*接收来自客户进程或类型为1的消息 */ pint=(int*)msg.mtext; /*将客户端的消息正文传递给pint*/pid=*pint; /*将读出消息指针送pid,此时*pint中是客户进程的pid值*/printf(“server:receive from pid %d\n”,pid);msg.mtype=pid; /*已接受客户进程的pid为消息类型*/*pint=getpid(); /*以本进程pid作为消息构成消息传递内容*/msgsnd(msggid,&msg,sizeof(int),0); /*发送消息*/}}void cleanup(int signo){ msgctl(msggid , IPC_RMID , 0); /*删除消息队列*/exit(0);}如下图所示:client.cserver.c运行结果如下所示:2、思考题(1)单独执行client或server 有什么结果?(2)执行一个server程序,多次执行client有什么结果?(3)消息机制与管道通信的区别?在消息机制中,进程间的数据交换是以格式化的message为单位,程序员直接利用操作系统提供的一组通信命令,不仅能实现大量的数据传递,而且还是隐藏通信细节,是通信过程对用户透明,减少通信程序的复杂性。

西北工业大学计算机学院

西北工业大学计算机学院

西北工业大学计算机学院计算机操作系统实验指导张羽谷建华王海鹏编2009-3一、操作系统课内实验目的:计算机操作系统课内实验作为操作系统课堂理论教学的辅助部分是加强计算机科学与技术专业实践的重要环节之一。

由于操作系统自身的庞大和复杂,造成学生在学过操作系统课程后,总有一种“雾里看花”的感觉,即只是支离破碎的了解了一些操作系统局部知识,而很难将这些知识融会贯通,对于运用操作系统知识从事设计和应用更是无从谈起。

本实验课的目的就是力图解决上述问题。

二、操作系统实验整体安排和要求:1.课内实验将按以下三个方面进行:对常用的系统调用命令的使用方式有一个较熟练的掌握;对典型操作系统的编程基础知识和机制进行学习和了解;运用一些重要的系统调用编写程序模块,对操作系统中的一些重要概念和典型算法进行实现或验证。

实验内容如下:实验一 Linux操作系统的安装及使用实验二 Linux Shell程序实验三 vi编辑器的学习和使用实验四 观察进程的并发性实验五 构造进程家族树实验六 理解进程的独立空间实验七 请求分页存储管理设计操作系统的课内实验共7个,根据具体上机条件和学时选做2~3个,其中实验2、3中必选1个,实验4~6必选,实验7可选做。

由于所有实验均在Linux环境下工作,用C语言编程,因此学生要具备一定的C语言编程能力,同时要求在充分预习实验内容中相关知识后,再进行实验的上机环节。

另外由于操作系统实验有些题目具有一定的难度和规模,建议采用分组方式进行。

2.操作系统课内实验考核:预习报告30%,上机实验35%,实验报告35%。

3.预习报告内容包括两部分,一是对相关知识学习的书面总结(知识综述和参考文献);二是对本次实验的分析报告(主要针对涉及算法的题目)。

实验报告内容主要包括本次实验的上机结果(数据结构、程序框图、源程序文档和运行情况)以及实验中难点分析和心得。

4.实验软、硬件环境要求:80386DX以上兼容机,可以使用Intel、AMD、CRIX处理器,对80386或80486SX的CPU建议具有数字协处理器。

西北工业大学_计算机系统基础_实验报告_第2次

西北工业大学_计算机系统基础_实验报告_第2次

计算机系统基础实验课第二次实验报告对二进制炸弹求解过程的详细描述首先使用objdump命令对bomb程序进行反汇编,并将汇编代码输出到asm.txt中。

阶段一、字符串比较打开asm.txt文件,搜索到phase_1函数,可以看到以下代码。

08048b33 <phase_1>:8048b33: 83 ec 14 sub $0x14,%esp8048b36: 68 7c a0 04 08 push $0x804a07c8048b3b: ff 74 24 1c pushl 0x1c(%esp)8048b3f: e8 3e 05 00 00 call 8049082 <strings_not_equal>8048b44: 83 c4 10 add $0x10,%esp8048b47: 85 c0 test %eax,%eax8048b49: 74 05 je 8048b50 <phase_1+0x1d>8048b4b: e8 29 06 00 00 call 8049179 <explode_bomb>8048b50: 83 c4 0c add $0xc,%esp8048b53: c3 ret可以看出,用户输入字串指针保存在0x1c(%esp),然后调用<strings_not_equal>,待<strings_not_equal>返回后,测试返回值,若equal则进入下一phase,否则<explode_bomb>,从<strings_not_equal>可知该函数用于比较两函数的值,因此需要两个字串作为输入,上面代码中, pushl 0x1c(%esp)用于传递用户字串指针,则push $0x804a07c自然是传递比较字串的指针了。

打开gdb,x/s 0x80497c0, 可以直接查看到该指针指向的子符串:所以第一个炸弹的拆弹指令为:I turned the moon into something I call a Death Star.阶段二、循环在asm.txt文件中可以找到phase_2函数代码如下:08048b54 <phase_2>:8048b54: 56 push %esi8048b55: 53 push %ebx8048b56: 83 ec 2c sub $0x2c,%esp8048b59: 65 a1 14 00 00 00 mov %gs:0x14,%eax8048b5f: 89 44 24 24 mov %eax,0x24(%esp)8048b63: 31 c0 xor %eax,%eax8048b65: 8d 44 24 0c lea 0xc(%esp),%eax8048b69: 50 push %eax8048b6a: ff 74 24 3c pushl 0x3c(%esp)8048b6e: e8 2b 06 00 00 call 804919e <read_six_numbers>8048b73: 83 c4 10 add $0x10,%esp8048b76: 83 7c 24 04 01 cmpl $0x1,0x4(%esp)8048b7b: 74 05 je 8048b82 <phase_2+0x2e>8048b7d: e8 f7 05 00 00 call 8049179 <explode_bomb>8048b82: 8d 5c 24 04 lea 0x4(%esp),%ebx8048b86: 8d 74 24 18 lea 0x18(%esp),%esi8048b8a: 8b 03 mov (%ebx),%eax8048b8c: 01 c0 add %eax,%eax8048b8e: 39 43 04 cmp %eax,0x4(%ebx)8048b91: 74 05 je 8048b98 <phase_2+0x44>8048b93: e8 e1 05 00 00 call 8049179 <explode_bomb>8048b98: 83 c3 04 add $0x4,%ebx8048b9b: 39 f3 cmp %esi,%ebx8048b9d: 75 eb jne 8048b8a <phase_2+0x36>8048b9f: 8b 44 24 1c mov 0x1c(%esp),%eax8048ba3: 65 33 05 14 00 00 00 xor %gs:0x14,%eax8048baa: 74 05 je 8048bb1 <phase_2+0x5d>8048bac: e8 df fb ff ff call 8048790 <__stack_chk_fail@plt>8048bb1: 83 c4 24 add $0x24,%esp8048bb4: 5b pop %ebx8048bb5: 5e pop %esi8048bb6: c3 ret根据call 804919e <read_six_numbers>可以推测题目要求是输入六个数字。

北航os实验报告

北航os实验报告

北航os实验报告北航OS实验报告一、引言操作系统(Operating System,简称OS)是计算机系统中最基础的软件之一,它负责管理和控制计算机硬件资源,为用户和应用程序提供一个可靠、高效的工作环境。

本文将对北航OS实验进行详细的报告和分析。

二、实验目的本次北航OS实验的目的是让学生深入理解和掌握操作系统的基本原理和实现方式。

通过实践,学生将学会设计和实现一个简单的操作系统,了解操作系统的核心功能和运行机制。

三、实验内容1. 系统引导实验开始时,我们需要编写引导程序,将操作系统加载到计算机的内存中,并跳转到操作系统的入口地址开始执行。

这一步骤是整个实验的起点,也是操作系统正常运行的基础。

2. 中断处理操作系统需要能够处理各种中断事件,如时钟中断、键盘中断等。

学生需要实现中断处理程序,使操作系统能够响应和处理这些中断事件,并根据具体情况进行相应的操作。

3. 进程管理操作系统需要能够管理多个进程的创建、调度和终止。

学生需要设计并实现进程管理模块,包括进程控制块(PCB)的数据结构和进程调度算法。

通过合理的调度策略,提高系统的并发性和响应速度。

4. 内存管理操作系统需要管理计算机的内存资源,包括内存的分配和释放。

学生需要设计并实现内存管理模块,使用合适的算法来管理内存的分配和回收,避免内存泄漏和碎片化问题。

5. 文件系统操作系统需要提供文件系统来管理计算机中的文件和数据。

学生需要设计并实现一个简单的文件系统,包括文件的创建、读写和删除等操作。

通过文件系统,用户可以方便地存储和管理自己的数据。

四、实验过程在实验过程中,我们遇到了许多挑战和问题,但通过不断的尝试和调试,我们最终成功实现了一个简单的操作系统。

以下是我们在实验过程中遇到的一些关键问题和解决方案:1. 内存管理在实验过程中,我们发现内存管理是一个非常关键的问题。

如果内存管理不当,容易导致内存泄漏或者内存碎片化,从而影响系统的性能和稳定性。

我们通过设计一个位图来管理内存的分配和释放,使用首次适应算法来分配内存,并通过合理地回收内存来避免内存泄漏问题。

计算机操作系统实验_运行用户态程序

计算机操作系统实验_运行用户态程序

西北工业大学操作系统实验实验报告一、实验目的掌握在GeekOS系统用户态模式下加载并运行可执行程序的方法。

二、实验要求1. 按照实验讲义P127页中的设计要求,实现在用户态模式下加载并运行可执行程序的代码,给出关键函数的代码以及实验结果。

三、实验过程及结果答:核心函数代码如下:================== user.c ===============//产生一个进程(用户态)int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread) {//TODO("Spawn a process by reading an executable from a filesystem");int rc;char *exeFileData = 0;ulong_t exeFileLength;struct User_Context *userContext = 0;struct Kernel_Thread *process = 0;struct Exe_Format exeFormat;if ((rc = Read_Fully(program, (void**) &exeFileData, &exeFileLength)) != 0 ){Print("Failed to Read File %s!\n", program);goto fail;}if((rc = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat)) != 0 ){Print("Failed to Parse ELF File!\n");goto fail;}if((rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext)) != 0){Print("Failed to Load User Program!\n");goto fail;}//在堆分配方式下释放内存并再次初始化exeFileDataFree(exeFileData);exeFileData = 0;/* 开始用户进程,调用Start_User_Thread函数创建一个进程并使其进入准备运行队列*/ process = Start_User_Thread(userContext, false);if (process != 0) {KASSERT(process->refCount == 2);/* 返回核心进程的指针*/*pThread = process;rc = process->pid;//记录当前进程的ID}elserc = ENOMEM;return rc;fail: //如果新进程创建失败则注销User_Context对象if (exeFileData != 0)Free(exeFileData);//释放内存if (userContext != 0)Destroy_User_Context(userContext);//销毁进程对象return rc;}-------------------------------------//切换至用户上下文void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state){static struct User_Context* s_currentUserContext; /* last user context used *///extern int userDebug;struct User_Context* userContext = kthread->userContext;KASSERT(!Interrupts_Enabled());if (userContext == 0) { //userContext为0表示此进程为核心态进程就不用切换地址空间return;}if (userContext != s_currentUserContext) {ulong_t esp0;//if (userDebug) Print("A[%p]\n", kthread);Switch_To_Address_Space(userContext);//为用户态进程时则切换地址空间esp0 = ((ulong_t) kthread->stackPage) + PAGE_SIZE;//if (userDebug)// Print("S[%lx]\n", esp0);/* 新进程的核心栈. */Set_Kernel_Stack_Pointer(esp0);//设置内核堆栈指针/* New user context is active */s_currentUserContext = userContext;}}================== elf.c ====================int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat){int i;elfHeader *head=(elfHeader*)exeFileData;programHeader *proHeader=(programHeader *)(exeFileData+head->phoff);KASSERT(exeFileData!=NULL);KASSERT(exeFileLength>head->ehsize+head->phentsize*head->phnum);KASSERT(head->entry%4==0);exeFormat->numSegments=head->phnum;exeFormat->entryAddr=head->entry;for(i=0;i<head->phnum;i++){exeFormat->segmentList[i].offsetInFile=proHeader->offset;exeFormat->segmentList[i].lengthInFile=proHeader->fileSize;exeFormat->segmentList[i].startAddress=proHeader->vaddr;exeFormat->segmentList[i].sizeInMemory=proHeader->memSize;exeFormat->segmentList[i].protFlags=proHeader->flags;proHeader++;}return 0;}=================== userseg.c ===================//需在此文件各函数前增加一个函数,此函数的功能是按给定的大小创建一个用户级进程上下文,具体实现如下://函数功能:按给定的大小创建一个用户级进程上下文static struct User_Context* Create_User_Context(ulong_t size){struct User_Context * UserContext;size = Round_Up_To_Page(size);UserContext = (struct User_Context *)Malloc(sizeof(struct User_Context));if (UserContext != 0)UserContext->memory = Malloc(size);//为核心态进程elsegoto fail;//内存为空if (0 == UserContext->memory)goto fail;memset(UserContext->memory, '\0', size);UserContext->size = size;//以下为用户态进程创建LDT(段描述符表)//新建一个LDT描述符UserContext->ldtDescriptor = Allocate_Segment_Descriptor();if (0 == UserContext->ldtDescriptor)goto fail;//初始化段描述符Init_LDT_Descriptor(UserContext->ldtDescriptor, UserContext->ldt, NUM_USER_LDT_ENTRIES);//新建一个LDT选择子UserContext->ldtSelector = Selector(KERNEL_PRIVILEGE, true, Get_Descriptor_Index(UserContext->ldtDescriptor));//新建一个文本段描述符Init_Code_Segment_Descriptor(&UserContext->ldt[0],(ulong_t) UserContext->memory,size / PAGE_SIZE,USER_PRIVILEGE);//新建一个数据段Init_Data_Segment_Descriptor(&UserContext->ldt[1],(ulong_t) UserContext->memory,size / PAGE_SIZE,USER_PRIVILEGE);//新建数据段和文本段选择子UserContext->csSelector = Selector(USER_PRIVILEGE, false, 0);UserContext->dsSelector = Selector(USER_PRIVILEGE, false, 1);//将引用数清0UserContext->refCount = 0;return UserContext;fail:if (UserContext != 0){if (UserContext->memory != 0){Free(UserContext->memory);}Free(UserContext);}return 0;}--------------------------------------------//摧毁用户上下文void Destroy_User_Context(struct User_Context* userContext){//TODO("Destroy a User_Context");//释放占用的LDTFree_Segment_Descriptor(userContext->ldtDescriptor);userContext->ldtDescriptor=0;//释放内存空间Free(userContext->memory);userContext->memory=0;//释放userContext本身占用的内存Free(userContext);userContext=0;}----------------------------------------------int Load_User_Program(char *exeFileData,ulong_t exeFileLength,struct Exe_Format *exeFormat,const char *command,struct User_Context **pUserContext){//TODO("Load a user executable into a user memory space using segmentation");int i;ulong_t maxva = 0;//要分配的最大内存空间unsigned numArgs;//进程数目ulong_t argBlockSize;//参数块的大小ulong_t size, argBlockAddr;//参数块地址struct User_Context *userContext = 0;//计算用户态进程所需的最大内存空间for (i = 0; i < exeFormat->numSegments; ++i) {//elf.hstruct Exe_Segment *segment = &exeFormat->segmentList[i];ulong_t topva = segment->startAddress + segment->sizeInMemory; /* FIXME: range check */if (topva > maxva)maxva = topva;}Get_Argument_Block_Size(command, &numArgs, &argBlockSize);//获取参数块信息size = Round_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE;argBlockAddr = size;size += argBlockSize;userContext = Create_User_Context(size);//按相应大小创建一个进程if (userContext == 0)//如果为核心态进程return -1;for (i = 0; i < exeFormat->numSegments; ++i) {struct Exe_Segment *segment = &exeFormat->segmentList[i];//根据段信息将用户程序中的各段内容复制到分配的用户内存空间memcpy(userContext->memory + segment->startAddress, exeFileData + segment->offsetInFile,segment->lengthInFile);}//格式化参数块Format_Argument_Block(userContext->memory + argBlockAddr, numArgs, argBlockAddr, command);//初始化数据段,堆栈段及代码段信息userContext->entryAddr = exeFormat->entryAddr;userContext->argBlockAddr = argBlockAddr;userContext->stackPointerAddr = argBlockAddr;//将初始化完毕的User_Context赋给*pUserContext*pUserContext = userContext;return 0;//成功}----------------------------------------------//将用户态的进程复制到内核缓冲区bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize){struct User_Context * UserContext = g_currentThread->userContext;//--: check if memory if validatedif (!Validate_User_Memory(UserContext,srcInUser, bufSize))return false;memcpy(destInKernel, UserContext->memory + srcInUser, bufSize);return true;}-----------------------------------------//将内核态的进程复制到用户态bool Copy_To_User(ulong_t destInUser, void* srcInKernel, ulong_t bufSize){struct User_Context * UserContext = g_currentThread->userContext;if (!Validate_User_Memory(UserContext, destInUser, bufSize))return false;memcpy(UserContext->memory + destInUser, srcInKernel, bufSize);return true;}----------------------------------------//切换到用户地址空间void Switch_To_Address_Space(struct User_Context *userContext){ushort_t ldtSelector= userContext->ldtSelector;/* Switch to the LDT of the new user context */__asm__ __volatile__ ("lldt %0"::"a"(ldtSelector));}================= kthread.c ===============添加头文件#include <geekos/user.h>----------------------------------//创建一个用户进程/*static*/ void Setup_User_Thread(struct Kernel_Thread* kthread, struct User_Context* userContext){ulong_t eflags = EFLAGS_IF;unsigned csSelector=userContext->csSelector;//CS选择子unsigned dsSelector=userContext->dsSelector;//DS选择子Attach_User_Context(kthread, userContext);//初始化用户态进程堆栈,使之看上去像刚被中断运行一样//分别调用Push函数将以下数据压入堆栈Push(kthread, dsSelector); //数据选择子Push(kthread, userContext->stackPointerAddr); //堆栈指针Push(kthread, eflags); //EflagsPush(kthread, csSelector); //文本选择子Push(kthread, userContext->entryAddr); //程序计数器Push(kthread, 0); //错误代码(0)Push(kthread, 0); //中断号(0)//初始化通用寄存单元,将ESI用户传递参数块地址Push(kthread, 0); /* eax */Push(kthread, 0); /* ebx */Push(kthread, 0); /* edx */Push(kthread, 0); /* edx */Push(kthread, userContext->argBlockAddr); /* esi */Push(kthread, 0); /* edi */Push(kthread, 0); /* ebp *///初始化数据段寄存单元Push(kthread, dsSelector); /* ds */Push(kthread, dsSelector); /* es */Push(kthread, dsSelector); /* fs */Push(kthread, dsSelector); /* gs */}//开始用户进程struct Kernel_Thread* Start_User_Thread(struct User_Context* userContext, bool detached) {struct Kernel_Thread* kthread = Create_Thread(PRIORITY_USER, detached);if (kthread != 0){Setup_User_Thread(kthread, userContext);Make_Runnable_Atomic(kthread);}return kthread;}================ syscall.c =================//需在此文件别的函数前增加一个函数,函数名为Copy_User_String,它被函数Sys_PrintString调用,具体实现如下:static int Copy_User_String(ulong_t uaddr, ulong_t len, ulong_t maxLen, char **pStr) { int rc = 0;char *str;if (len > maxLen){ //超过最大长度return EINV ALID;}str = (char*) Malloc(len+1); //为字符串分配空间if (0 == str){rc = ENOMEM;goto fail;}if (!Copy_From_User(str, uaddr, len)){ //从用户空间中复制数据rc = EINV ALID;Free(str);goto fail;}str[len] = '\0';//成功*pStr = str;fail:return rc;}-----------------------------------------static int Sys_Exit(struct Interrupt_State* state){Exit(state->ebx);}-----------------------------------------static int Sys_PrintString(struct Interrupt_State* state){int rc = 0;//返回值uint_t length = state->ecx;//字符串长度uchar_t* buf = 0;if (length > 0) {if ((rc = Copy_User_String(state->ebx, length, 1023, (char**) &buf)) != 0) goto done;Put_Buf(buf, length);}done:if (buf != 0)Free(buf);return rc;}----------------------------------------------static int Sys_GetKey(struct Interrupt_State* state){return Wait_For_Key(); //返回按键码keyboard.c/Wait_For_Key()}---------------------------------------------static int Sys_SetAttr(struct Interrupt_State* state){Set_Current_Attr((uchar_t) state->ebx);return 0;}---------------------------------------------static int Sys_GetCursor(struct Interrupt_State* state){int row, col;Get_Cursor(&row, &col);if (!Copy_To_User(state->ebx, &row, sizeof(int)) ||!Copy_To_User(state->ecx, &col, sizeof(int)))return -1;return 0;}-----------------------------------------------static int Sys_PutCursor(struct Interrupt_State* state){return Put_Cursor(state->ebx, state->ecx) ? 0 : -1;}-----------------------------------------------static int Sys_Spawn(struct Interrupt_State* state){int rc; //函数返回值char *program = 0; //进程名称char *command = 0; //用户命令struct Kernel_Thread *process;if ((rc = Copy_User_String(state->ebx, state->ecx, VFS_MAX_PATH_LEN, &program)) != 0){goto fail;}if(rc = Copy_User_String(state->edx, state->esi, 1023, &command)) != 0){//从用户空间复制用户命令goto fail;}Enable_Interrupts(); //开中断rc = Spawn(program, command, &process);//得到进程名称和用户命令后便可生成一个新进程if (rc == 0) {//若成功则返回新进程ID号KASSERT(process != 0);rc = process->pid;}Disable_Interrupts();//关中断fail://返回小于0的错误代码if (program != 0)Free(program);if (command != 0)Free(command);return rc;}-----------------------------------------static int Sys_Wait(struct Interrupt_State* state){ //TODO("Wait system call");int exitCode;struct Kernel_Thread *kthread = Lookup_Thread(state->ebx);if (kthread == 0)return -12;Enable_Interrupts();exitCode = Join(kthread);Disable_Interrupts();return exitCode;}---------------------------------------static int Sys_GetPID(struct Interrupt_State* state){ //TODO("GetPID system call");return g_currentThread->pid;}================= main.c ==================static void Spawn_Init_Process(void){ //TODO("Spawn the init process");struct Kernel_Thread *pThread;Spawn("/c/shell.exe","/c/shell.exe",&pThread);}实验结果如图所示:原理:Geekos 提供了一个简单的shell,保存在PFAT文件系统内,所以geekos 系统启动后,启动shell程序/c/shell.exe运行,将/c/shell.exe作为可执行文件传递给spawn函数的program参数,创建第一个用户态进程,然后由它来创建其他进程。

西工大 操作系统实验报告

西工大 操作系统实验报告

西工大操作系统实验报告西工大操作系统实验报告一、引言操作系统是计算机系统中最重要的软件之一,它负责管理计算机硬件和软件资源,为用户提供一个友好、高效的计算环境。

本次实验旨在通过实践操作系统的基本功能和原理,加深对操作系统的理解和掌握。

二、实验目的1. 理解操作系统的基本概念和作用;2. 学习操作系统的安装和配置;3. 掌握操作系统的文件管理和进程管理;4. 实践操作系统的调度算法和内存管理;5. 深入理解操作系统的并发控制和死锁处理。

三、实验环境本次实验使用的操作系统是Linux,具体版本为Ubuntu 20.04 LTS。

实验所需的软件和工具包括GCC编译器、Make工具、Vi编辑器等。

四、实验内容1. 操作系统的安装和配置首先,我们需要下载Ubuntu 20.04 LTS的镜像文件,并通过虚拟机软件创建一个虚拟机。

然后,按照提示进行操作系统的安装和配置,包括选择安装语言、分配磁盘空间、设置用户名和密码等。

安装完成后,我们可以登录系统,并进行一些基本设置,如修改主题、安装常用软件等。

2. 文件管理和进程管理操作系统的文件管理是指对计算机中的文件进行组织、存储和访问的过程。

我们可以使用命令行或图形界面来管理文件,包括创建文件、复制文件、删除文件等。

同时,操作系统还提供了进程管理的功能,可以管理计算机中运行的各个进程。

我们可以使用命令行或系统监视器来查看和管理进程,包括启动进程、终止进程、调整进程优先级等。

3. 调度算法和内存管理操作系统的调度算法是指决定哪个进程在何时执行的算法。

常见的调度算法包括先来先服务、短作业优先、轮转调度等。

我们可以通过修改系统的调度策略来改变进程的执行顺序。

另外,操作系统还负责管理计算机的内存资源,包括内存分配、内存回收等。

我们可以使用命令行或系统监视器来查看和管理内存,包括查看内存使用情况、释放内存空间等。

4. 并发控制和死锁处理操作系统需要保证多个进程之间的并发执行,同时又要避免出现竞争条件和死锁等问题。

西北工业大学-操作系统实验报告-实验二

西北工业大学-操作系统实验报告-实验二

实验二FreeBSD的应用软件安装一、实验目的学习如何使用FreeBSD安装应用软件。

二、实验内容与要求1、查阅资料,了解FreeBSD 安装软件的主要方式,每种方式的具体步骤、操作指南;2、学习使用FreeBSD安装方法的一种进行安装简单的SSH;3、详细记录探索学习的内容和实验的整个过程,包括资料的查询、资料的来源(资料名称、网址等)、所做的各种尝试、以及最终的结果(包含截屏);三、实验过程1、FreeBSD 安装软件的主要方式(1).package用 package 安装,只要抓取该程序 package 档案,简单的透过 --> 安装pkg_add package_name --> 移除 pkg_delete package_name就可以完成安装 / 移除。

注意:文件名称 .tgz 结尾的是 package 文件名称 .tar.gz 结尾的是 source 注 : 目前已经安装的 package 数据库放在 /var/db/pkg/ 这个数据夹之中。

通常在比较大型的套件(需要编译很久)或是老是无法编译成功以及想先快速了解未使用过的套件是长成什么样子时,我们会采用这种方式来安装套件。

(2)port如果你要使用 ports 安装软件,你必须先确认 /usr/ports 这个目录是否有安装。

如果没有的话,使用 /stand/sysinstall 来安装 ports 的目录:1. 以 root 执行 /stand/sysinstall2. 选择 Configure 后按 Enter3. 选择 Distributions 后按 Enter4. 选择 ports 后按空格键5. 选择 Exit 后按 Enter6. 选择你要从 CDROM 或 FTP 安装等7. 跟着选单照做,最后离开 sysinstall或者我们也可以到 /ports/ 去手动抓回 port.tar.gz 这个档案,将它放在 /usr/ 下。

[西北工业大学]计算机操作系统(202104)

[西北工业大学]计算机操作系统(202104)
14.操作系统是为了提高计算机的()和方便用户使用计算机而配置的基本软件。
A.速度 B.利用率 C.灵活性 D.兼容性 答案:B
15.引入多道程序的目的在于()。 A.充分利用CPU,减少CPU等待时间 B.提高实时响应速度 C.有利于代码共享,减少主、辅存信息交换量 D.充分利用存储器 答案:A
24.可采用静态地址重定位技术进行存储管理的有()。 A.单一分区管理、固定分区管理、可变分区管理 B.单一分区管理、固定分区管理、段式存储管理 C.可变分区管理、页式存储管理、段式存储管理 D.单一分区管理、页式存储管理、段式存储管理 答案:A
25.引入多道程序技术后,处理机的利用率()。 A.降低了 B.有所改善 C.大大提高 D.没有变化,只是程序的执行方便了 答案:C
9.用户在一次计算过程中,或者一次事物处理中,要求计算机完成所做的工作的集合,这是指()。 A.进程 B.程序 C.作业 D.系统调用 答案:C
10.在可变式分区分配方案中,某一作业完成后,系统收回其主存空间,并与相邻空闲区合并,为此 需修改空闲区表,造成空闲区表项数减1的情况是()。 A.无上邻(前邻、低址)空闲区,也无下邻(后邻、高址)空闲区 B.有上邻(前邻、低址)空闲区,但无下邻(后邻、高址)空闲区 C.有下邻(后邻、高址)空闲区,但无上邻(前邻、低址)空闲区 D.有上邻(前邻、低址)空闲区,也有下邻(后邻、高址)空闲区 答案:D
11.进程从运行状态变为阻塞状态的原因是()。 A.输入或输出事件发生 B.时间片到 C.输入或输出事件完成 D.某个进程被唤醒 答案:A
12.()的主要目标是提高系统的吞吐量和效率。 A.实时操作系统 B.多道批处理系统 C.分时操作系统 D.微机操作系统 答案:B
13.操作系统是一种()。 A.应用软件 B.系统软件 C.通用软件 D.工具软件 答案:B

北理操作系统实验三

北理操作系统实验三

操作系统课程设计实验报告实验名称:生产者消费者问题姓名/学号:一.实验目的1.学习掌握操作系统中进程之间的通信2.理解掌握使用信号量机制来多进程互斥访问共享内存区的控制3.学习进程的创建及控制,共享内存区的创建和删除,信号量的创建使用删除二.实验内容•一个大小为3的缓冲区,初始为空,每个缓冲区能存放一个长度若为10个字符的字符串。

•2个生产者–随机等待一段时间,往缓冲区添加数据,–若缓冲区已满,等待消费者取走数据后再添加–重复6次•3个消费者–随机等待一段时间,从缓冲区读取数据–若缓冲区为空,等待生产者添加数据后再读取–重复4次说明:•显示每次添加和读取数据的时间及缓冲区的状态•生产者和消费者用进程模拟,缓冲区用共享内存来实现三.实验环境VMware Fushion8:Windows和ubuntu14.10四.程序设计与实现1、Windows下:A:主要函数说明1.PROCESS_INFORMATION StartClone(int nCloneID)功能:创建一个克隆的进程并赋于其ID值,并返回进程和线程信息2.CreateProcess:创建进程3.CreateSemaphore():创建信号量4.CreateFileMapping():在当前运行的进程中创建文件映射对象,模拟共享内存区5.MapViewOfFile():在此文件映射基础上创建视图映射到当前应用程序的地址空间B:程序流程图(下图)C:实验结果:2、Linux下:A:主要函数说明1.void(p):申请缓冲区2.void(v):释放缓冲区3.shmget():用来获得共享内存区域的ID,如果不存在这个内存区,就创建这个共享内存区。

4.semget():返回信号量集的Id,如果不存在就创建这个信号量集B:程序流程图C:实验结果五. 实验收获与体会1、进一步熟悉了Windows 、Linux 中进程的创建与管理2、掌握了WINDOWS 和Linux 下进程之间的通信:Windows 主要在于句柄的获取并用于API 函数的调用,并利用文件映射创建共享缓冲区;Linux 主要使用信号量机制和相关API的调用。

北方工业大学计算机操作系统实验1

北方工业大学计算机操作系统实验1

操作系统实验报告学生姓名杨先宇学号班级计13-42.进程控制:#include<stdio.h>main(){int p1,p2,i;while((p1=fork())==-1);if(p1==0){lockf(1,1,0);//锁定屏幕输出进行进程互斥for(i=0;i<5;i++)printf("child %d \n",i);lockf(1,0,0);}//解锁else{while((p2=fork())==-1);if(p2==0){lockf(1,1,0);for(i=0;i<5;i++)printf("son %d\n",i);lockf(1,0,0);}else{lockf(1,1,0);for(i=0;i<5;i++)printf("daughter %d \n",i);lockf(1,1,0);}}}3软中断:#include<unistd.h>#include<stdio.h>#include<signal.h>#include<stdlib.h>int wait_mark;void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}main(){int p1,p2;void waiting(),stop();while((p1=fork())==-1);if(p1>0){while((p2=fork())==-1);if(p2>0){printf("child process 1 is killed by parent!\n");wait_mark=1;signal(SIGINT,stop);waiting(0);kill(p1,16);kill(p2,17);wait(0);wait(0);printf(" \n");exit(0);}else{printf("child process 2 is killed by parent!\n");wait_mark=1;signal(SIGINT,SIG_IGN);signal(17,stop);waiting();lockf(1,1,0);printf("\n");lockf(1,0,0);exit(0);}}else{printf("parent process is killed!\n");wait_mark=1;signal(SIGINT,SIG_IGN);signal(16,stop);waiting();lockf(1,1,0);printf("parent process is killed! \n");lockf(1,0,0);exit(0);}}4管道通信:#include<stdio.h>#include<sys/types.h>#include<unistd.h>#include<string.h>}else{printf("Pipe error!");exit(0);}}六、实验结果与分析1.1.进程的创建运行结果:acb,abc.cab等都有可能,父进程与子进程的输出内容会叠加在一起,输出次序带有随机性。

西北工业大学-操作系统实验报告-实验五

西北工业大学-操作系统实验报告-实验五

实验五进程管理一、实验目的(1)加深对进程概念的理解,明确进程和程序的区别;(2)进一步认识并发执行的实质;(3)了解FreeBSD系统中进程通信的基本原理。

二、实验内容与要求1、掌握进程的概念,明确进程的含义;2、编写一段程序,使用系统调用fork( )创建两个子进程。

当此程序运行时,在系统中有一个父进程和两个子进程活动。

让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。

试观察记录屏幕上的显示结果(多次运行,查看结果是否有变化),并分析原因;3、修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,在观察程序执行时屏幕出现的现象(多次运行,查看结果是否有变化),并分析原因;4、如果在程序中使用调用lockf()来给每一个子进程加锁,可以实现进程之间的互斥,观察并分析出现的现象;5、对整个实验过程进行分析总结,给出详细步骤;三、实验过程1、进程的概念与含义狭义:进程就是一段程序的执行过程。

广义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。

它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

进程的概念主要有两点:第一,进程是一个实体。

每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。

文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。

第二,进程是一个“执行中的程序”。

程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。

进程是操作系统中最基本、重要的概念。

是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。

西北工业大学信号与系统实验五

西北工业大学信号与系统实验五
end
if abs(H-302)<5
t=1;
elseif abs(H-334)<5
t=2;
elseif abs(H-369)<5
t=3;
end
s=[s hm(r,t)];
while (ph(k)~=0)&(ph(k+1)~=0)
k=k+1;
end
k=k+1;
end
s
附3、键0对应的双音信号时域波形和频谱图:
三、实验设备(环境)
操作系统:Win10
系统内存:8GB
MATLAB版本:R2014a
四、实验内容与步骤
5.1计算dtft的样本
基本题:
(1)问题描述与分析
题目中要求使用解析方法计算矩形脉冲的DTFT,通过计算可以得出X=(1-exp(-1*j*w*10)).*1./(1-exp(-1*j*w));转换后,画出频谱图的幅值图和相位图;用fftshift对DTFT进行重新排列,再次画出X对w的幅值和相位
clearall;clc;
num=[0,-1,1];
den=[1,-5,6];
[r,p,k]=residue(num,den)
(d)
clearall;clc;
a=[6,-5,1];
b=[1,-1,0];
x=[1 0 0 0 0 0 0 0 0 0 0];
y=filter(b,a,x)
五、实验结果
见上题
六、实验分析与讨论
掌握了离散时间傅里叶变换的综合公式和分析公式,并且对离散时间傅里叶变换有了更深刻的认识
教师评语:
签名:
日期:
成绩:
plot(n,h);
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

评语: 课中检查完成的题号及题数:课后完成的题号与题数:成绩: 指导教师:实验报告三实验名称:七、八日期:2013.05.23 班级:10011007 学号:2010302555 姓名:杨宏志实验七理解线程的相关概念1. 实验目的理解当操作系统引入线程的概念后,进程是操作系统独立分配资源的单位,线程成为系统调度的单位,与同一个进程中的其他线程共享程序空间。

2. 实验预习内容预习线程创建和构造的相关知识,了解C语言程序编写的相关知识。

3. 实验内容及步骤(1)编写一个程序,在其main()函数中创建一个(或多个)线程,观察该线程是如何与主线程并发运行的。

输出每次操作后的结果;(2)在main()函数外定义一个变量shared(全局变量),在main()中创建一个线程,在main()中和新线程shared 进行循环加/减操作,观察该变量的变化;(3)修改程序把shared 变量定义到main()函数之内,重复第(2)步操作,观察该变量的变化。

4. 实验总结(1) 观察上述程序执行结果,并分析原因;(2) 提交源程序清单,并附加流程图与注释。

思考:分析进程和线程的不同之处。

5. 具体实现1)观察线程并发性:#include <stdio.h>#include <unistd.h>#include <pthread.h>void * func(void *params){while(1){printf("i am the thread 2\n");sleep(1);}return NULL;}int main(){pthread_t tid;int res=pthread_create(&tid, NULL,func,NULL);while(1){printf("i am main thread\n");sleep(1);}return 0;}2)全局变量共享#include <stdio.h>#include <unistd.h>#include <pthread.h>int shared=0;void * func(void *params){while(1){shared--;printf("i am thread2 shared=%d\n",shared);sleep(1);}return NULL;}int main(){pthread_t tid;int res=pthread_create(&tid, NULL,func,NULL);while(1){shared++;printf("i am main thread shared=%d\n",shared);sleep(1);}return 0;}3)局部变量,指针传参#include <stdio.h>#include <unistd.h>#include <pthread.h>void * func(void *params){while(1){printf("i am thread2 shared=%d\n",*(int *)params);(*(int *)params)--;sleep(1);}return NULL;}int main(){pthread_t tid;int shared=0;int res=pthread_create(&tid, NULL,func,(void *)(&shared));while(1){shared++;printf("i am main thread shared=%d\n",shared);sleep(1);}return 0;}实验八请求分页存储管理设计1. 实验目的模拟存储管理常用的请求分页存储管理技术,通过本实验使学生更加深入的理解虚拟内存的思想和主要的页面淘汰算法。

2. 实验预习内容学习虚拟存储器的相关基础知识,了解请求分页存储管理系统的原理和具体实现过程,熟悉各种主要的页面调度算法。

3. 实验内容及步骤(1) 通过随机数产生一个指令行列,共320条指令,指令中的地址按下述原则生成:50%的指令是顺序执行;25%的指令均匀分布在前地址部分;25%的指令均匀分布在后地址部分。

(2) 具体实验办法是:在[0,319]之间选一起始点M;顺序执行一条指令,即第M+1条;向前地址[0,M-1]中执行一条指令M;顺序执行一条指令,即第M+1条;向后地址[M+2,319]中执行一条指令M。

如此继续,直至产生320条指令。

使用产生随机数的函数之前,首先要初始化设置RAN()产生序列的开始点,SRAND(400);然后计算随机数,产生指令序列。

例如:a[0]=1.0*rand()/32767*319+1;a[1]=a[0]+1;a[2]=1.0*rand()/32767*(a[1]-1)+1;a[3]=a[2]+1;a[4]=319-1.0*rand()/32767*(a[3]-1);其中rand()和srand()为Linux操作系统提供的函数分别进行初始化和产生随机数,多次重复使用这5条指令,产生以后的指令序列。

(3) 将指令序列变换成页面地址流:假设,页面大小为1KB;用户实存容量(内存区容量)为4页或32页;用户虚存容量(逻辑地址空间容量)为32KB;用户虚存容量32KB,每1KB中放10条指令,共320条指令序列,按其地址0~9在0页,10~19在1页,…….,310~319在31页。

(4) 使用不同的页面调度算法处理缺页中断,并计算不同实存容量下的命中率:先进先出(FIFO)算法;最近最少使用(LRU)算法;命中率的算法为:命中率= 1 - (缺页中断次数/页地址流长度)。

本实验中,页地址流长度为320,缺页中断次数为每次访问相应指令时,该指令所对应的页不在内存的次数。

4. 实验总结(1) 编制的各程序采用的数据结构及符号说明,提交源程序清单,并附加流程图与注释;(2) 打印页表,对不同算法打印每次调出和装入的页面号,执行最后一条指令后在主存中页面号;(3) 根据实验结果分析并比较不同淘汰算法对不同实存容量的命中率,进而作出评价。

5.具体实现Fifo使用循环队列实现#include<stdio.h>#include<time.h>#include<stdlib.h>#define HARD_NUM 4#define INSTRUCT 320#define VIRTUAL_NUM 32int instruct[INSTRUCT]={0}; typedef struct{int id;//虚存idbool flag;//是否装入int count;//最近使用次数}HM;typedef struct{HM hm[HARD_NUM+1];int head;int tail;}FIFO;typedef struct{HM hm[HARD_NUM];}LRU;FIFO fifo;LRU lru;void init();void fifoTest();bool isInFifo(int page);void lruTest();int main(){init();printf("先进先出fifo...\n");fifoTest();printf("\n\n");printf("最近最少使用fifo...\n");lruTest();system("pause");return 0;}void init(){int i,j;srand(time(0));for(i=0; i<INSTRUCT; i+=5){instruct[i] = 1.0 * rand() / RAND_MAX * 320;instruct[i+1] = instruct[i] + 1;instruct[i+2] = 1.0 *rand() / RAND_MAX * instruct[i];instruct[i+3] = instruct[i+2] + 1;instruct[i+4] = 319 - 1.0 *rand() / RAND_MAX * instruct[i+3];}}void fifoTest(){int i,j;int lack=0;//缺页次数//内存初始化for(i=0; i<HARD_NUM; i++){fifo.hm[i].id=0;fifo.hm[i].flag=false;fifo.hm[i].count=0;}//模拟执行320条指令for(i=0; i<INSTRUCT; i++){//计算该指令在那一页,判断是否在FIFO中int page = instruct[i] % VIRTUAL_NUM;bool isIn =isInFifo(page);if(isIn)//在实存中{printf("%d alread in fifo\n",instruct[i]);}else//缺页,插入队列{lack ++;if((fifo.tail + 1)%(HARD_NUM+1) == fifo.head)//队列已满{printf("page %d in,page %dout\n",page,fifo.hm[fifo.head].id);fifo.hm[fifo.head].id = page;fifo.tail =fifo.head;fifo.head = (fifo.head + 1) %(HARD_NUM+1);}else{printf("page %d in\n",page);fifo.hm[fifo.tail].id = page;fifo.hm[fifo.tail].flag = true;fifo.tail = (fifo.tail+1) %(HARD_NUM+1);}}}printf("缺页次数:%d\n",lack);printf("命中:%lf\n",1.0 - 1.0 * lack / INSTRUCT);}bool isInFifo(int page){int cur=fifo.head;if( cur ==fifo.tail)//队列为空return false;while(1){if( cur % (HARD_NUM+1) ==fifo.tail)//已经到队列尾break;if(page == fifo.hm[cur].id && fifo.hm[cur].flag == true) return true;cur++;}return false;}void lruTest(){int i,j;int lack=0;//缺页次数//内存初始化for(i=0; i<HARD_NUM; i++){lru.hm[i].id=0;lru.hm[i].flag=false;lru.hm[i].count=0;}//模拟执行320条指令for(i=0; i<INSTRUCT; i++){//计算该指令在那一页,判断是否在实存中int page = instruct[i] % VIRTUAL_NUM;bool isIn=false;for(j=0; j < HARD_NUM; j++)if(lru.hm[j].id==page && lru.hm[j].flag ==true){isIn=true;lru.hm[j].count ++;}if(isIn)printf("%d alread in...\n",page);else{lack++;//查找最近最少使用的项int cur=0,count=INT_MAX;for(j=0; j < HARD_NUM; j++){if(lru.hm[j].count < count){cur = j;count = lru.hm[j].count;}}if(lru.hm[cur].flag ==false){printf("page %d in\n",page);lru.hm[cur].flag =true;}elseprintf("page %d in,page %dout\n",page,lru.hm[cur].id);lru.hm[cur].id=page;lru.hm[cur].count ++;}}printf("缺页次数:%d\n",lack);printf("命中:%lf\n",1.0 - 1.0 * lack / INSTRUCT);}实验结果:实存为4kb,4个页面结果:(仅打印结果)实存为10Kb,10个页面结果:由以上结果可以看出,最近最少使用算法lru效果比先进先出fifo要好的多,平均超过2倍的性能。

相关文档
最新文档