2嵌入式操作系统实验指导书更新文档格式.docx

上传人:b****6 文档编号:18068342 上传时间:2022-12-13 格式:DOCX 页数:14 大小:105.30KB
下载 相关 举报
2嵌入式操作系统实验指导书更新文档格式.docx_第1页
第1页 / 共14页
2嵌入式操作系统实验指导书更新文档格式.docx_第2页
第2页 / 共14页
2嵌入式操作系统实验指导书更新文档格式.docx_第3页
第3页 / 共14页
2嵌入式操作系统实验指导书更新文档格式.docx_第4页
第4页 / 共14页
2嵌入式操作系统实验指导书更新文档格式.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

2嵌入式操作系统实验指导书更新文档格式.docx

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

2嵌入式操作系统实验指导书更新文档格式.docx

(17)插入模式下输入“Hello,thisisviworld!

”.

(18)返回命令行模式。

(19)向下查找字符串“0:

wait”。

(20)再向上查找字符串“halt”。

(21)强制退出vim,不存盘。

2、用gdb调试程序的bug

(1)使用vi编辑器,将以下代码输入到名为greet.c的文件中。

此代码的原意为输出倒序main函数中定义的字符串,但结果显示没有输出,代码如下所示。

#include<

stdio.h>

intdisplay1(char*string);

intdisplay2(char*string);

intmain()

{

charstring[]=”EmbeddedLinux”;

display1(string);

display2(string);

}

intdisplay1(char*string)

printf(“Theoriginalstringis%s\n”,string);

intdisplay2(char*string1)

char*string2;

intsize,i;

size=strlen(string1);

string2=(char*)malloc(size+1);

for(i=0,i<

size;

i++)

{

string2[size-i]=string[i];

}

string2[size+1]=’’;

printf(“Thestringafterwardis%s\n”,string2);

(2)使用gcc编译这段代码,注意要加上“-g”选项以方便之后的调试。

(3)运行生成的可执行文件,观察运行结果。

(4)使用gdb调试程序,通过设置断点、单步跟踪,一步步找出错误所在。

(5)纠正错误,更改源程序并得到正确的结果。

3、编写包含多文件的makefile

(1)用vi在同一目录下编辑两个简单的hello程序,如下所示。

#hello.c

#include“hello.h”

printf(“Helloeveryone!

\n”);

#hello.h

#include<

(2)仍在同一目录下用vim编辑makefile,且不使用变量替换,用一个目标体实现(即直接将hello.c和hello.h编译成hello目标体)。

然后用make验证所写的makefile是否正确。

(3)将上述makefile使用变量替换实现。

同样用make验证所编写的makefile是否正确。

(4)编辑另一个makefile,取名为makefile1,不使用变量替换,但用两个目标体实现(也就是首先将hello.c和hello.h编译为hello.o,再将hello.o编译为hello),再用make的“-f”选项验证这个makefile1的正确性。

(5)将上述makefile1使用变量替换实现。

三、实验步骤

根据实验内容要求完成实验。

实验2进程管理实验

2实验名称:

进程管理实验

计算机科学与技术(嵌入式系统)学时数:

1、通过编写多进程程序,使读者熟练掌握fork()、exec()、wait()和waitpid()等函数的使用,进一步理解在Linux中多进程编程的步骤。

2、通过编写经典的“生产者—消费者”问题的实验,进一步熟悉Linux中的多线程编程,掌握用信号量处理线程间的同步和互斥问题。

1、编写多进程程序

该实验有3个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls-l”指令,另一个子进程在暂停5s之后异常退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,等待收集到第二个子进程结束的信息,父进程就返回。

参考流程图如图1所示。

图1多进程实验流程图

2、多线程实验

编写“生产者—消费者”问题的实验,熟悉Linux中的多线程编程。

“生产者—消费者”问题描述如下。

有一个有限缓冲区和两个线程:

生产者和消费者。

他们分别不停地把产品放入缓冲区和从缓冲区中拿走产品。

一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也必须等待。

