操作系统Linux课程实验报告文档格式.docx

上传人:b****5 文档编号:21466320 上传时间:2023-01-30 格式:DOCX 页数:14 大小:20.93KB
下载 相关 举报
操作系统Linux课程实验报告文档格式.docx_第1页
第1页 / 共14页
操作系统Linux课程实验报告文档格式.docx_第2页
第2页 / 共14页
操作系统Linux课程实验报告文档格式.docx_第3页
第3页 / 共14页
操作系统Linux课程实验报告文档格式.docx_第4页
第4页 / 共14页
操作系统Linux课程实验报告文档格式.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

操作系统Linux课程实验报告文档格式.docx

《操作系统Linux课程实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统Linux课程实验报告文档格式.docx(14页珍藏版)》请在冰豆网上搜索。

操作系统Linux课程实验报告文档格式.docx

wait(&

state);

}

实验内核模块

实验步骤:

(1).编写内核模块

文件中主要包含init_clock(),exit_clock(),read_clock()三个函数。

其中init_clock(),exit_clock()负责将模块从系统中加载或卸载,以及增加或删除模块在/proc中的入口。

read_clock()负责产生/proc/clock被读时的动作。

(2).编译内核模块Makefile文件

#Makefileunder

ifneq($(KERNELRELEASE),)

#kbuildsyntax.dependencyrelationshsipoffilesandtargetmodulesarelistedhere.

obj-m:

=

else

PWD:

=$(shellpwd)

KVER?

=$(shelluname-r)

KDIR:

=/lib/modules/$(KVER)/build

all:

$(MAKE)-C$(KDIR)M=$(PWD)modules

clean:

rm-rf.*.cmd*.o*.*.ko.tmp_versions*.symvers*.order

endif

编译完成之后生成模块文件。

(3).内核模块源代码

#include<

linux/>

asm/>

#defineMODULE

#defineMODULE_VERSION"

"

#defineMODULE_NAME"

clock"

structproc_dir_entry*my_clock;

