1、1操作系统实验报告(Linux 版)网络 142 潘豹 1429992实验一 观察 Linux 进程状态一、实验目的在本实验中学习 Linux操作系统的进程状态,并通过编写一些简单代码来观察各种情况下,Linux 进程的状态,进一步理解进程的状态及其转换机制。二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Linux Ubuntu 操作系统,gcc 编译器。(四)查看“不可中断阻塞” 状态(D )创建一个 C 程序,如 uninter_status.c,让其睡眠 30s代码:#include#includeint main()int i=0,j=0,k=0;for(i=0;i#incl
2、udeint main()3sleep(30);return;实验结果:(四)查看“不可中断阻塞” 状态(D )创建一个 C 程序,如 uninter_status.c,让其睡眠 30s编译链接,后台运行该程序(后接return;实验结果:(五)查看“僵尸” 进程(Z)创建一个 C 程序,如 zombie_status.c,在其中创建一个子进程,并让子进程迅速结束,而父进程陷入阻塞编译链接,后台运行该程序(后接实验结果:实验二 观察 Linux 进程/线程的异步并发执行一、实验目的通过本实验学习如何创建 Linux 进程及线程,通过实验,观察 Linux 进程及线程的异步执行。理解进程及线程的
3、区别及特性,进一步理解进程是资源分配单位,线程是独立调度单位。二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Linux Ubuntu 操作系统,gcc 编译器。三、实验内容和步骤1、进程异步并发执行编写一个 C语言程序,该程序首先初始化一个 count变量为 1,然后使用 fork函数创建两个子进程,每个子进程对 count加 1后,显示“I am son, count=x”或“I am daughter, count=x”,父进程对 count加 1之后,显示“I am father, count=x”,其中 x使用 count值代替。最后父进程使用 waitpid等待两个子进程结
4、束之后退出。编译连接后,多次运行该程序,观察屏幕上显示结果的顺序性,直到出现不一样的情况为止,并观察每行打印结果中 count的值。代码:#include#includeint main()5pid_t son_pid,daughter_pid;int count=1;son_pid=fork();if(son_pid=0)count+;printf(“i am son,count=%dn“,count);elsedaughter_pid=fork();if(daughter_pid=0)count+;printf(“i am daughter,count=%dn“,count);elseco
5、unt+;printf(“i am father,count=%dn“,count);waitpid(son_pid,NULL,0);waitpid(daughter_pid,NULL,0);2、线程异步并发执行编写一个 C语言程序,该程序首先初始化一个 count变量为 1,然后使用pthread_create函数创建两个线程,每个线程对 count加 1后,显示“I am son, count=x”或“I am daughter, count=x”,父进程对 count加 1之后,显示“I am father, count=x”,其中 x使用 count值代替。最后父进程使用 pthrea
6、d_join等待两个线程结束之6后退出。编译连接后,多次运行该程序,观察屏幕上显示结果的顺序性,直到出现不一样的情况为止,并观察每行打印结果中 count的值。代码:#include#include#includevoid *daughter(void *num)int* a=(int *)num;*a+=1;printf(“i am daughter,count=%dn“,*a);void *son(void *num)int* a=(int *)num;*a+=1;printf(“i am son,count=%dn“,*a);int main()pthread_t son_tid,dau
7、ghter_tid;int count=1;pthread_create(pthread_create(count+;printf(“i am parent,count:=%dn“,count);pthread_join(son_tid,NULL);pthread_join(daughter_tid,NULL);return 0;实验结果:7实验三 使用信号量进行互斥与同步 一、实验目的本实验介绍在 Linux 中使用信号量进行进程同步、互斥的方法。读者可以通过实验进一步理解进程间同步与互斥、临界区与临界资源的概念与含义,并学会 Linux 信号量的基本使用方法。二、实验环境硬件环境:计算机一
8、台,局域网环境;软件环境:Linux Ubuntu 操作系统,gcc 编译器。三、实验内容和步骤三、实验内容和步骤(一)参考:POSIX 以及 System VSystem V:Unix 众多版本中的一支,最初由 ATint i=0;if(argc1)message=argv10;8for(i=0;i#include#include#include#include#include#includeint main(int argc,char *argv)char message=x;int i=0;if(argc1)message=argv10;sem_t *mutex=sem_open(“my
9、sem“,O_CREAT,0666,1);for(i=0;i#include#include#include#include#include10#includeint main(int argc,char *argv)int i=0;sem_t *hei=sem_open(“chess_black_sem“,O_CREAT,0666,1);sem_t *hong=sem_open(“chess_red_sem“,O_CREAT,0666,0);for(i=0;i#include#include#include#include#include#includeint main(int argc,c
10、har *argv)int i=0;sem_t *hei=sem_open(“chess_black_sem“,O_CREAT,0666,1);sem_t *hong=sem_open(“chess_red_sem“,O_CREAT,0666,0);for(i=0;i#include #include #include/最大作业数量const int MAXJOB=50;/作业的数据结构typedef struct node13int number;/作业号 int reach_time;/作业抵达时间int need_time;/作业的执行时间int privilege;/作业优先权floa
11、t excellent;/响应比int start_time;/作业开始时间int wait_time;/等待时间int visited;/作业是否被访问过bool isreached;/作业是否抵达job;job jobs50;/作业序列int quantity;/作业数量/初始化作业序列void initial_jobs()int i;for(i=0;ijobsi.need_timeminloc=i;return minloc;/查找最早到达作业,若全部到达返回-1.int findrearlyjob(job jobs,int count)int rearlyloc=-1;int rear
12、lyjob=-1;int i;for(i=0;ijobsi.reach_timerearlyloc=i;return rearlyloc;/读取作业数据void readJobdata()FILE *fp;char fname20;int i;/输入测试文件文件名printf(“please input job data file namen“);scanf(“%s“,fname);if(fp=fopen(fname,“r“)=NULL)printf(“error, open file failed, please check filename:n“);else/依次读取作业信息while(!
13、feof(fp)if(fscanf(fp,“%d %d %d %d“,/打印作业信息printf(“output the origin job datan“);printf(“-n“);printf(“tjobIDtreachtimetneedtimetprivilegen“);for(i=0;icurrent_time)jobsloc.start_time=jobsloc.reach_time;current_time=jobsloc.reach_time;elsejobsloc.start_time=current_time;jobsloc.wait_time=current_time-j
14、obsloc.reach_time; printf(“t%-8dt%-8dt%-8dt%-8dt%-8dn“,loc+1,jobsloc.reach_time,jobsloc.start_time,jobsloc.wait_time,jobsloc.wait_time+jobsloc.need_time);jobsloc.visited=1;current_time+=jobsloc.need_time;total_waitime+=jobsloc.wait_time; 17total_roundtime=total_roundtime+jobsloc.wait_time+jobsloc.ne
15、ed_time;/获取剩余作业中最近到达作业loc=findrearlyjob(jobs,quantity); printf(“总等待时间:%-8d 总周转时间:%-8dn“,total_waitime,total_roundtime); printf(“平均等待时间: %4.2f 平均周转时间: %4.2fn“,(float)total_waitime/(quantity),(float)total_roundtime/(quantity); /短作业优先作业调度void SFJschdulejob(job jobs,int count)int main() initial_jobs();
16、readJobdata(); FCFS();reset_jinfo();SFJschdulejob(jobs,quantity);system(“pause“);return 0;实验结果:18实验五 Linux 内存分配一、实验目的1、了解 Linux 内存的分配和虚拟内存管理的原理,学习如何使用 malloc 动态申请内存,了解动态申请与静态申请的区别。2、深入理解 Linux 的内存布局:代码段、数据段、BSS 段、堆栈段、堆二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Linux Ubuntu 操作系统,gcc 编译器。三、实验内容和步骤第一部分:编程分析 Linux 中内存
17、动态申请与内存静态申请的区别要求: 1、编写一个 Linux C 程序,在该程序中使用定义一个全局变量,以及使用 malloc 申请一段内存(可大于物理内存大小,理论上在 32 位系统中可以申请小于 3G 空间,但由于malloc 要求申请连续的空间,所以能申请到的空间一般在 2G 以下) 。2、打印出全局变量的起始地址,以及 malloc 分配的内存的地址;3、观察运行结果,并分析说明结果的地址是否是物理地址。代码:#include#includeint pint128;int main()char* pbuf=(char *)malloc(sizeof(char)*1024*1024*10
18、24);19if(pint)printf(“the address of pint is %xn“,pint);if(pbuf)printf(“the address of pbuf is %xn“,pbuf);if(pbuf)free(pbuf);pbuf=NULL;return 0;实验结果:第二部分:进一步了解 Linux内存的分配和虚拟内存管理的原理、了解 Linux的内存布局:代码段、数据段、BSS 段、堆栈段、堆。要求:1、编写一个 Linux C 程序,在该程序中定义初始化全局变量、未初始化全局变量、初始化静态变量、未初始化静态变量、局部变量、使用 malloc 分配的局部变量2
19、、打印出各种变量的的起始地址代码:#include #include /定义两个初始化的全局变量int data_var0 = 10; int data_var1 = 10; /定义两个未初始化的全局变 量int bss_var0; int bss_var1; int main() 20 /分别定义一个初始化和一个未初始化的静态变量static int data_var2 = 10; static int bss_var2;/定义两个局部变量int stack_var0 = 1; int stack_var1 = 1; int stack_var2 = 1; printf(“-TEXT Seg
20、ment-n“); printf(“Address of main: %pn“, main); printf(“-DATA Segment-n“); printf(“Address of data_var0: %pn“, printf(“Address of data_var1: %pn“, printf(“Address of data_var2: %pn“, printf(“-BSS Segment-n“); printf(“Address of bss_var0(BSS Segment): %pn“, printf(“Address of bss_var1(BSS Segment): %
21、pn“, printf(“Address of bss_var2(BSS Segment): %pn“, printf(“-STACK Segment-n“); printf(“Address of stack_var0: %pn“, printf(“Address of stack_var1: %pn“, printf(“Address of stack_var2: %pn“, /使用 malloc 分配三个大小为1024B 的内存char* heap_var0 = (char*)malloc(1024); char* heap_var1 = (char*)malloc(1024); cha
22、r* heap_var2 = (char*)malloc(1024); /使用 malloc 分配三个大小为 512MB 的内存char* mmap_var0 = (char*)malloc(1024 * 1024 * 512); char* mmap_var1 = (char*)malloc(1024 * 1024 * 512); char* mmap_var2 = (char*)malloc(1024 * 1024 * 512); printf(“-HEAP Segment-n“); if(heap_var0) printf(“Address of heap_var0:%pn“, heap
23、_var0); free(heap_var0); heap_var0 = NULL; if(heap_var1) printf(“Address of heap_var1:%pn“, heap_var1); free(heap_var1); heap_var1 = NULL; 21if(heap_var2) printf(“Address of heap_var2:%pn“, heap_var2); free(heap_var2); heap_var2 = NULL; printf(“-mmap-n“); if(mmap_var0) printf(“Address of mmap_var0:%
24、pn“, mmap_var0); free(mmap_var0); mmap_var0 = NULL; if(mmap_var1) printf(“Address of mmap_var1:%pn“, mmap_var1); free(mmap_var1); mmap_var1 = NULL; if(mmap_var2) printf(“Address of mmap_var2:%pn“, mmap_var2); free(mmap_var2); mmap_var2 = NULL; return 0; 实验结果:22实验六 页面置换模拟程序设计一、实验目的1、通过软件模拟页面置换过程,加深对请
25、求页式存储管理实现原理的理解2、理解和掌握 OPT、FIFO 和 LRU 三种页面置换算法,深入分析三者之间的优缺点。二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Linux Ubuntu 操作系统,gcc 编译器。三、实验内容和步骤代码:#include#include#include#include#define VM_PAGE 32#define PM_PAGE 4#define TOTAL_INSTR 320#define INSTR_PER_PAGE 10#define OPT 1#define FIFO 223#define LRU 3typedef structint
26、vmn;int pmn;int exist;int time;vpage_item;vpage_item page_tableVM_PAGE;vpage_item* ppage_bitmapPM_PAGE;typedef structint num;int vpage;int offset;int inflow;instr_item;instr_item instr_arrayTOTAL_INSTR;struct instr_flowinstr_item*instr;struct instr_flow*next;struct instr_flow_headint num;struct inst
27、r_flow*next;struct instr_flow_head iflow_head;int pfail_num=0;int cur_replace_alg=1;void init_data();void reset_page_table();int add_to_flow(int n);int gen_instr_flow();int alloc_PPage(struct instr_flow*cur,int chip);void run();int opt(struct instr_flow*cur);int fifo(struct instr_flow*cur);int lru(s
28、truct instr_flow*cur);void clean();int main()init_data;gen_instr_flow();printf(“-the result of OPT-n“);cur_replace_alg=OPT;run();24printf(“-the result of FIFO-n“);cur_replace_alg=FIFO;reset_page_table();run();printf(“-the result of LRU-n“);cur_replace_alg=LRU;reset_page_table();run();clean();/3.数据初始
29、化void init_data()int i=0;for(i=0;iinstr=tail-next=NULL;if(instr_arrayn.inflow=0)instr_arrayn.inflow=1;ret=1;if(iflow_head.num=0elseptr=iflow_head.next;while(ptr-next!=NULL)ptr=ptr-next;ptr-next=tail;iflow_head.num+=1;return ret;int gen_instr_flow()int total=0;int s;srand(int)getpid();s=(int)rand()%T
30、OTAL_INSTR;total+=add_to_flow(s);if(s0)s=(int)rand()%s;total+=add_to_flow(s);26if(sinstr-vpage;for(i=0;iexist=0;ppage_bitmapppage-time=-1;ppage_bitmapppage=return ppage;/void run()int vpage,offset,ppage;int chip=0;struct instr_flow * cur=iflow_head.next;while(cur!=NULL)vpage=cur-instr-vpage;offset=c
31、ur-instr-offset;if(page_tablevpage.exist=0)ppage=alloc_PPage(cur,chip);pfail_num+=1;else switch (cur_replace_alg)case LRU:page_tablevpage.time=chip;break;case OPT:28case FIFO:default:break;cur=cur-next;chip+;printf(“page fault ratio is %fn“,(float)pfail_num/(float)iflow_head.num);/int opt(struct ins
32、tr_flow * cur)int found=0;int ppage_hashPM_PAGE;struct instr_flow * ptr=cur-next;int vpage,ppage,exist,i,ret;memset(ppage_hash,0,sizeof(int) * PM_PAGE);while(ptr !=NULL ppage=page_tablevpage.pmn;exist=page_tablevpage.exist;if(exist found+=1;ptr=ptr-next;for(i=0;itimetime;ppage=1;return ppage;int fifo(struct instr_flow*cur)int min_time=1000000,ppage=-1,i;for(i=0; itimetime;ppage=i;return ppage;void clean()struct instr_flow*ptr=NULL,*cur=NULL;ptr=cur=iflow_head.next;while(ptr !=NULL)cur=ptr;ptr=ptr-next;free(cur);实验结果:30