-
华中科技大学
嵌入式操作系统课程设计实验报告
院
系
:
计算机科学与技术学院
专业
:
班级:
姓
名:
指导老师:
报告时间:
计算机科学与技术学院操作系统课程设计实验报告
U201014281
计算机科学与技术学院
目
录
p>
1.
课程设计目的…………………………………………………………
3
2.
课程设计环境搭建……………
………………………………………3
3.
内容一:熟悉和理解
Linux
编程环境
< br>
3.1
内容要求…………
…………………………………………………………5
3.2
设计过程及实现………………………………………………………
……5
4.
内容二:掌握添加系统调用的方法
4.1
内容要求……………………
………………………………………………
9
4.2
设计过程及实现……………………………………………
………………
9
5.
内容三:掌握添
加设备驱动程序的方法
5.1
内容要求
…………………………………………………………………17
5.2
设计过程及实现……………
……………………………………………17
6.
内容四:理解和分析
/proc
文件
6.1
内容要求………
…………………………………………………………22
6.2
设计过程及实现……………………………………………
……………22
__________________________
第
2
页
p>
/
共
29
页
计算机科学与技术学院操作系统课程设计实验报告
< br>U201014281
1
课程设计目的
(
1
)掌握
Linux
操作系统的使
用方法;
(
2
)了解
Linux
系统内核代码结构;
(
3
)掌握实例操作系统的实现方
法。
2
课程设计环境搭建
(
1
)
windows 7
上,
利用虚拟机软件
VMware
软件搭建的
linux
平台:
◎
Ubuntu 11.10
p>
(安装包:
ubuntu-11.10-desktop-i386
)
◎内核:
linux-
headers-3.0.0-12-generic
(
2<
/p>
)更改
root
登录:
< br>
在现阶段
Ubuntu
p>
的系统中,是不允许直接以
root
身份登
录系统的,但是在
做课设的过程中,需要大量的使用
root<
/p>
权限来进行命令的操作。如果以普通用
户登录
ubuntu
,会连编辑一个文件都非常周折。为此,我找到了一种修改系统
文件,以达到直接使用
root
身份登录的方
法:
◎开始的时候,只能以普通用户登录,用
Ctrl+Alt+T
打开终端:
初始化
/
修改
root
密码
sudo
passwd root
用
p>
vi
编辑器修改这个文件:
sudo vi /etc/lightdm/
在文件最后加入这么一行代码:
greeter-show-manual-
login=true
然后保存退出,
sudo
reboot
重启系统。之后就可以输入
root
用户登录。
(
3
)在添加系统调用中用到的其他内核包:
__________________________
第
3
页
p>
/
共
29
页
◎下载和当前实验环境最为接近的系统版本(这点很重要)
使用
apt-get
install linux-source
-3.0.0
命令,
◎下载结果是
2
◎解压命令:
tar
–
xjvf 2
–
C /usr/src
◎解压后,
在
/usr/src
目录下得到内核文件夹
linux-source-3.0.0
计算机科学与技术学院操作系统课程设计
实验报告
U201014281
(
4
)在调用
linux
图形库时需要安装
GTK
环境:
◎安装
gcc/g++/gdb/make
等基本编程工具
apt-get install build-essential
Tip
:如果提示由于依赖项不能安
装,需要使用
apt
的强化版
apti
tude
,这
个工具可以自动分析软件包依赖,系统一般不自带
,需要先安装,具体过程是:
apt-get install aptitude
aptitude install build-essential
aptitude
这个工具很强大,对于解决软件包安装时的依赖问题很有帮
助。
◎安装
libgtk2.0-dev libglib2.0-dev
等开发相关的库文件:
apt-get install gnome-core-devel
◎安装
GTK
核心组件:
apt-get install
libgtk2.0-dev
这个安装完成后,
GTK
环境就基本搭建成功,网上有些教程说要安装其他配
置文件,经我亲测
,发现只要安装
libgtk2.0-dev
这个包就能搞定。
__________________________
第
4
页
p>
/
共
29
页
计算机科学与技术学院操作系统课程设计实验报告
< br>U201014281
3
内容一:熟悉和理解
Linux
编程环境
3.1
内容要求
< br>(
1
)编写一个
C
程序,实现文件拷贝功能
(
2
)
编写一个
C
程序,
使用
Linux
下的图形库
,
分窗口显示三个并发进程运行;
3.2
设计过程及实现
(
1
)文件拷贝:
p>
①文件的拷贝主要的思想就是利用文件指针操作,
在两个文件之间进
行按字符的
fget
和
fput
。从而完成整个文件的拷贝操作。在这个基本功能之外,需要增加
程序
的健壮性,具体有以下几个方面:
·源文件是否存在且能读取数据;
·是否能创建目的文件,且能向里面写入数据;
·程序需要的
argc
参数个数是否满足要求;
p>
②基于以上几点和内容要求,主要的程序段如下:
if(argc!=3)
//
判断参数个数是否为
3
,否则返回
{
printf(
return 0;
}
if(
(fsource=fopen(argv[1],
{
p>
printf(
//
判断源文件是否能打开
和读出
return 0;
}
if(
(ftarget=fopen(argv[2],
{
}
printf(
!
n
//
判断目的文件时候能
创建和写入
return 0;
while((c=fgetc(fsource))!=EOF)
{
}
__________________________
第
5
页
p>
/
共
29
页
fputc(c,ftarget);
//
按字符读取和写入数据
计算机科学与技术学院操作系统课程设计实验报告
U201014281
③执行结果如下:
将
source/
文件拷贝到到
,
开始时如下图
3-1
所示:
图
3-1
p>
复制开始前
source/
文件内容
利用
mycop
y
程序复制,查看
文件复制结果如下图
3-2
所示:
图
3-2
复
制后
文件的具体内容
(
2
)实现三个进程之间的并发程序:
这里需要用到课程实验时的
fork( )
程序以及
GTK
的图形显示。
<
/p>
①基本
fork
()程序,调用显示一个
父进程和两个子进程的结构如下:
if((pid_1=fork())==0)
{
printf(
//
第一个子进程
Child 1#
show(argc,argv,
//
调用函数显示窗口
}
else
{
if((pid_2=fork())==0){
printf(
< br>//
第二个子进程
Child
2#
show(argc,argv,
//
调用函数显示窗口
}
else {
printf(
//
父进程
Parent #
//
由于父进程需要显示全部子进程
PID
,所以这里直接用参数画窗口
}
__________________________
第
6
页
p>
/
共
29
页
计算机科学与技术学院操作系统课程设计实验报告
< br>U201014281
}
<
/p>
②调用
GTK
显示窗体函数模块的结构:
void show(int argc,char
*argv[],char *title ){
gtk_init (&argc, &argv);
p>
//
初始化工具包并且获取命令行参数
;
window = gtk_window_new
(GTK_WINDOW_TOPLEVEL);
//
创建新的窗口
;
//
设定窗口的位置
;
p>
gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER);
//<
/p>
监听窗口的
destroy
事件
;
g_signal_connect (G_OBJECT
(window),
gtk_window_set_title
(GTK_WINDOW (window),
title);//
用来设定更改窗口标题
;
gtk_container_set_border_width
(GTK_CONTAINER (window),
20);//
设定宽度
;
//
使用
g
tk_vbox_new
函数建立纵向组装盒
;
//
为了显示构件,必须将构件放入
组装盒中
,
并将组装盒放在窗口内
;
vbox = gtk_vbox_new (FALSE, 10);
gtk_container_set_border_width
(GTK_CONTAINER (vbox),
100);//
设定宽度
;
gtk_container_add (GTK_CONTAINER
(window), vbox);
gtk_widget_show
(vbox);
//
使用
gtk_box_pack_start
函数
将构件放到组装盒中
;
sprintf
(id_char,
//
显示
PID
号
p>
label = gtk_label_new
(id_char);
gtk_box_pack_start (GTK_BOX
(vbox), label, FALSE, FALSE, 10);
gtk_widget_show (label);
sprintf (id_char,
父进程
ID:%d
//<
/p>
显示
PPID
号
label = gtk_label_new (id_char);
gtk_box_pack_start (GTK_BOX
(vbox), label, FALSE, FALSE, 10);
gtk_widget_show (label);
button = gtk_button_new_with_label
(
//
关闭窗口按钮
//
信号
登记函数
,
监听按钮的
clicked
事件。
/
/
当窗口
clicked
时,
gtk_widget_destroy
就会被调用。
//
而
gtk_widget_destroy
函数又调用
gtk_main_quit()
结束程序运行。
g_signal_connect_swapped
(G_OBJECT
(button),
G_CALLBACK
(gtk_widget_destroy), window);
gtk_box_pack_start (GTK_BOX (vbox),
button, FALSE, FALSE, 10);
GTK_WIDGET_SET_FLAGS (button,
GTK_CAN_DEFAULT);
gtk_widget_grab_default (button);
//
函数显示窗口中的组件
gtk_widget_show (button);
__________________________
第
7
页
p>
/
共
29
页
计算机科学与技术学院操作系统课程设计实验报告
< br>U201014281
gtk_widget_show (window);
//
准备将窗口和所有的组件显示在
屏幕上,函数必须在
GTK
程序的最后调用
.
gtk_main ();
} <
/p>
③编译代码
forkgtk.c
,运行;
编译命令为:
gcc -o forkgtk
forkgtk.c `pkg-config --cflags --libs
gtk+-2.0`
程序运行结果如下图
3-3
所示:
图
3-3
三个并行显示窗口
__________________________
第
8
页
p>
/
共
29
页
计算机科学与技术学院操作系统课程设计实验报告
< br>U201014281
4.
内容二:掌握添加系统调用的方法
4.1
内容要求
< br>(
1
)采用编译内核的方法,添加一个新的系统调用。<
/p>
(
2
)编写一
个应用程序,测试新添加的系统调用。
(
3
)系统调用的功能:文件拷贝。
4.2
设计过程及实现
在这一个部分,投入了比较多的时间。总结起来,主要有这么
几个方面:
·linux
内核版本的不同,
linux2.X
和
linux3.X
直接添加系统调用和重新编
译
内核的方法有差异,甚至
linux2.X
之间,内核文件也有
变化。
·再加上相关资料的步骤和
方法不尽相同,甚至还有互斥的步骤,这就使得
这个推进比较漫长。我之前的
Ubuntu
版本是
13.04
< br>,后来发现因为是
64
位的,
行
不通,只好换了一个低版本的
Ubuntu11.10,
经过自
己的实际工作,下面是在
运行成功之后,总结的一个过程。
(环
境和内核配置见本报告第二部分)
(
1
)修改
Makefile
文件,修改
系统版本后缀:如下图
4-1
所示:这里加的是本
人的姓名的首字母,以示区分。
__________________________
第
9
页
p>
/
共
29
页
计算机科学与技术学院操作系统课程设计实验报告
< br>U201014281
图
4-1
修改
Makefile
文件版本
(
2
)修改
/
usr/src/
linux-source-3.0.0
/
kernel/
目录下的
sys.c
文
件,在最后加
入新的系统调用,拷贝函数实现。如下所示:
asmlinkage int sys_zcycopyfile(const
char* s_file, const char* t_file)
{
const int BUF_SIZE = 512;
int
fin,fout;
char buf[BUF_SIZE];
int copy_count;
mm_segment_t fs;
//
段操作的初始化
fs = get_fs();
set_fs(get_ds());
/*
系统调用打开源文件,若失败,返回
-1 */
if ((fin =
sys_open(s_file,O_RDONLY
,S_IRUSR)) ==
-1)
{
return -1;
printk(
}
/*
系统调用创建并打开目标文件,若失败,返回
-2 */
if
((fout
=
sys_open(t_file,O_RDWR
|
O_CREAT
|
O_TRUNC,S_IRUSR
|
S_IWUSR)) == -1)
{
return -2;
printk(
}
whi
le(copy_count=sys_read(fin,buf,BUF_SIZE))
{
/*
拷贝文件,若失败,返回
-3
*/
if (copy_count == -1 ||
sys_write(fout,buf,copy_count) == -1)
{
return -3;
printk(
}
}
set_fs(fs);
/*
段操作结束
*/
return 0;
}
(
3
)修改
/usr/src/
linux-source-3.0.0<
/p>
/arch/x86/include/asm/
文件夹下面头文
件:
unistd_32.h
,
在文件
的系统调用号部分添加一个新的系统调用
,
具体添加行如下:<
/p>
#define __NR_sys_zcycopyfile
347
__________________________
第
10
页
<
/p>
/
共
29
页
p>
计算机科学与技术学院操作系统课程设计实验报告
U201014281
同时把下面的总调用号加
1<
/p>
,变成
348
。具体截图如下图
4-2
所示。
图
4-2
添加系统调用号
(
< br>4
)修改
/usr/src/ linux-sourc
e-3.0.0/x86/kernel/syscall_table_32.s
,<
/p>
①加入新的一行:
.long sys_zcycopyfile
②具体实现如下图
4-3
所示:
< br>
/* 347 */
__________________________
第
11
页
<
/p>
/
共
29
页
p>
计算机科学与技术学院操作系统课程设计实验报告
U201014281
图
4-3
填写系统调用入口表
③当用户程序需要系统提供服务的时候,
比如
347
号调用
sys_zcycopyfile,
就会通过系统调用产生一个
int 0x80
的软中断,就
会进入到系统调用的入口函
数,
找到这个调用函数表查找入口函
数,
也就是这里的
.long
sys
_zcycopyfile
,
进而在
s
ys.c
中找到具体的函数实现
asmlinkage int
sys_zcycopyfile(const
char* s_file,
const char* t_file)
,从而实现系统调用。
(
5
)配置内核:(先
cd
到下载的新的内核包)
①净化解压后的源代码
make mrproper
②安装
ncurses
环境:
apt-get install libncurses5-dev
ncurses
是一个能提供基于文
本终端窗口功能的动态库
,
提供字符终端处理库,
包括面板和菜单。
③对内核选项进行配置
make menuconfig
执行命令之后,会弹出一个框,提示对内核裁剪或配置。这次用不到变化内
核模块,直接
用键盘方向键选
项就行了。
④建立模块间的依赖信息
make dep
__________________________
第
12
页
<
/p>
/
共
29
页
p>
计算机科学与技术学院操作系统课程设计实验报告
U201014281
这一步正常情况会提示用户多此一举
⑤删除配置时留下的一些不用的文件
make clean
这一步一般没动作,除非是失败后再次编译内核时要用到。
<
/p>
(
6
)编译内核:
①编译内核文件
bzImage:
make bzImage
–
j9
这一步耗费的时间比较长,所以加了一个
-j9
,这种方法使用多线程编程,
实际使用时发现能很大的提高效率。
(
这个视
CPU
而定,要看
CPU
最多支持几个
线程
)
②编译内核模块:
make modules
–
j9
(
7
)安装内核
经过最麻烦的编译内核,接下来的安装内核就显得容易多了,输入命令
sudo make
modules_install
sudo make install
安装内核
安装内核模块
同样,如果嫌时间太慢的话,同样可以在最后加上
–
j9
(
8
)环境修改:
接下来主要是将编译安装生成的操作系统让系统引导程序“知道”,具体过
程如下图
4-4
所示:
图
4-4
环境修改
具体如下:
①复制内核到
boot
目录:
__________________________
第
13
页
<
/p>
/
共
29
页
p>
计算机科学与技术学院操作系统课程设计实验报告
U201014281
cp
arch/i386/boot/bzImage
/boot/
可利用
Tab
快速补全路径和文件,这样方便又不容易出错。
②建立要载入
ramdisk
的映
像文件
mkinitramfs
-o /boot/-3.0.69-zcy
③更新启动项文件
,直接输入命令
update-
grub2
就行。
(
9
)最后需要修改
/boot/grub/
目录下
文件;
进入文件之后,
按
Ctrl+F
查找
timeout
,
将所有的
timeout
数值改为
100
;
这个数值的单位是秒,
这么做的目的是修改启动项的暂停时间,
以便让用户有足
够的
时间选择要进入的操作系统。
(
10
)重
启,进入新系统:启动项如下图
4-5
所示:
< br>
图
4-5
系统启动项
※原版本内核比新内核小,入口在
Previous
Linux version
目录下,如下
图
4-6
所示:以上做的工作相当于在添加新的系统调用的同时还更新了系统。<
/p>
__________________________
第
14
页
<
/p>
/
共
29
页
p>
-
-
-
-
-
-
-
-
-
上一篇:剑桥雅思同义词替换大全
下一篇:高中完型近义词词汇比较