intread_clock(char*page,char**start,off_toff,intcount,int*eof,

void*data){

intlen;

structtimevalxtime;

do_gettimeofday(&

xtime);

len=sprintf(page,"

%d%d\n"

,;

printk("

clock:

read_func()\n"

returnlen;

}

structproc_dir_entry*clock_proc_file;

intinit_clock(void)

{

clock_proc_file=create_proc_read_entry("

0,NULL,read_clock,NULL);

return0;

voidexit_clock(void)

remove_proc_entry("

clock_proc_file);

module_init(init_clock)

module_exit(exit_clock)

MODULE_LICENSE("

GPL"

(4).编译内核模块

#make

(5).加载内核模块

在系统root用户下运行用户态模块命令装载内核模块

#insmod

(6).测试

在终端中输入以下命令:

#cat/proc/clock

(7).卸载内核模块

在系统root用户下运行用户态模块命令卸载内核模块

#rmmod

实验系统调用

(1).添加新调用的源代码

在./中添加相应的调用代码

asmlinkageintsys_xwlcall(structtimeval*tv)

structtimevalktv;

ktv);

copy_to_user(tv,&

ktv,sizeof(ktv));

printk(KERN_ALERT"

PID%ldcalledsys_xwlcall()./n"

(long)current->

pid);

(2).连接系统调用

a、修改./,

在系统调用列表后面相应位置添加一行,这样在用户空间做系统调用时就不需要知道系统调用号了,如果在用户空间指明了调用号,就可以省略这一步,实际上我就没写:

#define__NR_xwlcall338

新增加的调用号位338

b、修改./

在ENTRY(sys_call_table)清单最后添加一行,这步至关重要,338就是这里来的:

.longsys_xwlcall

(3).重建新的Linux内核

先安装好编译内核必要的软件包:

#sudoapt-getinstallbuild-essentialkernel-packagelibncurses5-dev

复制当前内核的配置文件

#cp/boot/config-`uname-r`./.config

保存配置文件

#sudomakemenuconfig

使用debian的的内核编译方法,要简单很多

#sudomake-kpkg-initrd--initrd--append-to-version=xwlcall

kernel_imagekernel-headers

运行以下deb包,安装内核镜像和模块:

运行以下deb包,安装内核头文件:

运行以下命令,使内核启动时能调用模块,比如硬件驱动:

#sudoupdate-initramfs-c-k此次编译的内核采用ubuntu默认配置文件,通用性非常好,可以拷贝到大部分x86机器上安装。

安装后系统自动会修改grub启动选单。

4.重建引导信息

a、安装deb包就自动重建引导信息了,无须另行处理。

b、如果仍然不放心,可以运行

#update-grub

5.重新引导从新的内核进入

6.修改系统调用表

7.测试

实验Shell编程实验(进程管理实验)

1、实验目的

通过编写shell程序,了解子进程的创建和父进程与子进程间的协同,获得多进程程序的编程经验。

2、实验内容1

设计一个简单的shell解释程序,能实现基本的bsh功能。

3、实验原理

将每一条命令分子段压入argv栈。

然后再子进程中调用execvp()来实现该命令的功能。

4、代码(源代码清单)

#defineBUFFERSIZE256

n"

buf);

计思路

通过fork()创建子进程,用execvp()更改子进程代码,用wait()等待子进程结束。

这三个系统调用可以很好地创建多进程。

另一方面,编写的Shell要实现管道功能,需要用pipe()创建管道使子进程进行通信。

2.源代码清单

#defineBUFFERSIZE256

exit

(1);

n=0;

argv2[n++]=cmd2;

while(argv2[n++]=strtok(NULL,"

\t\n"

));

pipe(fd);

if(fork()==0){

dup2(fd[0],0);

验步骤

(1)、安装GDB

(2)、编写观测程序

(3)、按照指令手册进行观察操作

2.观测程序源代码

charstr[50]="

HelloLinux."

;

intmain()

intnum=10;

while(num--){

printf("

%s\n"

str);

验结果及分析

(1).Gdb程序观察一个程序文件的内容和结构

结果截图:

(2).GDB观察程序内存映象的内容和结构

(3).在Linux下,用free和vmstat命令观察内存使用情况

(4).在Linux下,查看/proc与内存管理相关的文件,并解释显示结果

实验观察实验(进程通信)

在Linux下,用ipcs()命令观察进程通信情况,了解Linux基本通信机制

实验结果(截图):

实验IO系统编程实验

编写一个daemon进程,该进程定时执行ps命令,然后将该命令的输出写至文件F1尾部。

通过此实验,掌握LinuxI/O系统相关内容。

2、实验内容

3、实验原理

在这个程序中,首先fork一个子程序,然后,关闭父进程,这样,新生成的子进程被交给init进程接管,并在后台执行。

新生成的子进程里,使用system系统调用,将ps的输出重定向,输入到里面。

4、实验步骤

编写

代码如下:

intmain(intargc,char*argv[])

inti,p;

p=fork();

if(p>

0){

exit(0);

elseif(p==0){

for(i=0;

i<

100;

i++){

sleep(100);

system("

ps>

"

else{

perror("

Createnewprocess!

return1;

编译程序

#gcc-odaemon

执行程序

#./daemon

实验代码分析(文件系统管理实验)

1.实验目的

了解与文件管理有关的Linux内核模块的代码结构。

2.实验结果(源代码分析)

A.创建文件模块分析

5780/*creatsystemcall*/

5781Creat()

5782{

5783resister*ip;

5784externuchar;

5785

5786ip=namei(&

uchar,1);

5787if(ip==NULL){

5788if

5789return;

5790ip=maknode[1]&

07777&

(~ISVTX));

5791if(ip==NULL)

5792return;

5793open1(ip,FWRITE,2);

5794}else

5795open1(ip,FWRITE,1);

5796}

第5786:

“namei”(7518)将一路径名变换成一个“inode”指针。

“uchar”是一个过程的

名字,它从用户程序数据区一个字符一个字符地取得文件路径名。

5787:

一个空“inode”指针表示出了一个错,或者并没有具有给定路径名的文件存在。

5788:

对于出错的各种条件,请见UMP的CREAT(II)。

5790:

“maknode”(7455)调用“ialloc”创建一内存“inode”,然后对其赋初值,并使

其进入适当的目录。

注意,显式地清除了“粘住”位(ISVTX)。

B.删除文件rm模块分析

3510unlink()

3511{

3512resister*ip,*pp;

3513externuchar;

3514

3515pp=namei(&

uchar,2);

3516if(pp==NULL)

3517return;

3518prele(pp);

3519ip=iset(pp->

dev,

3520if(ip==NULL)

3521panic(*unlink–iset*);

3522if((ip->

i_mode%IFMT)==IFDIR&

&

!

suser())

3523gotoout;

3524[1]=-DIRSIZ+2;

3525=&

3526=DIRSIZE+2;

3527=0;

3528writei(pp);

3529ip->

i_nlink--;

3530ip->

i_flag=!

IUPD;

3531

3532out:

3533iput(pp);

3534iput(ip);

3535}

新文件作为永久文件自动进入文件目录。

关闭文件不会自动地造成文件被删除。

当内存“inode”项中的“i_nlink”字段值为0并且相应文件未被打开时,将删除该文件。

在创建文件时,该字段由“maknode”赋初值为1。

系统调用“link”(5941)可将其值加1,系统调用“unlink”(3529)则可将其值减1。

创建临时“工作文件”的程序应当在其终止前执行“unlink”系统调用将这些文件删除。

注意,“unlink”系统调用本身并没有删除文件。

当引用计数(i_count)被减为0时(7350、7362),才删除该文件。

为了减少在程序或系统崩溃时遗留下来的临时文件所带来的问题,程序员应当遵守下列约定:

(1)在打开临时文件后立即对其执行“unlink”操作。

(2)应在“tmp”目录下创建临时文件。

在文件名中包括进程标识数就可构成一惟一文件名

C.读写模块分析

5711Read()

5712{

5713rdwr(FREAD);

5714}

5720Write()

5721{

5722rdwr(FWRITE);

5723}

5731rdwr(mode)

5732{

5733resister*fp,m;

5734

5735m=mode;

5736fp=setf[R0]);

5737if(fp==NILL)

5738return;

5739if((fp->

f_flag&

m==0){

5740=EBADF;

5741return;

5742}

5743=[0];

5744=[1];

5745=0;

5746if(fp->

FPIPE){

5747if(m==FREAD)

5748readp(fp);

5749writep(fp);

5750}else{

5751[1]=fp->

f_offset[1];

5752[0]=fp->

f_offset[0];

5753if(m==FREAD)

5754readi(fp->

f_inode);

5755writei(fp->

5756dpadd(fp->

f_offset,[1]–;

5757}

5758[R0]=[1]–;

5759}

“read”系统调用的基本工作过程为:

……read(f,b,n);

/*用户程序*/

{发生陷入}

2693trap{#3系统调用}

5711read();

5713rdwr(FREAD);

用户进程执行系统调用激活运行在核心态的“trap”。

“trap”识别#3系统调用,然后通过“trapl”调用例程“read”,它又调用“rdwr”。

“rdwr”包含了很多“read”和“write”操作共用的代码。

它调用“getf”(6619)将用户进程提供的文件标识变换成“file”数组中一项的地址。

注意,该系统调用的第1个参数是以不同于另外2个参数的方式传送的。

将“”设置为0,这表示此操作的目的地址在用户地址空间中。

在以一个inode指针参数调用“readi”后,将要求传送的字符数减去剩余未传输字符数(在_count中),加至文件位移量中。

6221readi

6239lbn=lshift,-9);

6248on=[i]&

0777;

6241n=min(512–on,;

6250dn=ip->

i_dev;

6258bp=bread(dn,bn);

6260iomove(bp,on,n,B_READ);

6261brelse(bp);

“readi”将文件位移量分解成两部分:

一个逻辑块号“lbn”,以及一个块内索引“on”。

将要传输的字符数是下而两个值中的较小者:

“_count”和块内尚余字符数(在这种情况下以后还必须读其他块,此处没有进一步对此说明),还应考虑尚余留在文件中的字符数(对这种情况也未进一步说明)。

“dn”是存储在“inode”中的设备编号,“bn”是在该设备(磁盘)上的实际块号,这是由“bmap”(6415)用“lbn”计算得到的。

对“bread”的调用找到所要求的磁盘块,若需要,则将其从磁盘复制到内存中。

“iomove”(6364)将适当数量的字符传送至目的区,然后执行计数操作。

“read”和“write”执行的操作有很多相似之处,两者共享很多代码。

系统调用“read”(5711)和“write”(5720),然后立即调用“rdwr”,它执行下列操作:

5736:

将用户程序文件标识变换成指向相应文件表项的指针。

5739:

检查所要求的操作(读或写)是否与文件打开时的读/写方式符合。

5743:

用各参数在“u”中设置几个标准单元。

5746:

从此开始对“管道”文件进行特殊处理。

5755:

按读、写要求分别调用“readi”或“writei”。

5756:

更新文件位移量,使其增加实际传送的字符数,同时也将实际传送的字符数返回。

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

当前位置:首页 > 医药卫生 > 基础医学

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

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