操作系统Linux实验及程序运行结果.docx
《操作系统Linux实验及程序运行结果.docx》由会员分享,可在线阅读,更多相关《操作系统Linux实验及程序运行结果.docx(18页珍藏版)》请在冰点文库上搜索。
![操作系统Linux实验及程序运行结果.docx](https://file1.bingdoc.com/fileroot1/2023-8/13/bf570c1d-fe60-4124-a4b7-cdb55428e27b/bf570c1d-fe60-4124-a4b7-cdb55428e27b1.gif)
操作系统Linux实验及程序运行结果
实验一:
操作系统用户接口实验
1实验目的:
熟悉操作系统的命令接口、图形接口和程序接口
2实验内容:
1)使用linux常用命令:
pwd、ls、cd、mkdir、cp、date,显示这些命令的结果,并解释这些命令的作用;
2)用C语言编制一个小程序,使其可通过Localtime()系统调用来获得OS提供的时间和日期。
//注释:
localtime(取得当地目前时间和日期)
v相关函数time,asctime,ctime,gmtime
v表头文件#include
v定义函数structtm*localtime(consttime_t*timep);
v函数说明localtime()将参数timep所指的time_t结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果由结构tm返回。
此函数返回的时间日期已经转换成当地时区。
v返回值返回结构tm代表目前的当地时间。
结构tm的定义为
structtm
{
inttm_sec;//代表目前秒数,正常范围为0-59,但允许至61秒
inttm_min;//代表目前分数,范围0-59
inttm_hour;//从午夜算起的时数,范围为0-23
inttm_mday;//目前月份的日数,范围01-31
inttm_mon;//代表目前月份,从一月算起,范围从0-11
inttm_year;//从1900年算起至今的年数
inttm_wday;//一星期的日数,从星期一算起,范围为0-6
inttm_yday;//从今年1月1日算起至今的天数,范围为0-365
inttm_isdst;//日光节约时间的旗标
};
程序如下:
#include
main(){
char*wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
time_ttimep;
structtm*p;
time(&timep);/*取得当地时间*/
p=localtime(&timep);/*转换时间*/
printf("%d%d%d",(1900+p->tm_year),(1+p->tm_mon),
p->tm_mday);
printf("%s%d:
%d:
%d\n",wday[p->tm_wday],p->tm_hour,
p->tm_min,p->tm_sec);
}
实验截图如下:
实验二进程的创建
一、实验目的
1、掌握进程的概念,明确进程的含义
2、认识并了解并发执行的实质
二、实验内容
1、编写一段程序,使用系统调用fork()创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:
父进程显示'a',子进程分别显示字符'b'和字符'c'。
试观察记录屏幕上的显示结果,并分析原因。
2、修改上述程序,每一个进程循环显示一句话。
子进程显示'daughter…'及'son……',父进程显示'parent……',观察结果,分析原因。
三、实验准备
(1)阅读LINUX的fork.c源码文件,分析进程的创建过程。
(2)阅读LINUX的sched.c源码文件,加深对进程管理概念的认识。
四、思考
(1)系统是怎样创建流程?
(2)可执行文件加载时进行了哪些处理?
(3)当首次调用新创建的进程时,其入口在哪里?
五、参考程序
1、
#include
main()
{
intp1,p2;
while((p1=fork())==-1);/*创建子进程p1*/
if(p1==0)putchar('b');
else
{
while((p2=fork())==-1);/*创建子进程p2*/
if(p2==0)putchar('c');
elseputchar('a');
}
}
2、
#include
main()
{
intp1,p2,i;
while((p1=fork())==-1);/*创建子进程p1*/
if(p1==0)
for(i=0;i<10;i++)
printf("daughter%d\n",i);
else
{
while((p2=fork())==-1);/*创建子进程p2*/
if(p2==0)
for(i=0;i<10;i++)
printf("son%d\n",i);
else
for(i=0;i<10;i++)
printf("parent%d\n",i);
}
}
完整程序进程1:
#include
main()
{
intp1,p2;
while((p1=fork())==-1);/*创建子进程p1*/
if(p1==0)putchar('b');
else
{
while((p2=fork())==-1);/*创建子进程p2*/
if(p2==0)putchar('c');
elseputchar('a');
}
}
截图如下:
进程2程序如下:
#include
main()
{
intp1,p2,i;
while((p1=fork())==-1);/*创建子进程p1*/
if(p1==0)
for(i=0;i<10;i++)
printf("daughter%d\n",i);
else
{
while((p2=fork())==-1);/*创建子进程p2*/
if(p2==0)
for(i=0;i<10;i++)
printf("son%d\n",i);
else
for(i=0;i<10;i++)
printf("parent%d\n",i);
}
}
截图如下:
实验三进程间通信
实验目的:
Linux系统的进程通信机构(IPC)允许在任意进程间大批量的交换数据。
本实验的目的是了解和熟悉Linux支持的通信机制、共享存储区机制及信号量机制。
一、实验预备内容:
阅读Linux系统的msg.csem.cshm.c等源码文件,熟悉Linux的三种通信机制。
、
二、实验内容:
(1)消息的创建,发送和接收
(2)使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制一长度为1k的消息发送和接收程序。
<程序设计>
(1)为了便于操作和观察结果,用一个程序作为“引子”,先后fork()两个子进程,SERVER和CLIENT,进行通信。
(2)SERVER端建立一个Key为75的消息队列,等待其他进程发来的消息。
当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER。
SERVER每接收到一个消息后显示一句“(server)received”。
(3)CLIENT端使用Key为75的消息队列,先后发送类型从10到1的消息,然后退出。
最后一个消息,即是SERVER端需要的结束信号。
CLIENT每发送一条信息后显示一句“(client)sent”。
(4)父进程在SERVER和CLIENT均退出后结束。
程序设计如下:
#include
#include
#include
#include
#defineMSGKEY75
structmsgform
{
longmtype;
charmtext[1030];
}msg;
intmsgqid,i;
voidCLIENT()
{inti;
msgqid=msgget(MSGKEY,0777);
for(i=10;i>=1;i--)
{
msg.mtype=i;
printf("(client)sent\n");
msgsnd(msgqid,&msg,1024,0);/*发送消息msg入msgid消息队列*/
}
exit(0);
}
voidSERVER()
{
msgqid=msgget(MSGKEY,0777|IPC_CREAT);/*由关键字获得消息队列*/
do
{
msgrcv(msgqid,&msg,1030,0,0);/*从msgid消息队列接收消息msg*/
printf("(server)received\n");
}while(msg.mtype!
=1);/*消息类型为1时,释放队列*/
msgctl(msgqid,IPC_RMID,0);
exit(0);
}
voidmain()
{
while((i=fork())==-1);
if(!
i)SERVER();
while((i=fork())==-1);
if(!
i)CLIENT();
wait(0);
wait(0);
}
实验结果截图如下:
实验四存储管理
1实验目的:
通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。
2实验内容:
1)通过随机数产生一个指令序列,共320条指令;
2)将指令序列变换为页面号;
3)计算FIFO算法在分配不同内存块下的命中率。
(假设分配的内存块从4块至32块。
)
<程序设计>
设计一个虚拟存储区和内存工作区,使用FIFO算法计算访问命中率。
首先用Srand()和rand()函数定义和产生指令序列,然后将指令序列变换成相应的页面号,并针对FIFO算法计算相应的命中率。
命中率=1-缺页率
相关定义如下:
1.数据结构
(1)页面类型结构pl_type中
pn页号,pfn块号,counter为一个周期内访问页面次数,time为访问时间
(2)页面控制结构中
pfc[total_vp]定义用户进程虚页控制结构
*freepf_head为空页面头的指针
*busypf_head为忙页面头的指针
*busypf_tail为忙页面尾的指针
2.函数定义
(1)voidinitialize():
初始化函数,给每个相关的页面赋值
(2)voidFIFO():
计算使用FIFO算法时的命中率
3.变量定义
(1)inta[total_instruction]:
指令流数组
(2)intpage[total_instruction]:
每条指令所属页号
(3)intoffset[total_instruction]:
每页装入10条指令后取模运算页号偏移值
(4)inttotal_pf:
用户进程的内存块数
(5)intdiseffect:
页面失效次数,即缺页次数
完整程序如下:
#include
#include
#include
#include
#defineTRUE1
#defineFALSE0
#defineINVALID-1
#defineNULL0
#definetotal_instruction320/*指令流长*/
#definetotal_vp32/*虚页长*/
#defineclear_period50/*清零周期*/
typedefstruct{/*页面结构*/
intpn,pfn,counter,time;
}pl_type;
pl_typepl[total_vp];/*页面结构数组*/
structpfc_struct{/*页面控制结构*/
intpn,pfn;
structpfc_struct*next;
};
typedefstructpfc_structpfc_type;
pfc_typepfc[total_vp],*freepf_head,*busypf_head,*busypf_tail;
intdiseffect,a[total_instruction];
intpage[total_instruction],offset[total_instruction];
voidinitialize();
voidFIFO();
main()
{
intS,i,j,temp;
srand(getpid()*10);/*由于每次运行时进程号不同,故可以用来作为初始化随即数队列的“种子”*/
S=(float)319*rand()/RAND_MAX+1;
//printf("s=%d\n",S);
for(i=0;i{
a[i]=S;/*任选一指令访问点*/
a[i+1]=a[i]+1;/*顺序执行一条指令*/
//a[i+2]=(float)a[i]*rand()/32767;
a[i+2]=(float)a[i]*rand()/RAND_MAX;/*执行前地址指令m'*/
a[i+3]=a[i+2]+1;/*执行后地址指令*/
S=(float)rand()*(318-a[i+2])/RAND_MAX+a[i+2]+2;
}
for(i=0;i{
page[i]=a[i]/10;
offset[i]=a[i]%10;
}
for(i=4;i<=32;i++)/*用户内存工作区从4个页面到32个页面*/
{
printf("%2dpageframes",i);
FIFO(i);
printf("\n");
}
}
voidFIFO(total_pf)/*FIFO算法*/
inttotal_pf;/*用户进程的内存页面数*/
{
inti,j;
pfc_type*p,*t;
initialize(total_pf);/*初始化相关页面控制用数据结构*/
busypf_head=busypf_tail=NULL;/*忙页面队列头,队列尾链接*/
for(i=0;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;/*按FIFO方式调新页面入内存页面*/
freepf_head->next=NULL;
freepf_head->pn=page[i];
pl[page[i]].pfn=freepf_head->pfn;
if(busypf_tail==NULL)
busypf_head=busypf_tail=freepf_head;
else
{
busypf_tail->next=freepf_head;
busypf_tail=freepf_head;
}
freepf_head=p;
}
}
printf("FIFO:
%6.4f",1-(float)diseffect/320);
}
voidinitialize(total_pf)/*初始化相关数据结构*/
inttotal_pf;/*用户进程的内存页面数*/
{
inti;
diseffect=0;
for(i=0;i{
pl[i].pn=i;pl[i].pfn=INVALID;/*置页面控制结构中的页号,页面为空*/
pl[i].counter=0;pl[i].time=-1;/*页面控制结构中的访问次数为0,时间为-1*/
}
for(i=1;i{
pfc[i-1].next=&pfc[i];pfc[i-1].pfn=i-1;/*建立pfc[i-1]和pfc[i]之间的链接*/
}
pfc[total_pf-1].next=NULL;pfc[total_pf-1].pfn=total_pf-1;
freepf_head=&pfc[0];/*空页面队列的头指针为pfc[0]*/
}
试验截图如下: