操作系统课程设计报告upload.docx_第1页
操作系统课程设计报告upload.docx_第2页
操作系统课程设计报告upload.docx_第3页
操作系统课程设计报告upload.docx_第4页
操作系统课程设计报告upload.docx_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一、 课程设计目的掌握Linux操作系统的使用方法;了解Linux系统内核代码结构;掌握实例操作系统的实现方法。二、 课程设计要求1、 掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。l 编一个C程序,其内容为实现文件拷贝的功能;l 编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。2、 掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。另编写一个应用程序,调用新增加的系统调用。实现的功能是:文件拷贝;3、 掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序,其功能可以简单。实现字符设备的驱动;4、 了解和掌握/proc文件系统的特点和使用方法l 了解/proc文件的特点和使用方法l 监控系统状态,显示系统中若干部件使用情况l 用图形界面实现系统监控状态。5、 设计并实现一个模拟的文件系统(选作)三、 课程设计系统平台实体硬件CPUAMD Athlon 7750 Dual-Core Processor 2.7GHz主板Asus M3A78内存4.0GB(3.25GB可用)操作系统Windows 7下的虚拟机VMware Workstation 6.0虚拟系统ubuntu-10.10-i386内核版本Linux-虚拟硬件内存1GB硬盘16GB四、 课程设计内容一1、 编一个C程序,其内容为实现文件拷贝的功能要实现文件拷贝功能,主要用到的函数是open、write、read。以前在windows下写C语言打开文件常用的fopen,此时不能用,因为fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api ;所以应该直接使用linux中的系统函数open。主要用到的头文件:Unistd.h包含了许多Linux系统服务的函数原型,如:read、writeFcntl.h定义了很多宏和open,fcntl函数原型Stdio.h标准输入输出头文件sys/types.h此头文件包含适当时应使用的多个基本派生类型sys/stat.h 包含了获取文件属性的一些函数errno.h用于调试错误代码是所需要的一些errno变量string.h包含了处理字符串的一些函数设计思路:由命令行参数获取2个文件名,根据其文件名和路径分别打开该2个文件,设置一个循环,从源文件复制N个字节到目的文件,直到源文件指针到文件尾,最后关闭2个文件。在可能出错的地方需要加上相应的报错代码和中断,并输出错误信息,以方便调试或是往后应用在第2小题中可能发生的错误。理清楚设计思路后,根据需求写出相应的源代码见后页源程序代码scopy.c ;在Linux终端使用编译命令 gcc o scopy scopy.c将程序编译并生产exe可执行文件。然后手动创建一个测试文件test.txt ,在终端输入命令./scopy test.txt target.txt这样就能将源文件test.txt复制到目标文件target.txt程序源代码 scopy.c:#include #include #include #include #include #include #include #define BUFFER_SIZE 1024 /缓冲区大小int main(int argc,char *argv) int from_fd,to_fd; int bytes_read,bytes_write; char bufferBUFFER_SIZE; /设定一个缓冲区 char *ptr; if(argc!=3) /三个参数 fprintf(stderr,Usage:%s fromfile tofilena,argv0); return(-1); /* 打开源文件 */ if(from_fd=open(argv1,O_RDONLY)=-1) fprintf(stderr,Open %s Error:%sn,argv1,strerror(errno); return(-1); /* 创建目的文件 */ if(to_fd=open(argv2,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)=-1) fprintf(stderr,Open %s Error:%sn,argv2,strerror(errno); return(-1); while(bytes_read=read(from_fd,buffer,BUFFER_SIZE) /* 一个致命的错误发生了 */ if(bytes_read=-1)&(errno!=EINTR) break; else if(bytes_read0) ptr=buffer; while(bytes_write=write(to_fd,ptr,bytes_read) /* 一个致命错误发生了 */ if(bytes_write=-1)&(errno!=EINTR)break; /* 写完了所有读的字节 */ else if(bytes_write=bytes_read) break; /* 只写了一部分,继续写 */ else if(bytes_write0) ptr+=bytes_write; bytes_read-=bytes_write; /* 写的时候发生的致命错误 */ if(bytes_write=-1)break; close(from_fd); close(to_fd); return(1);2、 编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。 本次我选用的图形库是GTK+首先要在Linux下载GTK+相关库文件并安装。在终端输入sudo apt-get install gnome-core-devel ,然后根据提示操作,就会安装 libgtk2.0-dev libglib2.0-dev 等开发所需的相关库文件。编译GTK+代码时需要包含的头文件是gtk/gtk.h,此外,还必须连接若干库;比如编译test.c时用以下命令。gcc o test test.c pkg-config -cflags -libs gtk+-2.0在编写代码时需要用到的控件、窗口等视窗物件形态,用类GtkWidget定义其为指针类型。编写一个GTK+程序的基本步骤如下:l 初始化Gtkl 建立控件l 登记消息与消息处理函数l 执行消息循环函数gtk_main()之后所设计的3个进程,基本上都是以这样的方式编写代码的,因为之前曾用过OpenGL,所以在这方面掌握的比较快。初始化主要使用的函数有gtk_init(&argc,&argv); /启动GTK gtk_window_new(GTK_WINDOW_TOPLEVEL); /创建窗口 gtk_window_set_title(GTK_WINDOW(window),标题名); /设置窗口标题名 gtk_widget_set_usize(window, 200, 200); /设置窗口大小 gtk_widget_show(window); /显示窗口建立控件的一般流程/*创建表格准备封装*/gtk_table_new (/创建多少列gint rows,/创建多少栏gint columns,/用来决定表格如何来定大小gint homogeneous);/*这个函数是将表格table,结合到窗口window里*/gtk_container_add(GTK_CONTAINER(window),table);gtk_widget_show(table);/ 显示该表格/*要把物件放进box中,可用以下函数*/void gtk_table_attach_defaults (GtkTable*table,/参数(table)是选定某表格GtkWidget*widget,/(child)是想放进去的物件gintleft_attach,/以下参数是指定把物件放在哪里, 及用多少个boxesgintright_attach,ginttop_attach,gintbottom_attach);本次我所设计的3个进程主要使用了下列控件:进度条、按钮、文本框、滚动条,分别用在3个进程里。进度条函数:progress_bar=gtk_progress_bar_new(); /创建进度条按钮函数:gtk_button_new_with_label(“LABEL”);/创建带有LABEL的字在上面的按钮文本框:gtk_text_new(NULL,NULL);/创建文本构件滚动条:gtk_vscrollbar_new(GTK_TEXT(text)-vadj); /创建滚动条并设置其与文本同步其他函数:gint gtk_timeout_add (guint32 interval,/每间隔interval 毫秒呼叫一次指定函数GtkFunction function,/被呼叫的函数gpointer data);/要传给该函数的资料gtk_signal_connect (GtkObject *object,/送出信号的物件gchar *name,/希望接取的信号名称GtkSignalFunc func,/送给该函数的资料gpointer func_data);根据上述重要的函数分别编写4个源代码,分别编译后,输入./Stest运行Stest结果如截图所示:下面附上4个进程的源代码:1) Stest.c#include #include #include #include #include int semid;char *finish;int p1,p2;int main (void) if(p1=fork()=0)/创建新进程 execv(./S1,NULL); else if(p2=fork()=0) execv(./S2,NULL); else execv(./S3,NULL); return 0;2) S1.c#include #includeGtkWidget *window;GtkWidget *table;GtkWidget *button;GtkWidget *progress_bar;/ 更新进度条,这样就能够看到进度条的移动gint progress_timeout( gpointer data ) gdouble value; int v; char text20=0%; /使用在调整对象中设置的取值范围计算进度条的值 value=gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR (progress_bar)+0.01; if (value1.0) value=0.0; v=(int)(value*100); strcpy(text, ); sprintf(text,%d,v); strcat(text,% ); / 设置进度条的新值 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress_bar),value); gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar),text); /这是一个timeout函数,返回 TRUE,这样它就能够继续被调用 /如果想要结束,可以在进度条到100时,return 0;这样回调函数就会结束 return TRUE; int main(int argc,char *argv) int timer; gpointer data; gtk_init(&argc,&argv);/在任何构件生成之前完成 window=gtk_window_new(GTK_WINDOW_TOPLEVEL);/创建窗口 gtk_window_set_title(GTK_WINDOW(window),Swindow1);/设置窗口标题 gtk_widget_set_usize(window, 200, 200);/设置窗口大小 gtk_container_set_border_width(GTK_CONTAINER(window),5);/设置窗口边框宽度 gtk_widget_show(window);/显示窗口gtk_signal_connect(GTK_OBJECT(window),destroy,GTK_SIGNAL_FUNC(gtk_main_quit),NULL);table=gtk_table_new(5,11,TRUE);/创建表格3行*5列gtk_widget_show(table);/显示表格gtk_container_add(GTK_CONTAINER(window),table);/将table1装进窗口 /* 创建进度条 */ progress_bar=gtk_progress_bar_new(); gtk_table_attach_defaults(GTK_TABLE(table),progress_bar,0,11,1,2);/进度条装进表格 gtk_widget_show(progress_bar); /* 加一个定时器(timer),以更新进度条的值 */ timer=gtk_timeout_add(150,progress_timeout,data); gtk_main (); return 0;3) S2.c#define GTK_ENABLE_BROKEN#include#includeGtkWidget *window;GtkWidget *table;GtkWidget *label;GtkWidget *button;GtkWidget *button1;int i=0; gint hello(void ) label=gtk_label_new(Hello World!);/创建标题 gtk_table_attach_defaults(GTK_TABLE(table),label,3,8,0,1); gtk_widget_show (label); return TRUE;n int main(int argc,char *argv) GtkWidget *vscrollbar; int timer; gpointer data; gtk_init(&argc,&argv);/在任何构件生成之前完成 window=gtk_window_new(GTK_WINDOW_TOPLEVEL);/创建窗口 gtk_window_set_title(GTK_WINDOW(window),Swindow2);/设置窗口标题 gtk_widget_set_usize(window, 200, 200);/设置窗口大小 gtk_container_set_border_width(GTK_CONTAINER(window),5);/设置窗口边框宽度 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);/设置窗口位置 gtk_widget_show(window);/显示窗口 gtk_signal_connect(GTK_OBJECT(window),destroy,GTK_SIGNAL_FUNC(gtk_main_quit),NULL); table=gtk_table_new(11,10,TRUE);/创建表格11行*10列 gtk_container_add(GTK_CONTAINER(window),table);/将table1装进窗口 gtk_widget_show(table);/显示表格/* 添加一个按钮,用来退出应用程序 */ button = gtk_button_new_with_label (close); gtk_table_attach_defaults(GTK_TABLE(table),button,3,8,6,8);/按钮装进表格 gtk_widget_show (button); gtk_signal_connect(GTK_OBJECT(button),clicked,GTK_SIGNAL_FUNC(gtk_main_quit),NULL); gtk_main (); return 0;4) S3.c#define GTK_ENABLE_BROKEN#include#includeGtkWidget *window;GtkWidget *table;GtkWidget *label;GtkWidget *text;int i=0; gint text_timeout( gpointer data ) char buf20; char temp10; sprintf(temp,%d,i); strcpy(buf,text ); strcat(buf,temp); strcat(buf,n); /将buf内容插入到文本构件中 gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf,-1); i+; /这是一个timeout函数,返回 TRUE,这样它就能够继续被调用 /如果想要结束,return 0;这样回调函数就会结束 return TRUE; int main(int argc,char *argv) GtkWidget *vscrollbar; int timer; gpointer data; gtk_init(&argc,&argv);/在任何构件生成之前完成 window=gtk_window_new(GTK_WINDOW_TOPLEVEL);/创建窗口 gtk_window_set_title(GTK_WINDOW(window),Swindow3);/设置窗口标题 gtk_widget_set_usize(window, 200, 400);/设置窗口大小 gtk_container_set_border_width(GTK_CONTAINER(window),5);/设置窗口边框宽度 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);/设置窗口位置 gtk_widget_show(window);/显示窗口 gtk_signal_connect(GTK_OBJECT(window),destroy,GTK_SIGNAL_FUNC(gtk_main_quit),NULL); table=gtk_table_new(11,10,TRUE);/创建表格11行*10列 gtk_container_add(GTK_CONTAINER(window),table);/将table1装进窗口 gtk_widget_show(table);/显示表格 label=gtk_label_new(Text List);/创建标题 gtk_table_attach_defaults(GTK_TABLE(table),label,0,10,0,1); gtk_widget_show (label); text=gtk_text_new(NULL,NULL);/创建文本构件 gtk_widget_show(text);/显示文本构件 /将文本构件装进表格 gtk_table_attach_defaults(GTK_TABLE(table),text,0,9,1,11); /创建滚动条并设置其与文本同步 vscrollbar=gtk_vscrollbar_new(GTK_TEXT(text)-vadj); gtk_widget_show (vscrollbar);/显示垂直滚动条 gtk_table_attach_defaults (GTK_TABLE (table), vscrollbar,9,10,1,11);/将滚动条装进表格 timer=gtk_timeout_add(1000,text_timeout,data);/调用回调函数,每隔1秒输出一行文本 gtk_main (); return 0;五、 课程设计内容二Linux内核,简单来说就是一套用来控制计算机最底层的硬件设备,如处理器、内存、硬盘等的一种软件,一般称为操作系统,在Linux术语中称为内核。其中包含的模块有存储管理、CPU和进程管理、文件系统、设备管理和驱动、网络通信,以及系统的初始化(引导)、系统调用等。这次题目就是要更改Linux内核中的”系统调用”模块,在其中添加自定义的函数,实现功能是文件拷贝。本次我选用的Linux内核版本是linux-需要做的工作流程基本如下:下载并解压内核修改内核中关于系统调用所需要的文件编译内核安装内核测试功能1. 下载并解压内核首先到官方网站/下载内核,不一定要最新的,以广大用户评定较稳定的内核为优先。我这次选用linux-其次打开终端,使用下列命令对其解压到目录/usr/srcsudo tar -xjvf linux-.tar.bz2 -C /usr/src该目录用来存放内核的源码。2. 修改内核首先要对系统调用模块的源码添加一个自定义函数,即对/usr/src/linux-/kernel/sys.c进行修改,在该源码的最后添加下列函数的源码:asmlinkage int sys_mycall(char* sourceFile,char* destFile) int source=sys_open(sourceFile,O_RDONLY,0); int dest=sys_open(destFile,O_WRONLY|O_CREAT|O_TRUNC,0600); char buf4096; mm_segment_t fs; fs = get_fs(); set_fs(get_ds(); int i; if(source0 & dest0) do i=sys_read(source,buf,4096); sys_write(dest,buf,i); while(i); else printk(Error!); sys_close(source); sys_close(dest); set_fs(fs); return 10;修改完函数之后,接下来要修改系统调用号所对应的函数名,即修改/usr/src/linux-0/arch/x86/include/asm/unistd_32.h该文件定义了系统调用号,我们只要找一没被使用的系统调用号,用该号给我们自定义函数使用,比如#define _NR_sys_mycall337/*定义系统调用sys_mycall 的系统调用号为337*/修改完系统调用号后,接下来要修改系统调用表,即/usr/src/linux-0/arch/x86/kernel/syscall_table_32.S,这个文件是用汇编语言编写的,因此要让自定义的系统调用相对于其他系统调用的顺序337个,写上.long sys_mycall /*337*/基本修改完以上源码后,接下来对其进行默认的净化、设置等。使用下列代码对其源码进行处理sudo make mrproper 净化解压后的源代码sudo make menuconfig对内核选项进行配置如果这一步有错误可能是正在使用的系统没有安装必要的库文件,如ncurses、libncurses*,这时候需要输入如下指令来安装首先回到系统根目录sudo apt-get install ncursessudo apt-get install libncurses*依照提示就能安装好必要的库文件了。然后再回到内核源码的目录下尝试使用sudo make menuconfig对内核选项进行配置。sudo make dep 建立模块间的依赖信息sudo make clean 删除配置时留下的一些不用的文件3. 编译内核接下来是最费时间的环节,少则2个小时,多则3个小时的编译,需要再三确保前面步骤是否正确后再进行下一步。sudo make bzImage编译内核这个过程大概是20多分钟sudo make modules编译内核模块这个过程大概要100分钟150分钟左右,一般如果有错误,会在前十几分钟就停止编译并报错。4. 安装内核比较简单,只需要两条指令sudo make modules_install 安装内核模块sudo make install 安装内核安装完毕后,需要开机时选择使用新的Linux核心,要做下列修改:1)复制内核到系统启动引导目录cp /usr/src/linux-/arch/i386/boot/bzImage /boot/vmlinuz--mykernel2)创建初始RAM磁盘initrd在创建之前先安装必要的程序apt-get install bootcd-mkinitramfsmkinitramfs -o /boot/initrd.img-3)更新grub在/boot/grub/grub.cfg中, 复制一段旧的核心代码,并将里面linux和initrd中的路径改为新增的,注意不能用update-grub2在/boot中复制一个旧的config-xxxxxx做为自己的4)cd /bootcp initrd.img- initrd-.old以上是备份initrid,下面是修改depmod aupdate-initramfs -k ccd /tmpgzip -dc /boot/initrd.img-| cpio -idtouch lib/modules//modules.depfind ./ | cpio -H newc -o /boot/initrd.img-.newgzip /boot/initrd.img-.newcd /bootmv initrd.img-.new.gz initrd.img-5)重开机测试5. 测试功能用C语言编写测试程序testsys.c,源代码如下:#include #include #include int main(int argc,char*argv) int i=syscall(337,argv1,argv2); /*337为系统调用号*/ printf(successfully!rn); printf(%d,i); return 1;编译gcc o testsys testsys.c运行./testsys test.txt target.txt系统调用337号功能,拷贝文件test.txt到target.txt运行结果截图如下:六、 课程设计内容三本题是为了更深刻了解模块机制,这种机制可以动态的在内核中添加或者删除模块。模块一旦被插入内核,他就和内核其他部分一样了。Unix系统将设备分为三种类型字符设备、块设备、网络接口;一般对应这三种模块字符模块、块模块、网络模块。字符设备,是能够像字节流一样被访问的设备,由字符设备驱动程式来实现这种特性。下面是一个的字符设备驱动程式。源代码sdev.c#include #include #include #include #include #include #define DEFAULT_MSG default dev datan/*默认字符设备数据*/#define DEVICE_NAME sdev/*设备名*/#define MAXBUF 20/*设备数据缓冲区大小*/static unsigned char sdev_bufMAXBUF;/*设备内存数据缓冲区*/static int sdev_open (struct inode *inode, struct file *file);static int sdev_release (struct inode *inode, struct file *file);static ssize_t sdev_read (struct file *file, char _user *buf,size_t count, loff_t *pos);static ssize_t sdev_write (struct file *file, const char _user *buf,size_t count, loff_t *pos);static int sdev_open (struct inode *inode, struct file *file) return 0;static int sdev_release (struct inode *inode, struct file *file) return 0;/*从设备读取count个数据到用户数据区buf中*/static ssize_t sdev_read (struct file *file, char _user *buf,size_t count, loff_t *pos) int size = count MAXBUF ? count : MAXBUF; /*选择读取数量 count or 数据缓冲区*/ if (copy_to_user(buf, sdev_buf, size)/*把设备数据copy到用户空间buf中,数量为size*/ return -ENOMEM;/*错误:内存不足*/ return size;/*把buf中count个数据写入设备内存空间中*/static ssize_t sdev_write (struct file *filp, const char _user *buf,size_t count, loff_t *pos) int size = count ops = &sdev_fops;/*设定字符设备操作函数指针*/ sdev_cdev-owner = THIS_MODULE;/*设备的属主*/ error = cdev_add(sdev_cdev, dev, 1);/*将设备添加到内核中去*/ if (error) printk(设备添加失败!n); unregister_chrdev_region(dev, 2);/*注销一个分配的设备号区域*/ cdev_del(sdev_cdev);/*删除字符设备对象*/ return error; memset (sdev_buf, 0, sizeof(sdev_buf);/*清空设备缓冲区数据*/ memcpy(sdev_buf, DEFAULT_MSG, sizeof(DEFAULT_MSG);/*设定设备缓冲区默认数据*/ printk(设备缓冲区默认数据: default dev datan);

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论