操作系统实验指导书.docx

上传人:b****8 文档编号:30079399 上传时间:2023-08-04 格式:DOCX 页数:20 大小:183.41KB
下载 相关 举报
操作系统实验指导书.docx_第1页
第1页 / 共20页
操作系统实验指导书.docx_第2页
第2页 / 共20页
操作系统实验指导书.docx_第3页
第3页 / 共20页
操作系统实验指导书.docx_第4页
第4页 / 共20页
操作系统实验指导书.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

操作系统实验指导书.docx

《操作系统实验指导书.docx》由会员分享,可在线阅读,更多相关《操作系统实验指导书.docx(20页珍藏版)》请在冰豆网上搜索。

操作系统实验指导书.docx

操作系统实验指导书

 

操作系统实验指导书

 

实验1安装Linux操作系统

一、实验目的

在虚拟机Vmware或者VirtualBox上安装Unbuntu9.1操作系统,后续实验都将在此环境上进行。

通过实验,要求:

1、掌握在虚拟机上安装操作系统的方法;

2、学会安装Linux系统;

3、学会启动Linux系统;

4、学会在宿主机WindowsXP操作系统下,与虚拟机上安排的Ubuntu共享文件的方法。

二、实验内容

1、把ubuntu安装至虚拟机上。

●加载安装ubuntu操作系统的ISOIMG文件

●启动ubuntu虚拟机

●按提示分阶段装入系统

2、在Windows下通过网络磁盘来访问ubuntu共享文件夹

●在虚拟系统Ubuntu下新建一个文件夹,右击该文件夹,选择属性,共享,启用“共享此目录”,并允许他人在此共享里写数据。

 

注:

共享时需要Samba的支持,系统会提示安装。

●安装完成Samba后,需要重启ubuntu才能生效。

此时回到XP时可在网上邻居里看到一个***-desktopserver(Samba,Ubuntu)的共享目录。

 

●返回WindowsXP系统,右击“网上邻居”,选择“映射网络驱动器”,

●在“浏览”里找到刚才在Ubuntu下共享的文件夹,选择后完成映射,

●这时打开“我的电脑”会发现多了一个“网络驱动器”,如同我们的硬盘一样。

 

● 这时你可以在XP系统里复制几个文件到相应的网络驱动器,然后进入Ubuntu系统,就能看到我们刚才复制的文件了;当然,我们也可以往ubuntu共享文件夹里放文件,在XP系统使用。

注:

在创建文件共享的时候,注意主机的网卡一定要打开,否则创建共享是不能成功的

实验2Linux系统中程序编辑、编译与调试工具

一、实验目的

1、熟悉使用Linux字符界面、窗口系统的常用命令。

2、熟悉运用Linux常用的编程工具。

3、掌握在Linux操作系统环境上编辑、编译、调试、运行一个C语言程序的全过程。

二、实验内容

1、熟悉开机后登录Linux系统和退出系统的过程;

2、掌握一种Linux的编辑器,特别是字符界面的vi工具的使用(详见VI简易使用手栅);

3、掌握GCC编译器的基本用法(详见GCC使用手册及常用命令行);

4、掌握GDB调试程序的方法(详见GDB调试程序手册)。

要求在实验报告上完整地进行一个数据结构中c程序的调试,源代码不能少于50行。

实验3进程并发与同步

一、实验目的

1、加深对进程概念的理解,区分进程并发执行与串行执行;

2、掌握进程并发执行的原理,理解进程并发执行的特点;

3、了解fork()系统调用的返回值,掌握用fork()创建进程的方法;熟悉wait、exit等系统调用;

4、能利用相应的系统调用实现进程树与进程间的同步。

二、实验内容

1、编写一C语言程序,实现在程序运行时通过系统调用fork()创建两个子进程,使父、子三进程并发执行,父亲进程执行时屏幕显示“Iamfather”,儿子进程执行时屏幕显示“Iamson”,女儿进程执行时屏幕显示“Iamdaughter”。

要求多次连续反复运行这个程序,观察屏幕显示结果的顺序,直至出现不一样的情况为止。

要求有运行结果截图与结果分析

2、连续4个fork()的进程家族树,family1-1.c程序清单如下:

#include

main()

