2嵌入式操作系统实验指导书(5月更新)由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“华为实验指导书更新”。
《嵌入式操作系统》实验指导书
实验1 Linux编程基础
实验序号:1 适用专业:计算机科学与技术
一、实验目的1、熟悉Vim的工作模式,熟练使用vim中的常见操作。
2、熟练掌握gcc编译命令及gdb的调试命令,通过对有问题程序的跟踪调试,进一步提高发现问题和解决问题的能力。
3、熟悉多文件的makefile的编写,熟悉各种形式的makefile,并且进一步加深对makefile中用户自定义变量、自动变量的理解。
4、使用autotools生成多文件的makefile,进一步掌握autotools的使用方法。
二、实验内容
1、vim使用练习
(1)在“/root”目录下建一个名为“vim”的目录。(2)进入“vim”目录。
(3)将文件“/etc/inittab”复制到“vim”目录下。(4)使用vim打开“vim”目录下的inittab.(5)设定行号,指出设定initdefault(类似于“id:5:initdefault”)的所在行号。(6)将光标移到该行。(7)复制该行内容。
(8)将光标移到最后一行行首。(9)粘贴复制行的内容。(10)撤销第9步的动作。
(11)将光标移动到最后一行的行尾。(12)粘贴复制行的内容。
(13)光标移到“si::sysinit:/etc/rc.d/rc.sysinit”。(14)删除该行。(15)存盘但不退出。(16)将光标移到首行。
(17)插入模式下输入“Hello,this is vi world!”.(18)返回命令行模式。
(19)向下查找字符串“0:wait”。(20)再向上查找字符串“halt”。
实验名称:Linux编程基础
学 时 数:4学时
(21)强制退出vim,不存盘。
2、用gdb调试程序的bug(1)使用vi编辑器,将以下代码输入到名为greet.c的文件中。此代码的原意为输出倒序main函数中定义的字符串,但结果显示没有输出,代码如下所示。
#include int display1(char *string);int display2(char *string);
int main(){
} int display1(char *string){
} int display2(char *string1){
char *string2;int size,i;size=strlen(string1);string2=(char *)malloc(size+1);for(i=0,i
(4)使用gdb调试程序,通过设置断点、单步跟踪,一步步找出错误所在。
(5)纠正错误,更改源程序并得到正确的结果。
3、编写包含多文件的makefile(1)用vi在同一目录下编辑两个简单的hello程序,如下所示。#hello.c #include“hello.h” int main(){
} #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使用变量替换实现。
三、实验步骤
根据实验内容要求完成实验。printf(“Hello everyone!n”);
实验2 进程管理实验
实验序号:2
实验名称:进程管理实验
适用专业:计算机科学与技术(嵌入式系统)学 时 数:4学时
一、实验目的1、通过编写多进程程序,使读者熟练掌握fork()、exec()、wait()和waitpid()等函数的使用,进一步理解在Linux中多进程编程的步骤。
2、通过编写经典的“生产者—消费者”问题的实验,进一步熟悉Linux中的多线程编程,掌握用信号量处理线程间的同步和互斥问题。
二、实验内容
1、编写多进程程序
该实验有3个进程,其中一个为父进程,其余两个是该父进程创建的子进程,其中一个子进程运行“ls-l”指令,另一个子进程在暂停5s之后异常退出,父进程先用阻塞方式等待第一个子进程的结束,然后用非阻塞方式等待另一个子进程的退出,等待收集到第二个子进程结束的信息,父进程就返回。参考流程图如图1所示。
开始 fork()创建两个子进程子进程1父进程阻塞式等待子进程1的结束等待1s子进程2是否结束?运行(调用execlp()执行“ls-l”命令)是子进程2运行(调用sleep函数)结束
图1 多进程实验流程图
2、多线程实验
编写“生产者—消费者”问题的实验,熟悉Linux中的多线程编程。
“生产者—消费者”问题描述如下。有一个有限缓冲区和两个线程:生产者和消费者。他们分别不停地把产品放入缓冲区和从缓冲区中拿走产品。一个生产者在缓冲区满的时候必须等待,一个消费者在 缓冲区空的时候也必须等待。另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥执行。
要求使用有名管道来模拟有限缓冲区,并且使用信号量来解决“生产者—消费者”问题中的同步和互斥问题。
使用3 个信号量,其中两个信号量 avail 和 full 分别用于解决生产者和消费者线程 之间的同步问题,mutex 是用于这两个线程之间的互斥问题。其中 avail 表示有界缓冲区中 的空单元数,初始值为 N;full 表示有界缓冲区中非空单元数,初始值为 0;mutex是互斥 信号量,初始值为 1。参考流程图如图2所示。
开始 建立有名管道 打开有名管道 初始化三个信号量 创建消费者和生 产者两个线程 生产者线程 P操作(avail)P操作(mutex)读管道消费者线程 P操作(full)P操作(mutex)写管道 V操作(full)V操作(mutex)结束 V操作(avail)V操作)(mutex 图2 多线程实验流程图
三、实验步骤
1、根据参考流程图编写程序;
2、编译和运行程序代码,并观察运行结果。
实验3 模块编程实验
实验序号:3
实验名称:模块编程实验
适用专业:计算机科学与技术(嵌入式系统)学 时 数:4学时
一、实验目的1、熟悉模块添加和删除的方法。
2、熟悉字符设备驱动的编写流程。
二、实验内容 要求实现到虚拟设备(一段内存)的打开、关闭、读写的操作,并通过编写测试程序来测试虚拟设备及其驱动运行是否正常。
三、实验步骤
(1)编写代码。
这个简单的驱动程序的源代码如下所示: /*test_drv.c*/ #include #include #include #include #incldue #include #include #include #include #define TEST_DEVICE_NAME “test_dev” #define BUFF_SZ 1024 /*全局变量*/ static struct cdev test_dev;unsigned int major=0;/*主设备号major=250*/ static char *data=NULL;/*读函数*/ static ize_t test_read(struct file *file,char *buf,size_t count, loff_t *f_pos)
{ int len;if(count
} { } len=strlen(data);count=(len>count)?count:len;if *(copy_to_user(buf,data,count))/*将内核缓冲的数据复制到用户空间*/ {
} return count;return –EFAULT;return –EINVAL;/*写函数*/ static ize_t test_write(struct file *file,const char *buffer,size_t count,loff_t *f_pos){
if(count
} /*打开函数*/ static int test_open(struct inode *inode,struct file *file){
printk(“This is open operationn”);/*分配并初始化缓冲区*/ data=(char*)kmalloc(sizeof(char)* BUFF_SZ,GFP_KERNEL);if(!data)count=(BUFF_SZ>count)?count:BUFF_SZ;if(copy_from_user(data,buffer,count))/*将用户缓冲的数据复制到内核空间*/ {
} return count;return –EFAULT;return –EINVAL;
} { } memset(data,0,BUFF_SZ);return 0;return –ENOMEM;/*关闭函数*/ static int test_release(struct inode *inode,struct file *file){
} /* 创建、初始化字符设备,并且注册到系统*/ static void test_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops)
{ int err, devno = MKDEV(major, minor);cdev_init(dev, fops);dev->owner = THIS_MODULE;dev->ops = fops;
err = cdev_add(dev, devno, 1);
if(err){
printk(KERN_NOTICE “Error %d adding test %d”, err, minor);} } /* 虚拟设备的 file_operations 结构 */ static struct file_operations test_fops = {
.owner = THIS_MODULE,.read.open };
/*模块注册入口*/= test_read, = test_open,.write = test_write,.release = test_release, printk(“This is release operationn”);if(data){
} return 0;kfree(data);data=NULL;
/*释放缓冲区*/ /*防止出现野指针*/
int init_module(void){
int result;dev_t dev = MKDEV(major, 0);if(major)
{/* 静态注册一个设备,设备号先前指定好,并设定设备名,用 cat /proc/devices 来查看*/ } else { } if(result
printk(KERN_WARNING“Test device:unable to get major %dn”,major);return result;
} test_setup_cdev(&test_dev, 0, &test_fops);printk(“The major of the test device is %dn”, major);return 0;}
/*卸载模块*/ void cleanup_module(void){
cdev_del(&test_dev);unregister_chrdev_region(MKDEV(major, 0), 1);printk(“Test device uninstalledn”);} result=alloc_chrdev_region(&dev,0,1,TEST_DEVICE_NAME);result=register_chrdev_region(dev,1,TEST_DEVICE_NAME);
(2)编译代码。
虚拟设备的驱动程序的 Makefile 如下所示:
ifeq($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname-r)/build /*内核代码编译路径*/ PWD := $(shell pwd)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: modules modules_install clean else 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 $* || exit 1 # 查到创建设备的主设备号
major=`cat /proc/devices | awk “$2==”$device“ {print $1}”` # 创建设备文件节点
mknod /dev/${device} c $major 0 # 设置设备文件属性
chgrp $group /dev/${device} chmod $mode /dev/${device}
卸载脚本 test_drv_unload 如下所示:
#!/bin/sh
module=“test_drv” device=“test_dev” # 卸载驱动模块
/sbin/rmmod $module $* || exit 1 # 删除设备文件
rm-f /dev/${device} exit 0(4)编写测试代码。
最后一步是编写测试代码,也就是用户空间的程序,该程序调用设备驱动来测试驱动的运行是否正常。以下实例只实现了简单的读写功能,测试代码如下所示:
/* test.c */ #include #include #include #include #include #include
#include #define TEST_DEVICE_FILENAME “/dev/test_dev” /* 设备文件名*/ #define BUFF_SZ 1024 /* 缓冲大小*/ int main(){
int fd, nwrite, nread;char buff[BUFF_SZ];/* 打开设备文件 */ fd = open(TEST_DEVICE_FILENAME, O_RDWR);if(fd
perror(“open”);exit(1);} do { printf(“Input some words to kernel(enter 'quit' to exit):”);memset(buff, 0, BUFF_SZ);if(fgets(buff, BUFF_SZ, stdin)== NULL){
perror(“fgets”);break;}
buff[strlen(buff)-1] = ' ';if(write(fd, buff, strlen(buff))
perror(“write”);break;}
if(read(fd, buff, BUFF_SZ)
perror(“read”);break;} else {
/*缓冲区*/
/* 从设备读取数据 */ printf(“The read string is from kernel:%sn”, buff);} } while(strncmp(buff, “quit”, 4));close(fd);exit(0);}
四、实验结果
首先在虚拟设备驱动源码目录下编译并加载驱动模块。
$ make clean;make $./test_drv_load $ gcc –o test test.c $./test
;加载模块直接运行脚本文件test_drv_load 接下来,编译并运行测试程序
测试程序运行效果如下:
Input some words to kernel(enter 'quit' to exit):Hello, everybody!The read string is from kernel:Hello, everybody!/* 从内核读取的数据 */ Input some words to kernel(enter 'quit' to exit):This is a simple driver The read string is from kernel: This is a simple driver Input some words to kernel(enter 'quit' to exit):quit The read string is from kernel:quit
最后,卸载驱动程序
$./test_drv_unload
卸载模块直接运行脚本文件test_drv_unload 通过 dmesg 命令可以查看内核打印的信息:
$ dmesg|tail –n 10 ……
The major of the test device is 250 /* 当加载模块时打印 */ This is open operation This is release operation Test device uninstalled
/* 当打开设备时打印 */ /* 关闭设备时打印 */ /* 当卸载设备时打印 */
《操作系统》实验指导书(适用于计科、网络工程、软件工程、信计专业)计算机科学与技术学院2010-5目录前言 .....................................................................
实验一 嵌入式开发环境的建立一、实验目的通过此实验系统,读者可以了解嵌入式实时操作系统 uC/OS-II 的内核机制和运行原理。本实验系统展示了 uC/OS-II 各方面的管理功能,包......
操作系统实验实验一Linux常用命令实验一.目的和要求本实验的目的是熟悉Linux操作系统的命令接口、图形接口和程序接口;了解Linux操作系统的启动过程;了解Linux操作系统的目录结......
天津理工大学华信软件学院 《操作系统》实验教学指导书2.1 课程代码: 课程名称: 适用专业: 指导教师:1460350操作系统 / Operating System 软件工程专业 张一鸣 开课院(系)、实验......
《操作系统课程设计》实验指导课程设计一:进程调度1、设计目的(1) 要求学生设计一个模拟进程调度的算法 (2) 理解进程控制块的结构 (3) 理解进程运行的并发性(4) 掌握进程调度的三种......