操作系统实验 订阅
《操作系统实验》是2004年中央电大出版社出版的图书,作者是孟庆昌。 展开全文
《操作系统实验》是2004年中央电大出版社出版的图书,作者是孟庆昌。
信息
页    数
93
作    者
孟庆昌
定    价
12.00元
书    名
操作系统实验
出版时间
2004-7
出版社
中央电大
副标题
操作系统实验
ISBN
9787304018801
接单内容简介
内容介绍《计算机应用专业系列教材·操作系统实验》以SCO UNIX为例介绍了操作系统的安装和使用,通过指导读者上机实验,使读者既加深对操作系统概念的理解,又学会对UNIX系统的一般使用。全书共分九章,内容包括:UNIX系统安装,SCO UNIX图形界面,用户帐户建立,vi使用,进程管理,存储器管理,文件系统,设备管理和简单shell编程。《计算机应用专业系列教材·操作系统实验》是中央电大的实验教材,同时也可作为广大UNIX初学者的指导书。 [1] 
收起全文
精华内容
下载资源
问答
  • 操作系统实验
    千次阅读
    2021-12-21 17:43:30

    操作系统实验五–存储管理

    一、实验目的

    1、了解虚拟存储技术的特点,掌握请求页式存储管理的主要页面置换算法原理。

    2、掌握请求页式存储管理中页面置换算法的模拟设计方法。

    二、实验内容

    设计一个虚拟存储区和内存工作区,并使用下述方法计算访问命中率。

    ①先进先出的算法(FIFO);

    ②最近最少少使用算法(LRR);

    ③最佳淘汰算法(OPT):选淘汰最不常用的页地址;

    ④最少访问页面算法(LFR);

    ⑤最近最不经常使用算法(NUR).

    (其中③④为选择内容)

    ​ 命中率= 1 - 页面失效次数 / 页地址流长度

    三、设计原理及相关算法

    1、通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成:

    ​ ①50%的指令是顺序执行的;

    ​ ②25%的指令是均匀分布在前地址部分;

    ​ ③25%的指令是均匀分布在后地址部分。

    ​ 具体的实施方法是:

    ​ ①在[1,319]指令地址之间随机选取一起点m;

    ​ ②顺序执行一条指令,即执行地址为m十1的指令;

    ​ ③在前地址[0,m十1]中随机选取一条指令并执行,该指令的地址为 m’;

    ​ ④顺序执行一条指令,其地址为m‘+1;

    ​ ⑤在后地址[m’+2,319]中随机选取一条指令并执行;

    ​ ③重复上述步骤①~⑤,直到执行320次指令。

    2、将指令序列变换成为页地址流

     设:①页面大小为IK;
    

    ​ ②用户内存容量为4页到32页;

    ​ ③用户虚存容量为32K。

     在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方
    

    式为:

    第0条~第9条指令为第0页(对应虚存地址为[0,9]);

    第10条~第19条指令为第1页(对应虚存地址为[10,19]);

    第 310条~第 319条指令为第 31页(对应虚存地址为[310,319])。

    按以上方式,用户指令可组成32页。

    四、结果分析

    image-20211221174054132

    五、源代码

    //1.存储管理。
    #define TRUE 1
    #define FALSE 0
    #define INVALID -1
    #define NULL  0
    #define  total_instruction 320     /*指令流长*/
    #define  total_vp  32               /*虚页长*/
    #define  clear_period  50           /*清0周期*/
     
    typedef struct                      /*页面结构*/
    {
    	int pn;      //页号 logic number
    	int pfn;     //页面框架号 physical frame number
    	int counter; //计数器
    	int time;    //时间
    }pl_type;
     
    pl_type pl[total_vp];                      /*页面线性结构---指令序列需要使用地址*/
     
    typedef struct pfc_struct                  /*页面控制结构,调度算法的控制结构*/
    {                          
        int pn;
    	int pfn;
    	struct pfc_struct *next;
    }pfc_type;
     
     
    pfc_type pfc[total_vp], *freepf_head, *busypf_head, *busypf_tail;
     
    int diseffect,  a[total_instruction]; /* a[]为指令序列*/
     
    int page[total_instruction],  offset[total_instruction];/*地址信息*/
     
    int  initialize(int);
    int  FIFO(int);
    int  LRU(int);
    int  LFU(int);
    int  NUR(int); //not use recently
    int  OPT(int);
     
    int main( )
    {
    	int s,i,j;
     
    	srand(10*getpid());                    /*由于每次运行时进程号不同,故可用来作为初始化随机数队列的“种子”*/
     
    	s=(float)319*rand( )/32767/32767/2+1;  /*正态分布*/
     
    	for(i=0;i<total_instruction;i+=4)        /*产生指令队列*/
    	{
    		if(s<0||s>319)
    		{
    			printf("When i==%d,Error,s==%d\n",i,s);
    			exit(0);
    		} 
    		a[i]=s;                                   /*任选一指令访问点m*/
    		a[i+1]=a[i]+1;                            /*顺序执行一条指令*/
    		a[i+2]=(float)a[i]*rand( )/32767/32767/2; /*执行前地址指令m*/
    		a[i+3]=a[i+2]+1;                          /*顺序执行一条指令*/
     
    		s=(float)(318-a[i+2])*rand( )/32767/32767/2+a[i+2]+2;
    		if((a[i+2]>318)||(s>319))
     
    			printf("a[%d+2],a number which is :%d and s==%d\n",i,a[i+2],s);
     
    	}
    	for (i=0;i<total_instruction;i++) /*将指令序列变换成页地址流*/
    	{
    		page[i]=a[i]/10;
    		offset[i]=a[i]%10;
    	}
    	for(i=4;i<=32;i++)   /*用户内存工作区从4个页面到32个页面*/
    	{
    		printf("--%2d page frames   ",i);
    		FIFO(i);
    		LRU(i);
    		LFU(i);
    		NUR(i);
    		OPT(i);
    		
    	}
    	return 0;
    }
     
    /*初始化相关数据结构 total_pf表示内存的块数 */
     
    int initialize(int total_pf)             
    {
    	int i;
    	diseffect=0;
    	for(i=0;i<total_vp;i++)
    	{
     
    		pl[i].pfn=INVALID;       /*置页面控制结构中的页号,页面为空*/
    		pl[i].counter=0;         /*页面控制结构中的访问次数为0*/
    		pl[i].time=-1;           /*访问的时间*/
    	}
     
    	for(i=0;i<total_pf-1;i++)	/*建立pfc[i-1]和pfc[i]之间的链接*/
    	{	
    		pfc[i].next=&pfc[i+1];
    		pfc[i].pfn=i;
    	}   
     
    	pfc[total_pf-1].next=NULL;
    	pfc[total_pf-1].pfn=total_pf-1;
    	freepf_head=&pfc[0];         /*空页面队列的头指针为pfc[0]*/
    	return 0;
    }
     
    int FIFO(int total_pf)              /*先进先出算法total_pf:用户进程的内存页面数*/
    {
    	int i,j;
    	pfc_type *p;					/*中间变量*/
    	initialize(total_pf);         /*初始化相关页面控制用数据结构*/
    	busypf_head=busypf_tail=NULL; /*忙页面队列头,队列尾链接*/
    	for(i=0;i<total_instruction;i++)
    	{
    		if(pl[page[i]].pfn==INVALID)   /*页面失效*/
    		{
    			diseffect+=1;                  /*失效次数*/
    			if(freepf_head==NULL)         /*无空闲页面*/
    			{
    				p=busypf_head->next;       
    				pl[busypf_head->pn].pfn=INVALID;
    				freepf_head=busypf_head;  /*释放忙页面队列的第一个页面*/
    				freepf_head->next=NULL;  /*表明还是缺页*/
    				busypf_head=p;
    			}
    			p=freepf_head->next;        
    			freepf_head->pn=page[i];
    			pl[page[i]].pfn=freepf_head->pfn;
    			freepf_head->next=NULL; /*使busy的尾为null*/
    			if(busypf_tail==NULL)
    			{
    				busypf_tail=busypf_head=freepf_head;
    			}
    			else
    			{
    				busypf_tail->next=freepf_head;
    				busypf_tail=freepf_head;
    			}
    			freepf_head=p;
    		}
    	}
    	printf("FIFO:%6.4f  ",1-(float)diseffect/320);
    	return 0;
    }
    int LRU (int total_pf)       /*最近最久未使用算法least recently used*/
    {
    	int min,minj,i,j,present_time; /*minj为最小值下标*/
    	initialize(total_pf);
    	present_time=0;
    	for(i=0;i<total_instruction;i++)
    	{
    		if(pl[page[i]].pfn==INVALID)             /*页面失效*/
    		{
    			diseffect++;
    			if(freepf_head==NULL)              /*无空闲页面*/
    			{
    				min=32767;						/*设置最大值*/
    				for(j=0;j<total_vp;j++)            /*找出time的最小值*/
    				{ 
    					if(min>pl[j].time&&pl[j].pfn!=INVALID)
    					{
    						min=pl[j].time;
    						minj=j;
    					}
    				}
    				freepf_head=&pfc[pl[minj].pfn];   //腾出一个单元
    				pl[minj].pfn=INVALID;
    				pl[minj].time=0;
    				freepf_head->next=NULL;
    			}
    			pl[page[i]].pfn=freepf_head->pfn;   //有空闲页面,改为有效
    			pl[page[i]].time=present_time;
    			freepf_head=freepf_head->next;      //减少一个free 页面
    		}
    		else
    		{
    			pl[page[i]].time=present_time;        //命中则增加该单元的访问次数
    			present_time++;
    		}
    	}
    	printf("LRU:%6.4f  ",1-(float)diseffect/320);
    	return 0;
    }
     
    int NUR(int  total_pf )                  /*最近未使用算法Not Used recently count表示*/
    { 
    int i,j,dp,cont_flag,old_dp;
    pfc_type *t;
    initialize(total_pf);
    dp=0;
     
    for(i=0;i<total_instruction;i++)
    { 
    	if (pl[page[i]].pfn==INVALID)         /*页面失效*/
    	{
    		diseffect++;
    		if(freepf_head==NULL)               /*无空闲页面*/
    		{ 
    			cont_flag=TRUE;
    			old_dp=dp;
    			
    			while(cont_flag)
    			{
    				
    			   if(pl[dp].counter==0&&pl[dp].pfn!=INVALID)
    					cont_flag=FALSE;
    				else
    				{
    					dp++;
    					if(dp==total_vp)
    						dp=0;
    					if(dp==old_dp)
    						for(j=0;j<total_vp;j++)
    						 pl[j].counter=0;
    				}
    			}
    			freepf_head=&pfc[pl[dp].pfn];
    			pl[dp].pfn=INVALID;
    			freepf_head->next=NULL;
    		}
    		
    		pl[page[i]].pfn=freepf_head->pfn;
    		
    		freepf_head->pn=page[i];
    		
    		freepf_head=freepf_head->next;
    	}
    	else
    		pl[page[i]].counter=1;
    	if(i%clear_period==0)
    		for(j=0;j<total_vp;j++)
    			pl[j].counter=0;
    }
    printf("NUR:%6.4f  ",1-(float)diseffect/320);
    return 0;
    }
     
    int OPT(int total_pf)       /*最佳置换算法*/
    {
    	int i,j, max,maxpage,d,dist[total_vp];
    	pfc_type *t;
    	initialize(total_pf);
    	for(i=0;i<total_instruction;i++)
    	{ 
    		if(pl[page[i]].pfn==INVALID)      /*页面失效*/
    		{
    			diseffect++;
    			if(freepf_head==NULL)         /*无空闲页面*/
    			{
    				for(j=0;j<total_vp;j++)
    				{
    					if(pl[j].pfn!=INVALID)
    						dist[j]=32767;
    					else
    						dist[j]=0;	 
    				}
    				for(j=0;j<total_vp;j++)	       
    				{
    					if((pl[j].pfn!=INVALID)&&(dist[j]==32767))
    					{
    						dist[j]=j;
    					}
    				}
    				max=0;
    				for(j=0;j<total_vp;j++)
    					if(max<dist[j])
    					{
    						max=dist[j];
    						maxpage=j;
    					}
    					freepf_head=&pfc[pl[maxpage].pfn];
    					freepf_head->next=NULL;
    					pl[maxpage].pfn=INVALID;
    			}
    			pl[page[i]].pfn=freepf_head->pfn;
    			freepf_head=freepf_head->next;
    		}
    	}
    	printf("OPT:%6.4f\n",1-(float)diseffect/320);
    	return 0;
    }
    /*该算法时根据已知的预测未知的,least frequency  Used是最不经常使用置换法*/
    int  LFU(int total_pf)        
    {
    	int i,j,min,minpage;
    	pfc_type *t;
    	initialize(total_pf);
    	for(i=0;i<total_instruction;i++)
    	{ 
    		if(pl[page[i]].pfn==INVALID)      /*页面失效*/
    		{ 
    			diseffect++;
    			if(freepf_head==NULL)          /*无空闲页面*/
    			{ 
    				min=32767;	
    				/*获取counter的使用用频率最小的内存*/	
    				for(j=0;j<total_vp;j++)
    				{
    					if(min>pl[j].counter&&pl[j].pfn!=INVALID)
    					{
    						min=pl[j].counter;
    						minpage=j;
    					}
    				}
    				freepf_head=&pfc[pl[minpage].pfn];
    				pl[minpage].pfn=INVALID;
    				pl[minpage].counter=0;
    				freepf_head->next=NULL;
    			}
    			pl[page[i]].pfn=freepf_head->pfn;   //有空闲页面,改为有效
    			pl[page[i]].counter++;
    			freepf_head=freepf_head->next;      //减少一个free 页面
    		}
    		else
    		{
    			pl[page[i]].counter;
    			pl[page[i]].counter=pl[page[i]].counter+1;
    		}
    	}
    	printf("LFU:%6.4f  ",1-(float)diseffect/320);
    	return 0;
    }	
    
    
    更多相关内容
  • 计算机操作系统实验代码,包括先来先服务FCFS和短作业优先SJF进程调度算法、时间片轮转RR进程调度算法、预防进程死锁的银行家算法、动态分区分配算法、虚拟内存页面置换算法、磁盘调度算法
  • 山东大学操作系统实验八 磁盘移臂调度算法实验
  • C语言实现银行家算法,操作系统实验报告,附带源码与实验截图
  • 山东大学的看过来啦,实验1-7,第8个还没做呢,做完之后再传,直接加上姓名,学号,班级就可以教了。
  • 本人清理旧系统时整理出来的,包含了哈尔滨工业大学操作系统课程8次实验的源代码及实验报告的整合版(除了实验七没有找到,但可以在本人的资源http://download.csdn.net/detail/ertwer12/1935717中下到实验七的单独...
  • 北航操作系统实验入门

    千次阅读 2021-02-07 07:57:54
    我给部分读者分配了登录北航操作系统实验平台的账号,但有读者反映不会操作,做起实验很困难。为了让读者尽快了解实验平台的操作,下面介绍lab0的实验步骤,希望读者能尽快掌握实验平台的使用方法。 1.用学生账号...

    有北航操作系统实验平台账号的部分读者反映不会操作。为了让读者尽快了解实验平台的操作,下面介绍lab0的实验步骤,希望读者能尽快掌握实验平台的使用方法。

    1. 用学生账号登录

    图片

    2. 点击【操作系统实验】进入实验界面

    图片

    3. lab0实验环境介绍,仔细阅读后点击【开始实验】

    图片

    4. 进入实验主界面

    图片

    5. 调整窗口,将窗口分成左右两个,左边是文档,右边是操作平台

    图片

     

    6. 直接从【0.6 实战测试】开始做实验,如果你对Linux/git/sed/shell等内容不熟,建议从开始做起。

    图片

    6.0 初始化系统

    图片

    6.1 编写fibo.c程序

    图片

    6.2 编写Makefile脚本文件

    图片

    6.3 编写hello_os.sh

    图片

    6.4 复制src到dst

    图片

    6.5 上传远程lab0分支

    图片

    下面执行git push命令,上传分支。

    图片

    可以看到以下信息,成绩为100(of 100)。

    图片

    再往下看,lab0完成,出现lab1

    图片

    拉出lab1,检出lab1,就可以看到下一个实验了。此时可以退出lab0,r然后进入实验lab1完成后续实验。

    图片

    更详细的内容参看微信文章: https://mp.weixin.qq.com/s/WEBRN8KX52ZKed7578mZ3g

    展开全文
  • 操作系统实验

    实验介绍

    上篇文章已经介绍了Linux内核的编译与安装,我们已经掌握了Linux系统内核的编译和启用。接下来,我们将学习掌握如何添加Linux的系统调用,学习掌握测试Linux系统调用。


    什么是系统调用(system call)

    由操作系统提供的供所有系统调用的程序接口集合;用户程序通常只在用户态下运行,当用户程序想要调用只能在内核态运行的子程序时,所以操作系统需要提供访问这些内核态运行的程序的接口,这些接口的集合就叫做系统调用。简要的说,系统调用是内核向用户进程提供服务的唯一方法。应用程序有时会需要一些危险的、权限很高的指令,如果把这些权限放心地交给用户程序是很危险的(比如一个进程可能修改另一个进程的内存区,导致其不能运行),但是又不能完全不给这些权限。于是有了系统调用,危险的指令被包装成系统调用,用户程序只能调用而无权自己运行那些危险的指令。另外,计算机硬件的资源是有限的,为了更好的管理这些资源,所有的资源都由操作系统控制,进程只能向操作系统请求这些资源。操作系统是这些资源的唯一入口,这个入口就是系统调用。


    实验准备

    华为云服务器,OpenEuler操作系统,Xshell远程登录软件(可选)

    在做此实验时需要多次编译内核,如果使用VMware本地虚拟机来进行实验,8个线程编译内核耗时过多,所以使用华为云服务器,购买32线程的云服务器编译内核1分钟就搞定,这样会节省很多时间,而且不用担心编译内核时出现bug导致本地虚拟机死机。


    本次实验全程在华为云服务器下进行

    掌握Linux内核的编译与安装请参考https://blog.csdn.net/weixin_53621503/article/details/123832515?spm=1001.2014.3001.5501


    开始实验

    1.2——掌握Linux系统调用基本概念

    添加一个新的系统调用,通过内核打印调试语句printk打印自己的学号

    1.将系统调用的函数加入到syscalls数组中

    输入

    cd kernel-kernel-4.19/include/uapi/asm-generic/  /*进入操作目录*/
    
    vim unistd.h  /*编辑该文件*/

    在该文件中输入

    #define __NR_hyb 294
    __SYSCALL(__NR_hyb, sys_hyb)

     如上图所示(注意坑点1:在编辑该文件时,找到文件最后一行为294,在其上加入系统调用函数,然后将最后的294改为295。后续实验添加调用函数后将295改为296以此类推。)

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    2.在头文件中声明系统调用函数

    输入

    cd kernel-kernel-4.19/include/linux/  /*进入头文件目录*/
    
    vim syscalls.h  /*编辑该文件*/

    在该文件中输入

    asmlinkage long sys_hyb(void);

    如上图所示(注意坑点2: 在编辑该文件时,不要将声明的函数加在 if 语句中,即将该声明放在#endif下面)

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    3.添加函数体

    输入

    cd kernel-kernel-4.19/kernel/  /*进入目录*/
    
    vim sys.c /*在该文件中添加需要的函数体*/

     在文件中添加如上图所示的内容(这里的坑点与坑点2相同)

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    4.编译、安装内核

    输入

    make -j 32  /*32为线程数,虚拟机为多少这里就写多少*/
    
    make modules_install
    
    make install
    
    reboot

    此操作时间取决于线程数量,越多耗时越短(注意坑点3:类似的操作都需要在kernel-kernel-4.19目录下进行)

    5.编写测试代码

    参考课本

    输入

    vim hyb.c  /*新建一个名为hyb.c的C语言文件*/

     输入如上图所示的内容

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    6.编译生成hyb_0文件

    输入

    gcc hyb.c -o hyb_0

    如图所示,生成了一个名为hyb_0的文件

    输入

    ./hyb_0  /*查看编译运行结果*/

     如图所示即为1.2实验结果


    1.3——设计和添加系统调用

    经过1.2的步骤,对于1.3来说,大致的过程与1.2不尽相同(三步走:写调用函数——编译安装内核——编写测试代码)

    题目一(必做):修改或返回指定进程的优先级(nice值和prio值)

    提示:可能参考的内核函数:set_user_nice()

    1.将系统调用的函数加入到syscalls数组中

    输入

    cd kernel-kernel-4.19/include/uapi/asm-generic/  /*进入操作目录*/
    
    vim unistd.h  /*编辑该文件*/

    在该文件中输入

    #define __NR_hybsetnice 295
    __SYSCALL(__NR_hybsetnice, sys_hybsetnice)

     如图所示,同理,根据上文介绍将末尾的数字295改为296

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    2.在头文件中声明系统调用函数

    输入

    cd kernel-kernel-4.19/include/linux/  /*进入头文件目录*/
    
    vim syscalls.h  /*编辑该文件*/

    在该文件中输入

     (这里的坑点与坑点2相同)

    3.添加函数体

    输入

    cd kernel-kernel-4.19/kernel/  /*进入目录*/
    
    vim sys.c /*在该文件中添加需要的函数体*/

    在该文件中添加函数体,注意格式正确(坑点与坑点2相同) 

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    4.编译、安装内核

    输入

    make -j 32  /*32为线程数,虚拟机为多少这里就写多少*/
    
    make modules_install
    
    make install
    
    reboot

    5.编写测试代码

    输入

    vim hyb_1.c  /*生成一个C语言文件并且编辑*/

     Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

     6.编译生成hyb_1文件

    输入

    gcc hyb_1.c -o hyb_1

     我们可以看到已经生成了hyb_1编译后的文件

    如图所示即为运行后的实验结果 

    题目一小结:

    在实验中,需要用到 Linux top命令行操作,什么是top?

    top 命令可以动态地持续监听进程地运行状态,与此同时,该命令还提供了一个交互界面,用户可以根据需要,人性化地定制自己的输出,进而更清楚地了进程的运行状态。

     在上图中看到有PID  USER  PR  NI  VIRT  RES  SHR  S  %CPU  %MEM  TIME+ COMMAND值,这里着重注意PR值和NI值。(PR值——优先级;NI值——nice值,有+有-,负值表示高优先级,正值表示低优先级)也就是题目中的nice prio值。

    那么,什么是nice值和prio值?

    通俗来说,nice值越低,证明这个进程越不nice(这个进程很霸道)抢占CPU的能力就越强,所以,值越低,进程的优先级越高。prio值即为priority值,为top命令中看到的PR值,优先级。


     选做题目二

    返回指定进程的内存管理信息,如进程可执行代码的起始及结束地址、已初始化数据的起始及结束地址、用户态堆栈起始地址、堆起始地址等。
    提示:可能参考的内核函数:get_task_mm()
    在进行此实验时,我们需要知道内核函数返回参数的说明,根据这个网址,可以查询。

     (牢记三步走战术)

    1.将系统调用的函数加入到syscalls数组中

    输入

    cd kernel-kernel-4.19/include/uapi/asm-generic/  /*进入操作目录*/
    
    vim unistd.h  /*编辑该文件*/

     

     同理,将下方的数字296改为297。

     Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    2.在头文件中声明系统调用函数

    cd kernel-kernel-4.19/include/linux/  /*进入头文件目录*/
    
    vim syscalls.h  /*编辑该文件*/

    在文件中输入

     (这里的坑点与坑点2相同)

    3.添加函数体

    输入

    cd kernel-kernel-4.19/kernel/  /*进入目录*/
    
    vim sys.c /*在该文件中添加需要的函数体*/

    在该文件中添加函数体,注意格式正确(坑点与坑点2相同) 

    Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

    4.编译、安装内核

    输入

    make -j 32  /*32为线程数,虚拟机为多少这里就写多少*/
    
    make modules_install
    
    make install
    
    reboot

    5.编写测试代码

    输入

    vim hyb_2.c

     Esc退出编辑模式,:wq保存并退出,cd /root返回桌面

     6.编译生成hyb_2文件

    输入

    gcc hyb_2.c -o hyb_2

     我们可以看到生成了名为hyb_2的文件,运行

    在输入PID时,可以参考前面提到过的top命令,输入一个存在的PID,以防报错。

     我们可以看到已经返回了6个想要的数据,而且ret=0为正确(ret=-1为错误)。

    题目二小结:

    题目要求输出6个需要的返回值,在参考资料后,我们发现这个内核函数中还有许许多多其他的返回参数,要学会举一反三。

    至此,实验1.3已全部完成,与上一篇博客一起,就是操作系统实验课的实验一。


    写在最后:

    本次实验是一个很耗时的实验,但是理解掌握了实验的“三步走”方法(声明——加入——编写),这个实验也会迎刃而解。查阅了非常多的资料,网络上的博客也是良莠不齐,晦涩难懂,需要多多参透课本的内容。内核编译需要非常强大的CPU,购买32核64G内存的服务器可以在make modules_install时节省大量的时间(用完记得关!!!)

    历经了很多次把内核编译崩溃的情况后,一定要冷静,仔细观察书写的代码有没有漏洞。有时候,往往那简单的一个" "、; 错误就会导致内核的编译失败(浪费了那么多时间还失败了真的很抓狂)。这就告诉我们,书写代码一定要规范仔细不可马虎。这个实验说难很难,说简单也很简单,不光只是1.3的两道题目,更要掌握其运行本质,这样才能在添加系统调用中如鱼得水。

    文章写作时间仓促,如有错误请指正,如有问题请在评论区中提问。

    加油!

    展开全文
  • 操作系统实验——进程控制

    千次阅读 2020-10-30 11:23:50
    操作系统实验——进程控制 预习内容: 1.进程的概念 ⑴程序的并发执行 ⑵进程的定义 2.进程的描述 ⑴进程控制块 ⑵进程上下文 ⑶进程上下文切换 ⑷进程空间与大小 3. 进程状态及其转换 ⑴进程状态 ⑵进程状态转换 4....

    操作系统实验——进程控制

    预习内容:

    1.进程的概念
    ⑴程序的并发执行
    ⑵进程的定义
    2.进程的描述
    ⑴进程控制块
    ⑵进程上下文
    ⑶进程上下文切换
    ⑷进程空间与大小
    3. 进程状态及其转换
    ⑴进程状态
    ⑵进程状态转换
    4.进程控制
    ⑴进程创建与撤销
    ⑵进程的阻塞与唤醒

    实验目的与要求(及主要实验仪器、设备):

    1、理解进程的概念,明确进程和程序的区别。
    2、理解并发执行的实质。
    3、 掌握进程的创建、睡眠、撤销等进程控制方法
    要求:
    (1)一台Windows7以上版本操作系统的计算机。
    (2)计算机装有Microsoft Visual Studio专业版或企业版。

    实验原理(方法与与原理分析):

    进程的创建:
    1.为新进程分配唯一的进程标识符,并从PCB队列中申请一个空闲的PCB;
    2.为新进程分配必要的内存空间和其它各种资源;
    3.初始化PCB中的相应信息,如标识信息、CPU信息、进程控制信息;
    4.若条件许可,将新进程的PCB插入到就绪队列中;

    实验步骤(程序代码与实验过程):

    步骤1:登录进入Windows,启动VC++。
    步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32ConsolApplication”,然后在“Projectname”处输入工程名,在“Location”处输入工程目录。创建一个新的控制台应用程序工程。
    步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++SourceFile”,然后在“File”处输入C/C++源程序的文件名。
    步骤4:将新创建的C/C++源程序中,编译成的可执行文件进行执行。
    1.创建新进程代码:
    void create()
    {
    if(num>=20) /判断是否有存储空间/
    printf("\n 内存已满,请删除或挂起其他程序");
    else{
    for(i=0;i<20;i++)
    if(neicun[i].state0) break; /按顺序在内存中寻找创建新进程的空间/
    printf("\n 请输入新建进程的 pid 值\n");
    scanf("%d",&neicun[i].pid);
    for(j=0;j<i;j++) /判断是否之前已存储相同 pid 进程/
    if(neicun[j].pid
    neicun[i].pid)
    { printf("\n 该进程已存在于内存中");
    return;
    }
    printf("\n 请输入新进程的优先级 \n" );
    scanf("%d",&neicun[i].youxianji);
    printf("\n 请输入新进程的大小\n" );
    scanf("%d",&neicun[i].daxiao);
    printf("\n 请输入新进程的内容\n" );
    scanf("%s",&neicun[i].neirong);
    neicun[i].state=1; /将进程状态设为 1,表示在内存中/
    num++;/内存中进程数目加一/
    }
    }
    2.查看进程代码:
    void run()
    { bj=0;
    for(i=0;i<20;i++)
    if(neicun[i].state1) /若进程状态设为 1,表示在内存中,输出查看/
    {printf("\n pid=%d",neicun[i].pid);
    printf(" youxianji=%d",neicun[i].youxianji);
    printf(" daxiao=%d",neicun[i].daxiao);
    printf(" neirong=%s",neicun[i].neirong);
    bj=1;/*存在于内存中的进程标记为 1 */
    }
    if(bj
    0)
    printf("\n 当前没有运行该进程\n" );/标记为 0,表示该进程未创建于内存中/
    }

    3.换出进程代码
    void huanchu()
    {if(num0) /num=0,表示内存中无进程/
    { printf("\n 当前没有运行的进程\n" );
    return;
    }
    printf("\n 请输入要换出的进程的 pid 值\n" );
    scanf("%d",&pid);
    bj=0;
    for(i=0;i<20;i++)
    {
    if(pid
    neicun[i].pid)
    { if(neicun[i].state1)
    {neicun[i].state=2; /将该进程的状态设为挂起/
    guaqi++;
    printf("\n 该进程已成功挂起换出\n" );
    }
    else if(neicun[i].state
    0)
    printf("\n 要换出的进程不存在\n" );
    else printf("\n 要换出的进程已经被挂起\n" );
    bj=1;break;
    }
    }
    if(bj0) printf("\n 要换出的进程不存在\n" );
    }
    4.杀死进程代码
    void kill()
    {
    if(num
    0)
    { printf("\n 当前没有运行的进程\n" );
    return;
    }
    printf("\n 请输入要杀死的进程的 pid 值\n" );
    scanf("%d",&pid);
    bj=0;
    for(i=0;i<20;i++)
    {
    if(pidneicun[i].pid)
    { if(neicun[i].state
    1)
    {neicun[i].state=0; /将该进程的状态设为不在内存中/
    num–; /内存中的进程数目减少一个/
    printf("\n 该进程已成功杀死\n" );
    }
    else if(neicun[i].state0)
    printf("\n 要杀死的进程不存在\n" );
    else printf("\n 要杀死的进程已经被挂起\n" );/剩余状态为 2,挂起/
    bj=1;break;
    }
    }
    if(bj
    0) printf("\n 要杀死的进程不存在\n" );
    }
    5.唤醒进程代码
    void huanxing()
    {
    if(num0)
    { printf(“当前没有运行的进程\n”);
    return;
    }
    if(guaqi
    0) /guaqi=0,表示没有挂起的进程/
    { printf("\n 当前没有换出的进程\n");
    return;
    }
    printf("\n 请输入要唤醒的进程的 pid 值:\n");
    scanf("%d",&pid);
    for(i=0;i<20;i++){
    if(pidneicun[i].pid)
    {
    if(neicun[i].state
    2)
    {neicun[i].state=1; /将该进程的状态设为挂起/
    guaqi–;
    num++;
    printf("\n 该进程已成功唤醒\n" );
    }
    else if(neicun[i].state==0)
    printf("\n 要唤醒的进程不存在\n" );
    else printf("\n 要唤醒的进程已经在内存中\n" );
    }
    }
    }

    实验结果(数据分析与结论):

    1.通过代码实现进程的创建和对是否有存储空间的判断,在有存储空间的情况下新建进程pid值,并且对之前是否存储相同pid值进行判断,在确定没有相同的pid进程的情况下输入进程的优先级,并且修改新建进程状态内存空间减少,之后结束;如果在有存储空间或者有相同的pid进程的情况下直接进行结束。
    2.执行查看的代码后通过查看当前运行进程来判断循环判断内存中进程状态是否为1,是的情况下输出当前进程状态后结束,如果内存中状态不为1则直接结束。
    3.创建进程
    在这里插入图片描述

    4.查看当前运行进程
    在这里插入图片描述

    5.换出进程
    在这里插入图片描述

    在这里插入图片描述

    6.杀死进程
    在这里插入图片描述
    在这里插入图片描述

    7.唤醒进程
    在这里插入图片描述

    问题讨论:

    问:在什么情况下会导致进程被撤销?
    答:
    (1)该进程已完成所要求的功能而正常终止;
    (2)由于某种错误导致非正常终止;
    (3)祖先进程要求撤销某个子进程。

    展开全文
  • 操作系统实验——进程调度

    千次阅读 2022-03-07 12:38:11
    实现了进程调度算法,包括FCFS(先进先出),SPF(短进程优先),HRRF(最高响应比优先法),HPF(优先级法)算法,设计了一个允许 n 个进程并发运行的进程管理模拟系统。该系统包括有简单的进程控制、同步,其进程调度...
  • 操作系统实验报告

    千次阅读 2022-01-06 10:52:08
    (2)学会使用 VMware 虚拟机安装 Linux 操作系统 (3)熟悉 Linux 下的 C/C++编程环境:vi/gedit 编辑器 + gcc 编译器 +gdb 调试器。 三、实验内容(实验原理/运用的理论知识、算法/程序流程图、步骤和方法、关键源...
  • 广州大学2020操作系统实验一:进程管理与进程通信

    千次阅读 多人点赞 2020-07-24 17:15:57
    实验一 进程管理与进程通信 一、实验目的 1、掌握进程的概念,明确进程的含义。 2、认识并了解进程并发执行的实质,进程的阻塞与唤醒,终止...当此程序运行时,在系统中有一个父进程和两个子进程并发执行,观察实验结.
  • 通过对操作系统启动过程的模拟,以及软件功能设计与实现,进一步理解和掌握《操作系统实验》课程中学习到的各个功能模块的原理和用法,提高自己的系统设计能力。 二、实验环境 硬件环境:计算机,无特殊配置要求 ...
  • 实验四 文件系统一、实验目的二、实验内容三、实验原理四、实验中用到的系统调用函数(包括实验原理中介绍的和自己采用的),自己采用的系统调用函数要按照指导书中的格式说明进行介绍。五、实验步骤1、对文件系统...
  • 操作系统实验四:文件系统

    千次阅读 2020-06-20 19:15:41
    一、实验目的 1、熟悉Linux文件系统的文件...四、实验原理 实验中用到的系统调用函数(包括实验原理中介绍的和自己采用的),实验步骤, 1、Linux各种发行版的目录结构基本一致,各个目录简单介绍如下: 目录 描述 / 根
  • 这个是07级哈尔滨工业大学操作系统实验的辛勤劳动,下面的压缩包中包含源代码,及实验报告,最好自己搭建平台,本人在电脑中又装了 linux,希望给感兴趣的人看看,呵呵,如果是工大的学弟学妹的话,千万不要顺手牵羊...
  • 操作系统实验

    热门讨论 2008-06-17 15:56:04
    C++Builder操作系统实验,内含文档,操作系统实验,进程调度,主存分配与回收,文件管理,作业调度
  • 操作系统实验报告操作系统实验报告操作系统实验报告操作系统实验报告操作系统实验报告操作系统实验报告操作系统实验报告
  • 实验三 内存管理一、实验目的二、实验内容三、实验原理四、实验中用到的系统调用函数(包括实验原理中介绍的和自己采用的),自己采用的系统调用函数要按照指导书中的格式说明进行介绍。五、实验步骤1、画出每个页面...
  • 操作系统实验报告心得体会

    千次阅读 2021-05-15 17:36:34
    下面是出国留学网小编为大家整理的操作系统实验报告心得体会,欢迎大家阅读。更多相关内容请关注出国留学网心得体会栏目。操作系统实验报告心得体会每一次课程设计度让我学到了在平时课堂不可能学到的东西。所以我对...
  • 目录前言实验内容实验实验实验实验四 前言 由于是小组实验,我分配被问到的是实验三的sender线程的实现,因此只记录了这一块内容可能问到的问题,不过代码里的注释很详尽了,可以自行观看。 实验内容 (1)...
  • 操作系统实验三:进程管理

    千次阅读 2021-01-21 18:23:54
    (1)掌握操作系统中进程的基本概念; (2)掌握 Linux操作系统进程管理基本方法; (3)了解进程并发运行的过程。 二、实验内容 (1)验证实验: ① 启动vi编辑器,并将其调入后台,再调出前台,最后退出vi; ② ...
  • 哈工大操作系统实验坏境搭建

    千次阅读 2021-10-09 16:21:17
    链接:https://pan.baidu.com/s/1UwLn0b1Y8H5AeWwpivwFXw 提取码:f6ex
  • Linux操作系统实验报告.doc

    千次阅读 2021-05-10 07:39:43
    Linux操作系统实验报告.docLINUX 操作系统实验报告课 程 Linux 操作系统 专 业 学 号 姓 名 指导教师 XXXXX 系20 年 月 日实验一 LINUX 基本命令实验目的1、掌握字符界面下关机及重启的命令。2、掌握LINUX下获取帮助...
  • 在Linux系统下用fork()函数创建进程,lockf()函数对进程加锁,实现进程的创建撤销与控制。 四、源代码 1.进程的创建 #include<stdio.h> main() { int p1,p2; while((p1=fork())==-1); if(p1==0) putchar('b');...
  • 操作系统实验一:Linux基本操作

    千次阅读 多人点赞 2020-11-26 18:31:24
    (1)掌握启动和退出Linux 操作系统方法; (2)了解与熟悉Linux 操作系统常用的Shell命令使用; (3)掌握Linux 操作系统下C程序的编辑、编译与调试运行方法。 2. 实验内容 (1)练习Linux的文件操作、目录操作、...
  • 熟悉操作系统实验环境,掌握Ubuntu linux基本命令。 (2) 实验要求: 1.使用VMware创建虚拟机,并安装ubuntu linux; 2.掌握Ubuntu linux基本命令 (3) 实验步骤 1.1 Linux Ubuntu的安装、创建新的虚拟机VMWare ...
  • 操作系统实验报告(四)文件系统

    千次阅读 2021-07-18 15:42:26
    2、 模拟实现Linux文件系统的简单I/O流操作:备份文件。 二、 实验环境 Ubuntu 20.10、gcc编译器 三、 实验内容 1、 浏览Linux系统根目录下的子目录,熟悉每个目录的文件和功能; 2、 设计程序模拟实现Linux文件系统...
  • HDU操作系统 实验1.1——掌握Linux内核的编译和安装

    千次阅读 多人点赞 2022-03-29 21:19:18
    HDU操作系统实验1
  • 操作系统实验(一)

    万次阅读 多人点赞 2019-03-28 16:46:58
    操作系统实验 hello,我是橘子 最近突然发现我以前写的操作系统实验,然后分享给大家吧,就是自己写的代码也不是很好,希望大家见谅哈 实验目的 一、进程控制 ●基本要求:利用简单的结构和控制方法模拟进程结构、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 477,008
精华内容 190,803
关键字:

操作系统实验