华中科技大学计算机学院操作系统课程设计报告
更新时间:2023-12-13 22:37:01 阅读量: 教育文库 文档下载
- 华中科技大学 计算机学院推荐度:
- 相关推荐
华中科技大学
嵌入式操作系统课程设计实验报告
院 系: 计算机科学与技术学院 专 业: 班 级: 姓 名: 指导老师:
报告时间:
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
计算机科学与技术学院
目 录
1.课程设计目的…………………………………………………………3 2.课程设计环境搭建……………………………………………………3 3.内容一:熟悉和理解Linux编程环境
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页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
1 课程设计目的
(1)掌握Linux操作系统的使用方法; (2)了解Linux系统内核代码结构; (3)掌握实例操作系统的实现方法。
2 课程设计环境搭建
(1)windows 7上,利用虚拟机软件VMware软件搭建的linux平台:
◎Ubuntu 11.10 (安装包:ubuntu-11.10-desktop-i386) ◎内核:linux-headers-3.0.0-12-generic
(2)更改root登录:
在现阶段Ubuntu的系统中,是不允许直接以root身份登录系统的,但是在
做课设的过程中,需要大量的使用root权限来进行命令的操作。如果以普通用户登录ubuntu,会连编辑一个文件都非常周折。为此,我找到了一种修改系统文件,以达到直接使用root身份登录的方法:
◎开始的时候,只能以普通用户登录,用Ctrl+Alt+T打开终端: 初始化/修改root密码
sudo passwd root
用vi编辑器修改这个文件:
sudo vi /etc/lightdm/lightdm.conf
在文件最后加入这么一行代码:
greeter-show-manual-login=true
然后保存退出,sudo reboot 重启系统。之后就可以输入root用户登录。
(3)在添加系统调用中用到的其他内核包:
__________________________
第3页 /共29页
◎下载和当前实验环境最为接近的系统版本(这点很重要)
使用apt-get install linux-source-3.0.0 命令,
◎下载结果是linux-source-3.0.0.tar.bz2
◎解压命令:tar –xjvf linux-source-3.0.0.tar.bz2 –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的强化版aptitude,这
个工具可以自动分析软件包依赖,系统一般不自带,需要先安装,具体过程是:
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页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
3 内容一:熟悉和理解Linux编程环境
3.1 内容要求
(1)编写一个C程序,实现文件拷贝功能
(2)编写一个C程序,使用Linux下的图形库,分窗口显示三个并发进程运行; 3.2 设计过程及实现 (1)文件拷贝:
①文件的拷贝主要的思想就是利用文件指针操作,在两个文件之间进行按字符的fget和fput。从而完成整个文件的拷贝操作。在这个基本功能之外,需要增加程序的健壮性,具体有以下几个方面:
·源文件是否存在且能读取数据;
·是否能创建目的文件,且能向里面写入数据; ·程序需要的argc参数个数是否满足要求;
②基于以上几点和内容要求,主要的程序段如下:
if(argc!=3)
//判断参数个数是否为3 ,否则返回
{
printf(\ return 0; }
if( (fsource=fopen(argv[1],\{
printf(\
//判断源文件是否能打开和读出
return 0; }
if( (ftarget=fopen(argv[2],\{ }
printf(\!\\n\//判断目的文件时候能创建和写入 return 0;
while((c=fgetc(fsource))!=EOF) { }
__________________________
第5页 /共29页
fputc(c,ftarget); //按字符读取和写入数据
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
③执行结果如下:
将source/source.txt文件拷贝到到target.txt,开始时如下图3-1所示:
图3-1 复制开始前source/source.txt文件内容
利用mycopy程序复制,查看target.txt文件复制结果如下图3-2所示:
图3-2 复制后target.txt文件的具体内容
(2)实现三个进程之间的并发程序:
这里需要用到课程实验时的fork( )程序以及GTK的图形显示。
①基本fork()程序,调用显示一个父进程和两个子进程的结构如下:
if((pid_1=fork())==0)
{ printf(\ //第一个子进程 Child 1# show(argc,argv,\ //调用函数显示窗口 } else { if((pid_2=fork())==0){ printf(\//第二个子进程 Child 2# show(argc,argv,\ //调用函数显示窗口 } else { printf(\ //父进程 Parent # //由于父进程需要显示全部子进程PID,所以这里直接用参数画窗口 }
__________________________
第6页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
}
②调用GTK显示窗体函数模块的结构:
void show(int argc,char *argv[ ],char *title ) { gtk_init (&argc, &argv); //初始化工具包并且获取命令行参数; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //创建新的窗口; //设定窗口的位置;
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
//监听窗口的destroy事件;
g_signal_connect (G_OBJECT (window), \ gtk_window_set_title (GTK_WINDOW (window), title);//用来设定更改窗口标题; gtk_container_set_border_width (GTK_CONTAINER (window), 20);//设定宽度; //使用gtk_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号 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\ //显示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页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
gtk_widget_show (window); //准备将窗口和所有的组件显示在屏幕上,函数必须在GTK程序的最后调用. gtk_main (); }
③编译代码forkgtk.c,运行;
编译命令为:gcc -o forkgtk forkgtk.c `pkg-config --cflags --libs gtk+-2.0` 程序运行结果如下图3-3所示:
图3-3 三个并行显示窗口
__________________________
第8页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
4.内容二:掌握添加系统调用的方法
4.1 内容要求
(1)采用编译内核的方法,添加一个新的系统调用。 (2)编写一个应用程序,测试新添加的系统调用。 (3)系统调用的功能:文件拷贝。 4.2 设计过程及实现
在这一个部分,投入了比较多的时间。总结起来,主要有这么几个方面: ·linux内核版本的不同,linux2.X和linux3.X直接添加系统调用和重新编译内核的方法有差异,甚至linux2.X之间,内核文件也有变化。
·再加上相关资料的步骤和方法不尽相同,甚至还有互斥的步骤,这就使得这个推进比较漫长。我之前的Ubuntu版本是13.04,后来发现因为是64位的,行不通,只好换了一个低版本的Ubuntu11.10,经过自己的实际工作,下面是在运行成功之后,总结的一个过程。(环境和内核配置见本报告第二部分) (1)修改Makefile文件,修改系统版本后缀:如下图4-1所示:这里加的是本人的姓名的首字母,以示区分。
__________________________
第9页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 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(\ }
while(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/arch/x86/include/asm/文件夹下面头文件:
unistd_32.h,在文件的系统调用号部分添加一个新的系统调用,具体添加行如下:
#define __NR_sys_zcycopyfile 347
__________________________
第10页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
同时把下面的总调用号加1,变成348。具体截图如下图4-2所示。
图4-2 添加系统调用号
(4)修改/usr/src/ linux-source-3.0.0/x86/kernel/syscall_table_32.s,
①加入新的一行:
.long sys_zcycopyfile
②具体实现如下图4-3所示:
/* 347 */
__________________________
第11页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
图4-3 填写系统调用入口表
③当用户程序需要系统提供服务的时候,比如347号调用sys_zcycopyfile,就会通过系统调用产生一个int 0x80的软中断,就会进入到系统调用的入口函数,找到这个调用函数表查找入口函数,也就是这里的.long sys_zcycopyfile,进而在sys.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页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
这一步正常情况会提示用户多此一举 ⑤删除配置时留下的一些不用的文件
make clean
这一步一般没动作,除非是失败后再次编译内核时要用到。
(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页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
cp arch/i386/boot/bzImage /boot/vmlinuz-3.0.69.zcy
可利用Tab快速补全路径和文件,这样方便又不容易出错。 ②建立要载入ramdisk的映像文件
mkinitramfs 3.0.69.zcy -o /boot/initrd.img-3.0.69-zcy
③更新启动项文件grub2.conf,直接输入命令update-grub2就行。
(9)最后需要修改/boot/grub/ 目录下 grub.cfg文件;
进入文件之后,按 Ctrl+F 查找 timeout ,将所有的timeout数值改为100;
这个数值的单位是秒,这么做的目的是修改启动项的暂停时间,以便让用户有足够的时间选择要进入的操作系统。
(10)重启,进入新系统:启动项如下图4-5所示:
图4-5 系统启动项
※原版本内核比新内核小,入口在Previous Linux version 目录下,如下
图4-6所示:以上做的工作相当于在添加新的系统调用的同时还更新了系统。
__________________________
第14页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
图4-6 旧的系统入口显示
(11)进入新系统之后,输入命令uname –a / -r查看系统新版本:执行情况如下图4-7所示。可知已经成功的进入到修改后的新内核3.0.69.zcy
图4-7 显示新内核信息
(12)编写测试程序zcopy.c,如下图4-8所示:
__________________________
第15页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
图4-8 测试程序,检测新的第347号系统调用
(13)编译运行,生成执行文件。然后看执行程序是否可以实现文件的拷贝,执行结果如下图4-9和图4-10所示,可看到已经成功的实现了预计的功能。
图4-9 执行程序
__________________________
第16页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
图4-10 程序执行显示结果
__________________________
第17页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
5.内容三:掌握添加设备驱动程序的方法
5.1 内容要求
(1)采用模块方法,添加一个新的设备驱动程序。 (2)要求添加字符设备的驱动。
(3)编写一个应用程序,测试添加的驱动程序 5.2 设计过程及实现
(1)Linux内核中的设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程。对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文件,用户程序可以象对其它文件一样对此设备文件进行操作。
Linux支持3种设备:字符设备、块设备和网络设备。
设备由一个主设备号和一个次设备号标识。主设备号唯一标识了设备类型,
即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,一般用于识别在若干可能的硬件设备中,I/O请求所涉及到的那个设备。
一个典型的驱动程序,大体上可以分为这么几个部分: ①注册设备:
在系统初启,或者模块加载时候,必须将设备登记到相应的设备数组,并返回
设备的主设备号;
②定义功能函数:
对于每一个驱动函数来说,都有一些和此设备密切相关的功能函数。以最常
用的块设备或者字符设备来说,都存在着诸如 open()、read()这一类的操作。当系统调用这些调用时,将自动的使用驱动函数中特定的模块。来实现具体的操作;
③卸载设备:
在不用这个设备时,可以将它卸载,主要是从/proc 中取消这个设备的特殊
文件。
__________________________
第18页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
(2)编写Makefile文件如下: ifneq ($(KERNELRELEASE),)
obj-m := zcydriver.o //obj-m表示编译连接后将生成zcydriver.o模块 else
PWD :=$(shell pwd) //PWD为当前目录
KVER :=$(shell uname -r) //KVER为当前系统内核版本 KDIR :=/lib/modules/$(KVER)/build all:
$(MAKE) -C $(KDIR) M=$(PWD) //调用内核模块编译 clean:
# rm -f *.cmd *.o *.mod *.ko
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions # $(MAKE) -C $(KDIR) M=$(PWD) clean endif
调用Makefile文件之后,其具体过程如下:
①KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量,在第
一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容;
②如果make的目标是clean,直接执行clean操作,然后结束。
③当make的目标为all时,-C $(KDIR)指明跳转到内核源码目录下读取那里
的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
④当从内核源码目录返回时,KERNELRELEASE已被定义,内核的build程序
Kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。
⑤else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,
以及要生成的目标模块名。
__________________________
第19页 /共29页
计算机科学与技术学院 操作系统课程设计实验报告 U201014281
(3)编写设备功能函数:(zcydriver.c)
函数框架如下所示:
//打开设备
#define MY_MAJOR 240 //定义设备号
int zcydriver_open(struct inode *inode, struct file *filp)
ssize_t zcydriver_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos )
//读数据
{
sprintf(s2,\ if(count<12) {
if(!copy_to_user(buf,s2,count)) { return 0; } } else {
if(!copy_to_user(buf,s2,strlen(s2))) { return 0; }
return -1; }
ssize_t zcydriver_write(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos)
}
//写数据
{
if (count < 0) return -EINVAL; if (s1 == NULL) return -ENOMEM; if (copy_from_user(s1, buf, count+1)) return -EFAULT; return count; }
int zcydriver_release(struct inode *inode, struct file *filp)
struct file_operations zcydriver_fops = { .owner = THIS_MODULE, .open = zcydriver_open, .read = zcydriver_read, .write = zcydriver_write, .release = zcydriver_release, };
//释放设备 //
__________________________
第20页 /共29页
正在阅读:
小学低年级学生学业不良的成因12-30
第十二章动能定理习题解答03-02
湖北省第21届外语翻译大赛获奖名单04-19
2018-2024年中国葡萄糖酸内酯市场监测调查分析与投资战略咨询预05-04
新课程理念下数学探究性教学案例研究03-03
上海市餐厨垃圾处理管理办法05-16
【免费下载】成品检验控制程序05-04
有趣的生物共栖现象教学设计(表格式)07-05
彭州市的资源 - 图文01-16
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 华中科技大学
- 操作系统
- 课程
- 计算机
- 报告
- 学院
- 设计
- 中央戏剧学院封面个人简历模板
- 2003年1月大学英语四级真题及答案(Sk整理)
- 特级教师课堂管理的66个细节
- 音标--教案
- 水利工程中混凝土裂缝的成因及对策
- 最新二级VB上机题库一(1-40)
- 考研机械原理题库(填空)
- 概率思维颠覆直觉
- Labview基本常见问题解答2
- 新课改下的高中历史教学
- 贵州2017年上半年卫生事业单位招聘医学基础考试试题
- VF课程设计 - 图文
- 2015江苏徐州公务员考试:中国现当代作家作品高频考点
- 大快人心!最高法院打响纠正企业家冤假错案的第一枪,遗憾没有追责(物美张文中案件评析)民商事裁判规则
- 西南大学《英语阅读二》复习思考题及答案
- 人教版 小学8年级 数学上册《全等三角形》《轴对称》期末复习提优题及答案解析
- 黑枸杞泡酒的比例及功效
- 小升初数学综合模拟试卷答案及详细解析(21)
- 2015年会计从业考试知识点《会计电算化》:数据的保护每日一练(9月8日)
- 统计从业资格考试训练题及答案