另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥执行。

要求使用有名管道来模拟有限缓冲区,并且使用信号量来解决“生产者—消费者”问题中的同步和互斥问题。

使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。

其中avail表示有界缓冲区中的空单元数,初始值为N;

full表示有界缓冲区中非空单元数,初始值为0;

mutex是互斥信号量,初始值为1。

参考流程图如图2所示。

图2多线程实验流程图

1、根据参考流程图编写程序;

2、编译和运行程序代码,并观察运行结果。

实验3模块编程实验

3实验名称:

模块编程实验

1、熟悉模块添加和删除的方法。

2、熟悉字符设备驱动的编写流程。

要求实现到虚拟设备(一段内存)的打开、关闭、读写的操作,并通过编写测试程序来测试虚拟设备及其驱动运行是否正常。

(1)编写代码。

这个简单的驱动程序的源代码如下所示:

/*test_drv.c*/

linux/module.h>

linux/init.h>

linux/fs.h>

linux/kernel.h>

#incldue<

linux/slab.h>

linux/types.h>

linux/errno.h>

linux/cdev.h>

asm/uaccess.h>

#defineTEST_DEVICE_NAME“test_dev”

#defineBUFF_SZ1024

/*全局变量*/

staticstructcdevtest_dev;

unsignedintmajor=0;

/*主设备号major=250*/

staticchar*data=NULL;

/*读函数*/

staticssize_ttest_read(structfile*file,char*buf,size_tcount,loff_t*f_pos)

{

intlen;

if(count<

0)

return–EINVAL;

}

len=strlen(data);

count=(len>

count)?

count:

len;

if*(copy_to_user(buf,data,count))/*将内核缓冲的数据复制到用户空间*/

return–EFAULT;

returncount;

/*写函数*/

staticssize_ttest_write(structfile*file,constchar*buffer,

size_tcount,loff_t*f_pos)