{

fork();

fork();

fork();

fork();

printf(“A\n”);

}

请根据程序运行结果,画出进程家族树,并分析原因。

3、修改程序1,在父、子进程中分别使用wait、exit等系统调用“实现”其同步推进,父进程必须等待儿子进程与女儿进程结束,才可以输出消息。

写出相应的同步控制,并分析运行结果。

4、创建一个子进程,并给它加载程序,其功能是调用键盘命令“ls-l”,已知该键盘命令的路径与文件名为:

/bin/ls。

父进程创建子进程,并加载./child2程序。

写出相应的程序代码并分析程序运行结果。

三、系统调用

创建子进程系统调用:

fork()

格式

intfork();

返回值

=0

创建成功,从子进程返回

>0

创建成功,从父进程返回,其值为子进程的PID号

=-1

创建失败

子进程创建时操作系统的工作:

✧检查同时运行的进程数目,若超过系统设定值,则创建失败,返回-1;

✧为子进程分配进程控制块task_struct结构,并赋予唯一进程标识符pid;

✧子进程继承父进程打开的所有文件及资源,对父进程的当前目录和所有已打开系统文件表项中的引用记数加1;

✧为子进程创建进程映像:

⏹创建子进程映像静态部分:

复制父进程映像静态部分

⏹创建子进程映像动态部分:

初始化task_struct结构

⏹结束创建,置子进程为内存就绪状态,插入就绪队列,作为一个独立的进程被系统调度。

✧若调用进程(父进程)返回,则返回创建的子进程标识符pid值(此时返回值>0);

✧若子进程被调度执行,则将其U区计时字段初始化然后返回(此时返回值=0)。

进程睡眠系统调用:

sleep()

格式

sleep(n);

参数

n表示延时的秒数

功能

进程睡眠n秒

 

进程终止系统调用:

exit(status)

格式

voidexit(intstatus);

参数

status是子进程向父进程发送的终止信息,父进程使用wait()系统调用来接收这个信息

头文件

#include

功能

将进程置僵死状态

释放其所占有的资源

向父进程发本进程死信号,并发送信息status给父进程,将自己及自己的子进程运行CPU的时间总和留待父进程使用wait()收集

子进程终止时操作系统做以下工作:

✧关闭软中断:

因为进程即将终止而不再处理任何软中断信号;

✧回收资源:

关闭所有已打开文件,释放进程所有的区及相应内存,释放当前目录及修改根目录的索引节点;

✧写记帐信息:

将进程在运行过程中所产生的记帐数据(其中包括进程运行时的各种统计信息)记录到一个全局记帐文件中;

✧置该进程为僵死状态:

向父进程发送子进程死的软中断信号,将终止信息status送到指定的存储单元中;

✧转进程调度:

因为此时CPU已经被释放,需要由进程调度进行CPU再分配。

父进程等待子进程终止系统调用:

wait()与waitpid()

格式1

pid_twait([int*stat_addr,]0);

参数

*stat_addr中存放exit()所发来终止信号stat的值。

返回值

>=0

表示有子进程终止,其值为终止子进程的pid号

=-1

表示无子进程终止

头文件

#include

#include

功能

父进程使用它等待任意一个子进程终止,如果在执行wait()之前已经有一个子进程结束了,则对其做善后处理,并返回子进程的pid号,如果没有则返回-1,该进程阻塞,插入等待子进程终止的队列,当有子进程终止时被唤醒。

在&stat_addr中保留了子进程僵死时的终止信息(不是返回值)。

注意:

一个wait()只能用来等待一个子进程终止,如果等待多个子进程终止则需要使用多个wait()。

格式2

pid_twaitpid(pid_tpid,int*stat_addr,intoptions);

参数

pid=0

等待与父进程同组的子进程

pid=-1,options=0

等同于wait(),等待任意子进程

pid>0

等待给定pid号的子进程

功能

等待指定pid的子进程终止

说明:

1)若父进程仅仅只是等待任意一个子进程结束,而不需要取子进程发来的信号,则可以简单地使用wait(0)。

2)如果该进程没有创建自己的子进程就不能使用wait()或waitpid(),否则系统会返回一个出错信息。

