操作系统实验报告
实验名称 |
linux 进程创建 |
专业 |
软件工程 |
||
姓名 |
学号 |
班级 |
- 实验目的:
加深对进程概念的理解
练习使用fork()系统调用创建进程
二、实验内容:
使用fork()调用计算Fibonacci数列
Fibonacci数列是0,1,1,2,3,5,8…….通常表示为:fib0=0,fib1=1,fibn=fibn-1+fibn-2
写一个c程序,使用fork()系统调用产生一个子进程来计算Fibonacci数列,序列通过命令行显示。例如,如果参数为5,Fibonacci数列的前5个数字将在子进程中被输出。
因为父进程和子进程拥有各自的数据拷贝,所以需要由子进程输出。在退出程序之前,父进程调用wait()等待子进程完成。
要求提供必要的错误检测以保证在命令行传递的参数是非负数。
三、实验设备及软件环境:
操作系统:Linux
软件环境:word
- 实验过程及结果:
- 根据PPT自学Linux系统
- 学习Linux系统中的函数调用
1. fork()函数:创建一个新进程.
调用格式:
#include <sys/types.h>
#include <unistd.h>
int fork();
返回值:
正确返回时,等于0表示创建子进程,从子进程返回的ID值;大于0表示从父进程返回的子进程的进程ID值。
错误返回时,等于-1表示创建失败
2. wait()函数:用来控制父进程与子进程的同步。在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原程序。
调用格式:
#include<sys/type.h>
#include<sys/wait.h>
(pid_t) wait(int *statloc);
返回值:正确返回时大于0表示子进程的进程ID值;等于0表示其他。错误返回时等于-1表示调用失败。
3. exit()函数:进程结束最长调用的函数,在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。
调用格式:
#include<stdio.h>
void exit(int status);
其中,status为进程结束状态。
3.尝试编写斐波那契数列
- 实验截图
实验代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc,char* argv[])
{
pid_t pid;
int i;
int f0,f1,f2;
f0=0;
f1=1;
if(argv[1]<0)
{
fprintf(stderr,"requeest a nun-negative number");
}
pid=fork();
if(pid<0)
{
fprintf(stderr,"failed");
exit(-1);
}
else if(pid==0)
{
printf("argv[1]=%d\n",atoi(argv[1]));
printf("01");
for(i=2;i<=atoi(argv[1])-1;i++)
{
f2=f0+f1;
f0=f1;
f1=f2;
printf("%d",f2);
}
printf("\nchild process competed\n");
}
else
{
wait(NULL);
printf("parent process exist\n");
}
return 0;
}
五、总结:(实验结果分析,个人体会等)
这一次的上机实验,是我本人第一次接触LINUX操作系统,新鲜的事务,更让我觉得以后学习道路上更是需要十分的努力,通过这次试验,我学会了Linux的使用,并且成功的掌握了Linux操作系统的基本命令,VI的使用方法,GCC的使用方法以及调试器GDB的使用方法。在老师和同学的帮助下,我进一步学会了在Linux系统中如何创建一个目录,并在该目录下创建文件,并实现文件的目录转移。复制以及粘贴。
操作系统的学习,更不是局限在书本纸面上的内容,是需要结合实地实践和动手动脑学习的一项内容,所以以后的我会多与老师交流,参与实践,更努力学习操作系统。
实验成绩: 指导教师: 年 月 日
实验名称 |
实验二 Linux 进程通信 |
专业 |
软件工程 |
||
姓名 |
学号 |
班级 |
一、实验目的:
加深对进程概念的理解,明确进程和程序的区别
进一步认识并发执行的实质
分析进程争用资源的现象,学习解决进程互斥的方法
了解Linux系统中进程通信的基本原理
掌握Linux系统软中断通信的实现方法
学会使用Linux系统中关于进程通信的实现方法
**掌握管道通信的使用
- 实验内容:
编制实现软中断通信的程序
使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉定时器报警中断信号(SIGALRM),当父进程接收到该信号后,调用kill()向两个子进程发送终止信号,子进程分别输出下列信息后终止。
Child process 1 is killed by parent!!
Child process 2 is killed by parent!!
父进程调用wait()函数等待两个子进程终止后,输出以下信息后终止。
Parent process is killed!!
多运行几次编写的程序,简略分析出现不同结果的原因
- 实验设备及软件环境:
硬件:计算机
操作系统:Linux
软件环境:word
四、实验过程及结果:
实验过程:
1. fork()函数:创建一个新进程.
-
- 调用格式:
#include <sys/types.h>
#include <unistd.h>
int fork();
-
- 返回值:
正确返回时,等于0表示创建子进程,从子进程返回的ID值;大于0表示从父进程返回的子进程的进程ID值。
错误返回时,等于-1表示创建失败
2. wait()函数:用来控制父进程与子进程的同步。
在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原程序。
调用格式:
#include<sys/type.h>
#include<sys/wait.h>
(pid_t) wait(int *statloc);
返回值:正确返回时大于0表示子进程的进程ID值;等于0表示其他。错误返回时等于-1表示调用失败。
3. exit()函数:进程结束最长调用的函数。在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。
-
- 调用格式:
#include<stdio.h>
void exit(int status);
其中,status为进程结束状态。
4. kill()函数:用于删除执行中的程序或者任务。
-
- 调用格式:
#include<stdio.h>
kill(int PID, int IID);
其中,PID是要被杀死的进程号,IID为向将被杀死的进程发送的中断号。
5. signal()函数:允许调用进程控制软中断信号的处理。
-
- 调用格式:
#include<signal.h>
int sig;
void (*func)();
signal(sig, function);
function:在该进程中的一个函数地址,在核心返回用户态时,它以软件中断信号的序号作为参数调用该函数。
sig的值是下列之一:
6. pipe()函数:用于创建一个管道
-
- 调用格式:
#include<unistd.h>
pipe(int fp[2]);
其中,fp[2]是进程使用的文件描述符数组,fp[0]用于写,fp[1]用于读。
-
- 返回值:正确返回时,0表示调用成功
错误返回时,-1表示调用失败
实验代码:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include<sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
int flag_wait=1;
void stop2()
{
flag_wait=0;
printf("\nson interruption\n");
}
void stop()
{
printf("\ninterruption\n");
}
int main()
{
pid_t pid1,pid2;
signal(3,stop);
while((pid1=fork())==-1);
if(pid1>0)
{
while((pid2=fork())==-1);
if(pid2>0)
{
sleep(5);
kill(pid1,16);
wait(0);
kill(pid2,17);
wait(0);
printf("\nParent process is killed\n");
exit(0);
}
else
{
signal(17,stop2);
while(flag_wait);
printf("\nchild process 2 is killed\n");
exit(0);
}
}
else
{
signal(16,stop2);
while(flag_wait);
printf("\nchild process 1 is killed\n");
exit(0);
}
return 0;
}
实验截图:
五、总结:(实验结果分析,个人体会等)
这一次的实验,在实验1的基础上,我可以熟悉并且顺利打开linux操作系统,按照实验目的和要求进行实验2,完成进程间的通信,第二次的实验让我更体会到了面对每一次的实验内容,或者以后的实践学习过程中,都会有不同的问题和困难随之出现,我们必须要创新思维,不要固步自封的守住当前已学会的知识,而是应该针对具体情况具体分析,就像这一次的实验过程中,出现了我的命名方式总是找不到路径和地址,最后在同学的帮助下,我成功的解决了问题,让我在操作系统的学习之路上获得了小小的经验。
实验成绩: 指导教师: 年 月 日
实验名称 |
实验3 Linux 存储器管理 ——LRU算法 |
专业 |
软件工程 |
||
姓名 |
学号 |
班级 |
一、实验目的:
进一步掌握虚拟存储器的实现方法
掌握各种页面置换算法
比较各种页面置换算法的优缺点
二、实验内容:
使用常量total_instruction记录页面总共使用次数,使用变量diseffect记录总
共换入页面的次数(需要换出页面,总是因为没有命中而产生)
(1)初始化。设置两个数组page[ap]和pagecontrol[pp]分别表示进程页面数和内存分配的页面数,并产生一个随机序列main[total_instruction],(当然这个序列由page[]的下标随机组成),表示待处理的进程页面顺序,diseffect置零。
(2)看main[]中是否有下一个元素。若有,则由main[]中获取该页面下标,并转到(3);若没有,则转到(6)。
(3)如果该page[]单元在内存中便改变页面属性,使它保留最近页面的信息,就转到(2);否则转到(4),同时未命中的diseffect加1。
(4)判断是否有空闲的内存页面,如果有,就返回页面指针,转到(5);否则在内存页面中找出最长时间没有使用到的页面,将其“清干净”,并返回该页面指针。
(5)将需处理的page[]与(4)中得到的pagecontrol[]建立关系,同时需让对应的page[]单元保存“最新使用”信息,返回(2)。
(6)如果序列处理完成,就输出1-diseffect/total_instruction*100%,并结束。
三、实验设备及软件环境:
硬件:计算机
操作系统:Linux
软件环境:word
四、实验过程及结果:
实验代码:
#include <stdio.h>
#define M 4
#define N 17
#define Myprintf printf("|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\n") /*表格控制*/
typedef struct page
{
int num; /*记录页面号*/
int time; /*记录调入内存时间*/
}Page; /* 页面逻辑结构,结构为方便算法实现设计*/
Page b[M]; /*内存单元数*/
int c[M][N]; /*暂保存内存当前的状态:缓冲区*/
int queue[100]; /*记录调入队列*/
int K; /*调入队列计数变量*/
/*初始化内存单元、缓冲区*/
void Init(Page *b,int c[M][N])
{
int i,j;
for(i=0;i<N;i++)
{
b[i].num=-1;
b[i].time=N-i-1;
}
for(i=0;i<M;i++)
for(j=0;j<N;j++)
c[i][j]=-1;
}
/*取得在内存中停留最久的页面,默认状态下为最早调入的页面*/
int GetMax(Page *b)
{
int i;
int max=-1;
int tag=0;
for(i=0;i<M;i++)
{
if(b[i].time>max)
{
max=b[i].time;
tag=i;
}
}
return tag;
}
/*判断页面是否已在内存中*/
int equation(int fold,Page *b)
{
int i;
for(i=0;i<M;i++)
{
if (fold==b[i].num)
return i;
}
return -1;
}
/*LRU核心部分*/
void Lru(int fold,Page *b)
{
int i;
int val;
val=Equation(fold,b);
if (val>=0)
{
b[val].time=0;
for(i=0;i<M;i++)
if (i!=val)
b[i].time++;
}
else
{
queue[++K]=fold;/*记录调入页面*/
val=GetMax(b);
b[val].num=fold;
b[val].time=0;
for(i=0;i<M;i++)
if (i!=val)
b[i].time++;
}
}
/*主程序*/
int main()
{
int a[N]={1,0,1,0,2,4,1,0,0,8,7,5,4,3,2,3,4};
int i,j;
start:
K=-1;
Init(b, c);
for(i=0;i<N;i++)
{
Lru(a[i],b);
c[0][i]=a[i];
/*记录当前的内存单元中的页面*/
for(j=0;j<M;j++)
c[j][i]=b[j].num;
}
/*结果输出*/
printf("内存状态为:\n");
Myprintf;
for(j=0;j<N;j++)
printf("|%2d ",a[j]);
printf("|\n");
Myprintf;
for(i=0;i<M;i++)
{ for(j=0;j<N;j++)
{
if(c[i][j]==-1)
printf("|%2c ",32);
else
printf("|%2d ",c[i][j]);
}
printf("|\n");
}
Myprintf;
printf("\n调入队列为:");
for(i=0;i<K+1;i++)
printf("%3d",queue[i]);
printf("\n缺页次数为:%6d\n缺页率:%16.6f",K+1,(float)(K+1)/N);
printf("\nAre you continuing!\ty?");
if(getchar()=='y')
goto start;
return 0;
}
实验截图:
五、总结:(实验结果分析,个人体会等)
这一次的实验,在两次实验的基础上,我进一步掌握了虚拟存储器的实现方法,又一次
熟悉了LINUX的环境,让我恍然大悟,学习的进步在于一遍一遍的重复与熟悉,在经验的积累基础上,然后寻求知识的掌握和升华,这一次实验内容中,我重点掌握了各种页面置换算法,着重的实现了LRU页面置换算法,比书本知识学习的更有画面感和印象感,而且通过这次试验,能够比较各种页面置换算法的优缺点,将操作系统中所学习的知识真正的做到学以致用,用于实践过程中的各个适合的场合。
实验成绩: 指导教师: 年 月 日
实验名称 |
Linux文件管理 |
专 业 |
软件工程 |
||
姓 名 |
学 号 |
班 级 |
- 实验目的:
掌握Linux文件系统的基本原理、结构和实现方法
掌握Linux文件系统中文件的建立、打开、读/写、执行、属性等系统调用的使用
学会设计简单的文件系统并实现一组操作
通过实验学习文件系统的系统调用命令,提高对文件系统实现功能的理解和掌握
- 实验内容:
设计并实现一个一级文件系统程序,要求实现以下功能:
1. 提供文件创建/删除接口命令create/delete、目录创建/删除接口命令mkdir/rmdir、显示目录内容命令ls等。
2. 创建的文件不要求格式和内容。
三、实验设备及软件环境:
操作系统:windows XP
软件环境:VM虚拟机
四、实验过程及结果:
实验代码:
main.cpp
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include "structure.h"
#include "creat.h"
#include "access.h"
#include "ballfre.h"
#include "close.h"
#include "delete.h"
#include "dir.h"
#include "format.h"
#include "halt.h"
#include "iallfre.h"
#include "install.h"
#include "log.h"
#include "name.h"
#include "open.h"
#include "rdwt.h"
#include "igetput.h"
struct hinode hinode[NHINO];
struct dir dir;
struct file sys_ofile[SYSOPENFILE];
struct filsys filsys;
struct pwd pwd[PWDNUM];
struct user user[USERNUM];
FILE *fd;
struct inode *cur_path_inode;
int user_id;
/*kkkkk*/
unsigned short usr_id;
char usr_p[12];
char sel;
char temp_dir[12];
main()
{
unsigned short ab_fd1,ab_fd2,ab_fd3,ab_fd4,i,j;
char *buf;
int done=1;
printf("\nDo you want to format the disk(y or n)?\n");
if(getchar()=='y')
{
printf("\nFormat will erase all context on the disk \n");
printf("Formating...\n");
format();
printf("\nNow will install the fillsystem,please wait...\n");
install();
printf("\n----Login----\nPlease input your userid:");
scanf("%u",&usr_id);
printf("\nPlease input your password:");
scanf("%s",&usr_p);
/* printf("\nsuccess\n");*/
if(!login(usr_id,usr_p))
return;
while(done)
{
printf("\n Please Select Your Operating\n");
printf(" -1----ls\n -2----mkdir\n -3----change dir\n -4----create file\n -0----Logout\n");/* зЂвт*/
sel=getchar();
sel=getchar();
switch(sel)
{
case '1':
_dir();
break;
case '2':
printf("please input dir name:");
scanf("%s",temp_dir);
mkdir(temp_dir);
break;
case '3':
printf("please input dir name:");
scanf("%s",temp_dir);
chdir(temp_dir);
break;
case '4':
printf("please input file name:");
scanf("%s",temp_dir);
ab_fd1=creat(2118,temp_dir,01777);
buf=(char *)malloc(BLOCKSIZ*6+5);
write(ab_fd1,buf,BLOCKSIZ*6+5);
close(0,ab_fd1);
free(buf);
break;
case '0':
logout(usr_id);
halt();
done = 0;
default:
printf("ERROR!\nNo such command,please try again.\nOr you can ask your teacher for help.\n");
break;
}
}
}
else
printf("User canseled\nGood Bye\n");
}
1.4源码二(或命令)
//create.h
creat(uid,filename,mode)
unsigned int uid;
char *filename;
unsigned short mode;
{
int di_ith,di_ino;
struct inode *inode;
int i,j;
i=0;
while(i<USERNUM)//user[]的值由函数login()注册,参看文件log.h
{
if(user[i].u_uid==uid)
{
user_id=i;
break;
}
i++;
}
if(i==USERNUM)
{
printf("the user id is wrong.\n");
exit(1);
}
di_ino=namei(filename);
if(di_ino!=-1)//文件已经存在
{
inode=iget(di_ino);
if(access(user_id,inode,mode)==0)
{
iput(inode);
printf("\ncreat access not allowed\n");
return 0;
}
for(i=0;i<inode->di_size/BLOCKSIZ+1;i++)
{
bfree(inode->di_addr[i]);
}
for(i=0;i<SYSOPENFILE;i++)
if(sys_ofile[i].f_inode==inode)
{
sys_ofile[i].f_off=0;
}
for(i=0;i<NOFILE;i++)
if(user[user_id].u_ofile[i]==SYSOPENFILE+1)
{
user[user_id].u_uid=inode->di_uid;
user[user_id].u_gid=inode->di_gid;
for(j=0;j<SYSOPENFILE;i++)
if(sys_ofile[j].f_count==0)
{
user[user_id].u_ofile[i]=j;
sys_ofile[j].f_flag=(char)mode;
}
return i;
}
}
else
{
inode=ialloc();
di_ith=iname(filename);
dir.size++;
dir.direct[di_ith].d_ino=inode->i_ino;
inode->di_mode=user[user_id].u_default_mode;
inode->di_uid=user[user_id].u_uid;
inode->di_gid=user[user_id].u_gid;
inode->di_size=0;
inode->di_number=0;
for(i=0;i<SYSOPENFILE;i++)
if(sys_ofile[i].f_count==0)
{
break;
}
for(j=0;j<NOFILE;i++)
if(user[user_id].u_ofile[j]==SYSOPENFILE+1)
{
break;
}
user[user_id].u_ofile[j]=i;
sys_ofile[i].f_flag=(char)mode;
sys_ofile[i].f_count=0;
sys_ofile[i].f_off=0;
sys_ofile[i].f_inode=inode;
return j;
}
return 0;
}
1.5源码三(或命令)
//delete.h
#include <stdio.h>
#include "structure.h"
delete(char *filename)
{
unsigned int dinodeid;
struct inode *inode;
dinodeid=namei(filename);
if(dinodeid!=(int)NULL)
inode=iget(dinodeid);
inode->di_number--;
iput(inode);
}
1.6源码四(或命令)
//dir.h
_dir()
{
unsigned int di_mode;
int i,j,one;
struct inode *temp_inode;
printf("CURRENT DIRECTORY:\n");
for(i=0;i<dir.size;i++)
{
if(dir.direct[i].d_ino!=DIempty)
{
printf("%sDIRSIZ",dir.direct[i].d_name);
temp_inode=iget(dir.direct[i].d_ino);
di_mode=temp_inode->di_mode;
for(j=0;j<9;j++)
{
one=di_mode%2;
di_mode=di_mode/2;
if(one) printf("x");
else printf("-");
}
if(temp_inode->di_mode&&DIFILE==1)
{
printf("%ld\n",temp_inode->di_size);
printf("block chain:");
for(i=0;i<temp_inode->di_size/BLOCKSIZ+1;i++)
printf("%4d",temp_inode->di_addr[i]);
printf("\n");
}
else printf("<dir>\n");
iput(temp_inode);
}
}
}
mkdir(char *dirname)
{
int dirid,dirpos;
struct inode *inode;
struct direct buf[BLOCKSIZ/(DIRSIZ+2)];
unsigned int block;
dirid=namei(dirname);
if(dirid!=-1)//dirid==-1表示没有该目录名存在;
{
inode=iget(dirid);
if(inode->di_mode&DIDIR)
printf("\n%s directory already existed!!\n");
else
printf("\n%s is a file name&can not creat a dir the same name",dirname);
iput(inode);
return 0;
}
dirpos=iname(dirname);
inode=ialloc();
inode->i_ino=dirpos;
dir.direct[dirpos].d_ino=inode->i_ino;
dir.size++;
strcpy(buf[0].d_name,".");
buf[0].d_ino=dirid;
strcpy(buf[1].d_name,"..");
buf[1].d_ino=cur_path_inode->i_ino;
block=balloc();
fseek(fd,DATASTART+block*BLOCKSIZ,SEEK_SET);
fwrite(buf,1,BLOCKSIZ,fd);
inode->di_size=2*(DIRSIZ+2);
inode->di_number=1;
inode->di_mode=user[user_id].u_default_mode;
inode->di_uid=user[user_id].u_uid;
inode->di_gid=user[user_id].u_gid;
inode->di_addr[0]=block;
iput(inode);
return 0;
}
chdir(char *dirname)
{
int dirid;
int temp;
struct inode *inode;
short block;
int i,j,low=0,high=0;
dirid=namei(dirname);
if(dirid==-1)
{
printf("\n%s does not existed\n",dirname);
return 0;
}
inode=iget(dirid);
if(!access(user_id,inode,user[user_id].u_default_mode))
{
printf("\nhas not access to the directory %s",dirname);
iput(inode);
return 0;
}
for(i=0;i<dir.size;i++)
{
for(j=0;j<DIRNUM;j++)
{
temp=dir.direct[j].d_ino;
if(dir.direct[j].d_ino==0||dir.direct[j].d_ino>MAX) break;
}
dir.direct[j].d_ino=0;
}
for(i=0;i<cur_path_inode->di_size/BLOCKSIZ+1;i++)
{
bfree(cur_path_inode->di_addr[i]);
}
i=dir.size;
for(i=0;i<dir.size;i+=BLOCKSIZ/(DIRSIZ+2))
{
block=balloc();
cur_path_inode->di_addr[i]=block;
fseek(fd,DATASTART+block*BLOCKSIZ,SEEK_SET);
fwrite(&dir.direct[i],1,BLOCKSIZ,fd);
}
cur_path_inode->di_size=dir.size*(DIRSIZ+2);
iput(cur_path_inode);
cur_path_inode=inode;
i=inode->di_size/BLOCKSIZ+1;
j=0;
for(i=0;i<inode->di_size/BLOCKSIZ+1;i++)
{
fseek(fd,DATASTART+inode->di_addr[i]*BLOCKSIZ,SEEK_SET);
fread(&dir.direct[j],1,BLOCKSIZ,fd);
j+=BLOCKSIZ/(DIRSIZ+2);
}
return 0;
}
实验结果:
五、总结:
这一次,是操作系统的最后一次实验了,通过这次实验课我对操作系统的喜好更深刻一步,在前三次的基础上我掌握了Linux文件系统的基本原理、结构和实现方法,并且掌握了Linux文件系统中文件的建立、打开、读/写、执行、属性等系统调用的使用,学会设计简单的文件系统并实现一组操作。虽然实验部分的学习结束了,但是我深知自己学习操作系统的道路还没有停止,我会更加努力,知识结合实践,完成更好的成绩。
实验成绩: 指导教师: 年 月 日
相关阅读
今天打开电脑有一阵,正在调试Python程序,突然感觉电脑异常的慢,对于我来说这种速度是相当于的诡异,就像给你一辆飞机,结果你偏偏要用人
近日,坚持自主创新、专注产品化的云计算公司上海云轴信息科技有限公司(简称:ZStack)与天津麒麟信息技术有限公司(TKC)(简称:天津麒麟
学习操作系统:自己动手写操作系统 ->chapter5_e Kernel
前面已经分析过了boot.asm和loader.asm的代码,有Text版本和VGA版本。 Text版本的Kernel书里有,直接看就可以。 本此学习时VGA版本的
操作系统 - http://bbs.pcbeta.com
----》》》1.BigBaiCai_STA_36.exe为大白菜安装包链接:https://pan.baidu.com/s/1wEbjb3YI1atGBBmmAd4O4Q 密码:z794----》》》3.wi