实验名称 |
Linux 进程创建 |
专业 |
软件工程 |
||
姓名 |
|
学号 |
|
班级 |
|
加深对进程概念的理解
练习使用fork()系统调用创建进程
练习Linux操作系统下C程序设计
二、实验内容:
使用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
1. fork()函数:创建一个新进程.
调用格式:
#include
#include
int fork();
返回值:
正确返回时,等于0表示创建子进程,从子进程返回的ID值;大于0表示从父进程返回的子进程的进程ID值。
错误返回时,等于-1表示创建失败
2. wait()函数:用来控制父进程与子进程的同步。在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原程序。
调用格式:
#include
#include
(pid_t) wait(int *statloc);
返回值:正确返回时大于0表示子进程的进程ID值;等于0表示其他。错误返回时等于-1表示调用失败。
3. exit()函数:进程结束最长调用的函数,在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。
调用格式:
#include
void exit(int status);
其中,status为进程结束状态。
3.尝试编写斐波那契数列
实验代码:
#include
#include
#include
#include
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
#include
int fork();
正确返回时,等于0表示创建子进程,从子进程返回的ID值;大于0表示从父进程返回的子进程的进程ID值。
错误返回时,等于-1表示创建失败
2. wait()函数:用来控制父进程与子进程的同步。
在父进程中调用wait()函数,则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,会产生一个终止状态字,系统会向父进程发出SIGCHLD信号。当接到信号后,父进程提取子进程的终止状态字,从wait()函数返回继续执行原程序。
调用格式:
#include
#include
(pid_t) wait(int *statloc);
返回值:正确返回时大于0表示子进程的进程ID值;等于0表示其他。错误返回时等于-1表示调用失败。
3. exit()函数:进程结束最长调用的函数。在main()函数中调用return,最终也是调用exit()函数。这些都是进程的正常终止。在正常终止时,exit()函数返回进程结束状态。
#include
void exit(int status);
其中,status为进程结束状态。
4. kill()函数:用于删除执行中的程序或者任务。
#include
kill(int PID, int IID);
其中,PID是要被杀死的进程号,IID为向将被杀死的进程发送的中断号。
5. signal()函数:允许调用进程控制软中断信号的处理。
#include
int sig;
void (*func)();
signal(sig, function);
function:在该进程中的一个函数地址,在核心返回用户态时,它以软件中断信号的序号作为参数调用该函数。
sig的值是下列之一:
6. pipe()函数:用于创建一个管道
#include
pipe(int fp[2]);
其中,fp[2]是进程使用的文件描述符数组,fp[0]用于写,fp[1]用于读。
错误返回时,-1表示调用失败
实验代码:
#include
#include
#include
#include
#include
#include
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
#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 { b[i].num=-1; b[i].time=N-i-1; } for(i=0;i for(j=0;j c[i][j]=-1; } /*取得在内存中停留最久的页面,默认状态下为最早调入的页面*/ int GetMax(Page *b) { int i; int max=-1; int tag=0; for(i=0;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 { 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 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 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 { Lru(a[i],b); c[0][i]=a[i]; /*记录当前的内存单元中的页面*/ for(j=0;j c[j][i]=b[j].num; } /*结果输出*/ printf("内存状态为:\n"); Myprintf; for(j=0;j printf("|%2d ",a[j]); printf("|\n"); Myprintf; for(i=0;i { for(j=0;j { if(c[i][j]==-1) printf("|%2c ",32); else printf("|%2d ",c[i][j]); } printf("|\n"); } Myprintf; printf("\n调入队列为:"); for(i=0;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 #include #include #include #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 { 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 { bfree(inode->di_addr[i]); } for(i=0;i if(sys_ofile[i].f_inode==inode) { sys_ofile[i].f_off=0; } for(i=0;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 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 if(sys_ofile[i].f_count==0) { break; } for(j=0;j 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 #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 { 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 printf("%4d",temp_inode->di_addr[i]); printf("\n"); } else printf(" 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 { for(j=0;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 { bfree(cur_path_inode->di_addr[i]); } i=dir.size; for(i=0;i { 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 { 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文件系统中文件的建立、打开、读/写、执行、属性等系统调用的使用,学会设计简单的文件系统并实现一组操作。虽然实验部分的学习结束了,但是我深知自己学习操作系统的道路还没有停止,我会更加努力,知识结合实践,完成更好的成绩。 实验成绩: 指导教师: 年 月 日