3)如果要取子进程执行exit()后所发来的终止信号stat,可以使用*stat来取该变量中的值,而不能使用wait()的返回值,因为wait()的返回值是该终止子进程的pid号。

将指定的可执行文件加载到指定进程映像中,覆盖该进程中原有的程序

系统调用:

execl()、execle()、execlp()、execv()、execve()与execvp()

功能

将一个指定的程序装入调用它的进程的映像中,用这个可执行文件的副本去覆盖该进程的程序空间,从而改变调用进程的执行代码,使调用进程执行新引入的可执行程序(二进制代码文件)

内核在响应这组系统调用后做以下工作:

1)根据给出的路径名找到指定的可执行文件,检查该文件是否可执行,用户是否具有执行权限(该文件必须是编译连接后的二进制代码)。

2)将该文件载入到调用它的进程映像中覆盖其原来的程序。

3)为该程序的执行设置参数数组和环境变量。

4)启动该进程进入新的程序入口点去执行。

此组函数执行时,如果加载成功则直接执行,没有返回;若加载不成功则返回-1。

格式1

execv(file,argv)

参数

char*file

指向文件全名(路径名/文件名)的指针

char*argv[n]

指向命令及参数的指针

功能

1)执行参数指定的命令或文件。

2)用该命令或可执行文件的副本覆盖调用它的子进程的映像

返回值

=-1

表示错误返回

头文件

#include

格式2

execl(“路径名/文件名”,0)

说明

功能、返回值、头文件均同格式1

使用方法:

1)事先准备好子进程要执行的程序,并将它编译连接成可执行文件,记下该文件的路径名和文件名。

如果不带参数则可以直接使用execl(),带参数则使用execv()。

2)在父进程创建子进程之前,在程序中事先定义子进程要执行的程序文件的文件标识符path和参数数组argv[],其中的环境值可以用NULL取代。

如果不带参数使用execl(),则这一步可以不做。

3)创建子进程后,在子进程的分支中,如果不带参数使用execl(filepath,0),如果带参数则使用execv(filepath,argv)来实现用指定的程序filepath覆盖子进程映像中原有的程序。

   实验4进程通信

一、实验目的

1、加深理解进程通信的方法与原理;

2、掌握如何利用管道机制、消息缓冲队列、共享存储区机制进行进程间的通信。

二、实验内容

   1、了解系统调用pipe()、msgget()、msgsnd()、msgrcv()、msgctl()、shmget()、shmat()、shmdt()、shmctl()的功能和实现过程。

2、编写一C语言程序,使其用管道来实现父子进程间通信。

子进程向父进程发送字符串“issendingamessagetoparent!

”;父进程则从管道中读出子进程发来的消息,并将其显示到屏幕上,然后终止。

3、运行该程序,观察、记录并简单分析其运行结果。

三、有名管道、无名管道系统调用

1、创建无名管道的系统调用

创建无名管道的系统调用:

pipe()

格式

intpipe(int管道名[2]);

返回值

0

正确返回

1

错误返回

参数说明

管道名[1]:

为写入端

管道名[2]:

为读出端

功能

创建一个管道名为指定名称的无名管道,以便于创建管道的进程及其子孙进程共享

头文件

include

●当进程向管道中写时,数据就复制不予考虑了共享的数据页;

●从管道中读时,字节从共享页中按照FIFO的顺序复制出来。

●当所有进程完成管道的操作后,管道的i结点和共享数据页被释放。

2、读写管道的系统调用

读写管道的系统调用:

write()、read()

格式

write(管道名[1],buf,size)

read(管道名[0],buf,size)

参数说明

buf:

程序中定义的字符型数组或缓冲区;

size:

读写的信息长度

说明

管道为临界资源,父子进程之间除了需要读写同步以外,在对管道进行读写操作时还需要互斥进入。

为了保证管道操作过程中不至于因为用户的疏忽而死锁,Linux采用以下措施来避免死锁:

●当进程因读或写等待时,要检查管道的另一端是否已经关闭,如果发现对方已经关闭则直接返回,不再等待。

●当进程关闭管道时,要检查管道的另一端是否正处于等待状态,如果是,则要先唤醒对方,然后再关闭管道。

●如果进程需要实现互斥,因为管道是文件,可以使用对文件上锁和开锁的系统调用。