if(count<

memset(data,0,BUFF_SZ);

count=(BUFF_SZ>

BUFF_SZ;

if(copy_from_user(data,buffer,count))/*将用户缓冲的数据复制到内核空间*/

/*打开函数*/

staticinttest_open(structinode*inode,structfile*file)

printk(“Thisisopenoperation\n”);

/*分配并初始化缓冲区*/

data=(char*)kmalloc(sizeof(char)*BUFF_SZ,GFP_KERNEL);

if(!

data)

return–ENOMEM;

memset(data,0,BUFF_SZ);

return0;

/*关闭函数*/

staticinttest_release(structinode*inode,structfile*file)

printk(“Thisisreleaseoperation\n”);

if(data)

kfree(data);

/*释放缓冲区*/

data=NULL;

/*防止出现野指针*/

/*创建、初始化字符设备,并且注册到系统*/

staticvoidtest_setup_cdev(structcdev*dev,intminor,

structfile_operations*fops)

interr,devno=MKDEV(major,minor);

cdev_init(dev,fops);

dev->

owner=THIS_MODULE;

ops=fops;

err=cdev_add(dev,devno,1);

if(err)

printk(KERN_NOTICE"

Error%daddingtest%d"

err,minor);

/*虚拟设备的file_operations结构*/

staticstructfile_operationstest_fops=

.owner=THIS_MODULE,

.read=test_read,

.write=test_write,

.open=test_open,

.release=test_release,

};

/*模块注册入口*/

intinit_module(void)

intresult;

dev_tdev=MKDEV(major,0);

if(major)

{/*静态注册一个设备,设备号先前指定好,并设定设备名,用cat/proc/devices来查看*/

result=register_chrdev_region(dev,1,TEST_DEVICE_NAME);

else

result=alloc_chrdev_region(&

dev,0,1,TEST_DEVICE_NAME);

if(result<

printk(KERN_WARNING"

Testdevice:

unabletogetmajor%d\n"

major);

returnresult;

test_setup_cdev(&

test_dev,0,&

test_fops);

printk("

Themajorofthetestdeviceis%d\n"

major);

return0;

/*卸载模块*/

voidcleanup_module(void)

cdev_del(&

test_dev);

unregister_chrdev_region(MKDEV(major,0),1);

Testdeviceuninstalled\n"

);

(2)编译代码。

虚拟设备的驱动程序的Makefile如下所示:

ifeq($(KERNELRELEASE),)

KERNELDIR?

=/lib/modules/$(shelluname-r)/build/*内核代码编译路径*/

PWD:

=$(shellpwd)

modules:

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

modules_install:

$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_install

clean:

rm-rf*.o*~core.depend.*.cmd*.ko*.mod.c.tmp_versions

.PHONY:

modulesmodules_installclean

obj-m:

=test_drv.o/*将生成的模块为test_drv.ko*/

endif

(3)加载和卸载模块。

通过下面两个脚本代码分别实现驱动模块的加载和卸载。

加载脚本test_drv_load如下所示:

#!

/bin/sh

#驱动模块名称

module="

test_drv"

#设备名称。

在/proc/devices中出现

device="

test_dev"

#设备文件的属性

mode="

664"

group="

david"

#删除已存在的设备节点

rm-f/dev/${device}

#加载驱动模块

/sbin/insmod-f./$module.ko$*||exit1

#查到创建设备的主设备号

major=`cat/proc/devices|awk"

\\$2==\"

$device\"

{print\\$1}"

`

#创建设备文件节点

mknod/dev/${device}c$major0

#设置设备文件属性

chgrp$group/dev/${device}

chmod$mode/dev/${device}

卸载脚本test_drv_unload如下所示:

#卸载驱动模块

/sbin/rmmod$module$*||exit1

#删除设备文件

exit0

(4)编写测试代码。

最后一步是编写测试代码,也就是用户空间的程序,该程序调用设备驱动来测试驱动的运行是否正常。

以下实例只实现了简单的读写功能,测试代码如下所示:

/*test.c*/

#include<

stdlib.h>

string.h>

sys/stat.h>

sys/types.h>

unistd.h>

fcntl.h>

#defineTEST_DEVICE_FILENAME"

/dev/test_dev"

/*设备文件名*/

#defineBUFF_SZ1024/*缓冲大小*/

intfd,nwrite,nread;

charbuff[BUFF_SZ];

/*缓冲区*/

/*打开设备文件*/

fd=open(TEST_DEVICE_FILENAME,O_RDWR);

if(fd<

0)

perror("

open"

exit

(1);

do

printf("

Inputsomewordstokernel(enter'

quit'

toexit):

"

memset(buff,0,BUFF_SZ);

if(fgets(buff,BUFF_SZ,stdin)==NULL)

fgets"

break;

buff[strlen(buff)-1]='

\0'

;

if(write(fd,buff,strlen(buff))<

0)/*向设备写入数据*/

write"

if(read(fd,buff,BUFF_SZ)<

0)/*从设备读取数据*/

read"

printf("

Thereadstringisfromkernel:

%s\n"

buff);

}while(strncmp(buff,"

quit"

4));

close(fd);

exit(0);

四、实验结果

首先在虚拟设备驱动源码目录下编译并加载驱动模块。

$makeclean;

make

$./test_drv_load;

加载模块直接运行脚本文件test_drv_load

接下来,编译并运行测试程序

$gcc–otesttest.c

$./test

测试程序运行效果如下:

Hello,everybody!

/*从内核读取的数据*/

Thisisasimpledriver

Thisisasimpledriver

quit

最后,卸载驱动程序

$./test_drv_unload卸载模块直接运行脚本文件test_drv_unload

通过dmesg命令可以查看内核打印的信息:

$dmesg|tail–n10

……

Themajorofthetestdeviceis250/*当加载模块时打印*/

Thisisopenoperation/*当打开设备时打印*/

Thisisreleaseoperation/*关闭设备时打印*/

Testdeviceuninstalled/*当卸载设备时打印*/

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

当前位置:首页 > 工程科技 > 纺织轻工业

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

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