3、文件上锁、开锁系统调用

文件上锁、开锁系统调用:

lockf()

格式

lockf(files,function,size)

参数说明

files

是需要加以封锁的文件描述符,此处可以是管道的读写端口

function

为1表示上锁,为0表示开锁

size

表示锁定或开销的字节数,其值为0则表示文件全部内容

4、命名管道创建系统调用

命名管道创建系统调用:

mkfifo()

格式

intmkfifo(constchar*pathname,mode_tmode);

功能

专门用于创建FIFO

参数说明

mode

权限值,如0777表示所有用户都可读、可写、可执行

返回值

正确返回0,错误返回-1.

头文件

#include

#include

mknod用于创建一般的设备文件

四、Linux消息缓冲通信的系统调用

1、创建一个消息队列或获取已存在消息队列的标识

创建消息队列/获取已存在消息队列的系统调用:

msgget()

命令格式

intmsgget(key_tkey,intmsgflag);

功能

创建标识为key值的消息队列或者获取已存在的消息队列的描述符msgid

返回值

正确返回该消息队列的描述符msgid;

错误返回-1。

语句格式

msgid=msgget(key,msgflag);

参数说明

msgqid

该系统调用返回的消息队列描述符,-1表示失败;

key

用户指定的消息队列标识符,为一正整数,其值可以由用户指定,如果使用IPC_PRIVATE则由系统产生key值;

flag

用户设置的标志或访问方式,其值由操作权限和控制命令进行或运算得到

头文件

#include

#include

操作允许权八进制数

操作允许权八进制数

用户可读0400

用户可写0200

小组可读0040

小组可写0020

其他可读0004

其他可写0002

控制命令值

IPC_CREAT(创建)0001000

2、发送一条消息到指定的消息队列

发送一条消息到指定的消息队列系统调用:

msgsnd()

命令格式

intmsgsnd(intmsgid,structmsgbuf*msgp,intsize,intflag);

功能

发送一个消息给指定描述符的消息队列。

将msgp所指向的msgbuf中的消息复制到消息数据结构并挂到指定消息队列尾,唤醒等待消息的进程

参数说明

msgqid

执行msgget()返回的消息队列的描述符

msgp

指向用户存储区的一个消息缓冲msgbuf的指针,在msgbuf中包含消息类型和消息正文

size

由msgp指向的数据结构中字符数组的长度(消息长度)

flag

规定当核心用尽内部空间时应执行的动作。

例如:

若在flag中设置了IPC_NOWAIT,则当消息队列中的字节数超过最大值msgsnd立即返回,否则msgsnd睡眠。

flag可置0。

头文件

#include

#include

3、从消息队列接收消息

从消息队列接收消息的系统调用:

msgrcv()

命令格式

intmsgrcv(intmsgid,structmsgbuf*msgp,intsize,inttype,intflag);

功能

从指定的消息队列接收一个消息。

将消息复制到msgp所指的msgbuf中,从消息队列中删除此消息,若消息未到则调用进程阻塞,并将该进程插入等待消息队列尾。

参数说明

msgid

消息队列描述符;

msgp

用来存放要接收消息的用户msgbuf的地址;

size

msgp中数据数组的大小;

type

用户要读取的消息类型

=0表示接收队列的第一个消息;

>0表示接收类型type的第一个消息;

<0表示接收小于或等于|type|的最低类型的第一个消息

flag

规定若该队列无消息,操作系统核心应当做什么,可设置为0.

头文件

#include

#include

4、对消息队列的操作

对消息队列操作的系统调用:

msgctl()

命令格式

intmsgctl(intmsgid,intcmd,structmsgid_ds*buf);

功能

查询一个消息队列的状态;设置或修改它的状态;撤消一个消息队列

返回值

函数调用成功返回0;不成功返回-1.

参数说明

msgid

该消息队列的描述符;

cmd

规定命令的类型

●IPC_STAT查询消息队列状态,将与msgid相关联的消息队列首标读入buf;

●IPC_SET设置或修改消息队列状态,设置有效用户、组标识、操作允许权,及字节数;

●IPC_RMID撤消描述符为msgid的消息队列;

buf

含有控制参数或查询结果的用户缓冲区的地址,可设置为0

头文件

#include

#include

注意:

设置和撤消消息队列的进程需要有一定的权限,如超级用户、具有有效用户ID、符合msg_perm权限设置等。

四、共享内存通信的系统调用

1、创建或获取一个共享内存

创建/获取一个共享内存的系统调用:

shmget()

命令格式

shmget(key,size,flag);

功能

获得一个内部标识为shmid的共享存储区

说明

该函数创建的共享内存区域并没有立即分配物理内存,而是创建一个文件对象shm_file来描述该区域。

Shm_file文件并不属于磁盘文件,而是由内存页面组成,因此当系统亲面时,其中的内容也随之消失。

语句格式

intshmid=intshmget(key_tkey,intsize,intflag);

参数说明

key

共享存储区关键字,可以由用户指定,如果使用IPC_PRIVATE,则其值由系统产生。

size

存储区的大小(字节数)。

如果存储区定义为字符型,则大小为定义的字符个数;如果存储区定义为整型,大小可以使用sizeof(int)加以定义。

flag

用户设置的标志或访问方式,与消息缓冲shmget中的含义相同。

可以使用066|IPC_CREAT,表示任意进程可读可写。

返回值

正确时返回共享存储区的内部标识符shmid,错误时返回-1。

头文件

#include

#include

2、将共享内存附接到进程的虚拟地址空间

将共享内存附接到进程虚拟地址空间的系统调用:

shmat()

命令格式

字符型共享内存

shmat(intshmid,char*shmaddr,intmsgflg,ulong*raddr);

数值型共享内存

shmat(intshmid,int*shmaddr,intmsgflg,ulong*raddr);

功能

逻辑上将内部标识符为shmid的共享存储区附接到进程的虚拟地址空间shmaddr

语句格式

字符型共享内存

viraddr=(char*)shmat(shmid,shmaddr,shmflag);

数值型共享内存

viraddr=(int*)shmat(shmid,shmaddr,shmflag);

参数说明

shmid

共享存储区的描述符,可以由shmget()的返回值得到。

shmaddr

用户提供的共享存储区附接的虚地址。

若shmaddr为0,则由系统选择一个适当的地址来附接该存储区。

shmflag

规定了对该存储区的操作权限,以及系统是否要对用户规定的地址执行舍去操作。

如果shmflag中设置了SHM_RND,则表示操作系统在必要时舍去这个地址;如果设置SHM_RDONLY则表示只允许读,shmflag为0表示可读可写。

viraddr

附接的虚地址。

若定义为char*viraddr,则该共享内存作为字符存储区使用;若定义为int*viraddr,则该共享内存作为整型存储区使用。

返回值

正确时返回共享存储区附接后的虚地址,错误时返回-1。

头文件

#include

#include

3、将共享内存从进程的地址空间断开

将共享内存从进程地址空间断开的系统调用:

shmdt()

命令格式

shmdt(viraddr);

功能

将一个共享存储区从指定进程的虚拟地址空间断开

参数说明

viraddr

系统调用shmat()所返回的虚地址

返回值

正确时返回0,错误时返回-1。

头文件

#include

#include

4、对共享内存的操作

对共享内存操作的系统调用:

shmget()

命令格式

shmctl(intshmid,intcmd,structshmid_ds*buf)

功能

对与共享存储区关联的各种参数进行操作,从而对共享存储区进行控制,包括删除共享存储区

参数说明

shmid

共享存储区的内部标识符,由shmget()调用返回

buf

用户级数据结构地址,其结构类型与系统定义的shmid_ds一致,可以用0

cmd

规定操作的类型。

其规定如下:

●IPC_STAT:

返回包含在指定的shmid相关数据结构中的状态信息,并把它放置在用户存储区中的*buf指针所指的数据结构中。

执行此命令的进程必须有读取允许权。

●IPC_SET:

对于指定的shmid,为它设置有效用户和小组标识符和操作存取权。

●IPC_RMID:

删除指定的shmid以及与它相关的共享存储区的数据结构。

●SHM_LOCK:

在内存中锁定指定的共享存储区,必须是超级用户才可以进行此项操作。

返回值

正确时返回0,错误时返回-1。

头文件

#include

#include

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1