1、操作系统实验报告-华中科技大学计算机学院操作系统课程设计实 验 报 告 班 级: 学 号: 姓 名: 指导教师: 完成日期: 2010-04-02 一、实验目的:1.掌握Linux操作系统的使用方法;2.了解Linux系统内核代码结构;3.掌握实例操作系统的实现方法。二、实验题目:1.掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。1)编一个C程序,其内容为实现文件拷贝的功能;2)编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。 2.掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。另编写一个应用程
2、序,调用新增加的系统调用。实现的功能是:文件拷贝;3.掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序,其功能可以简单。实现字符设备的驱动。4.了解和掌握/proc文件系统的特点和使用方法(1)了解/proc文件的特点和使用方法(2)监控系统状态,显示系统中若干部件使用情况(3)用图形界面实现系统监控状态。 5. 设计并实现一个模拟的文件系统(选做)三、实验步骤及源代码:实验一题目一:源代码如下:#include#include #include #include int main() FILE *f1,*f2; f1=fopen(d:source1.txt,r); f2=f
3、open(d:source2.txt,w);while(!feof(f1)fputc(fgetc(f1),f2);fclose(f1);fclose(f2);printf(拷贝完成!n);创建文件copy.c,输入源代码。进入终端后使用编译命令:gcc copy2.c -o copy2 编译源代码。然后运行新生成文件./copy2,就会把source1.txt内的文字复制到source2.txt中(如果source2.txt不存在则会新建该文件)。结果如上图所示。题目二:源代码如下:3.c:#include #include #include #include #include int p1,
4、p2;int main (void) if(p1=fork()=0) execv(./gtk1,NULL); else if(p2=fork()=0) execv(./gtk2,NULL); else if (fork()=0) execv(./gtk3,NULL); return 0;gtk1.c:#include /* 传到这个函数的数据被打印到标准输出 */void callback( GtkWidget *widget, gpointer data ) g_print (Process 1- %s was pressedn, (char *) data);/* 这个回调退出程序 */g
5、int delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ) gtk_main_quit (); return FALSE;int main( int argc,char *argv ) GtkWidget *window; GtkWidget *button; GtkWidget *table; gtk_init (&argc, &argv); /* 创建一个新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 设置窗口标题 */ gtk_window_set
6、_title (GTK_WINDOW (window), 进程一); /* 为delete_event设置一个立即退出GTK的处理函数。 */ g_signal_connect (G_OBJECT (window), delete_event, G_CALLBACK (delete_event), NULL); /* 设置窗口的边框宽度。 */ gtk_container_set_border_width (GTK_CONTAINER (window), 20); /* 创建一个2x2的表 */ table = gtk_table_new (2, 2, TRUE); /* 将表放进主窗口 */
7、 gtk_container_add (GTK_CONTAINER (window), table); /* 创建第一个按钮 */ button = gtk_button_new_with_label (button 1); /* 当这个按钮被点击时,我们调用 callback 函数,并将一个 * 指向button 1的指针作为它的参数 */ g_signal_connect (G_OBJECT (button), clicked, G_CALLBACK (callback), (gpointer) button 1); /* 将button 1插入表的左上象限(quadrant) */ gt
8、k_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 0, 1); gtk_widget_show (button); /* 创建第二个按钮 */ button = gtk_button_new_with_label (button 2); /* 当这个按钮被点击时,我们调用 callback 函数,并将一个 * 指向button 2的指针作为它的参数 */ g_signal_connect (G_OBJECT (button), clicked, G_CALLBACK (callback), (gpointer) button 2
9、); /* 将button 2插入表的右上象限 */ gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 0, 1); gtk_widget_show (button); /* 创建Quit按钮 */ button = gtk_button_new_with_label (Quit); /* 当这个按钮被点击时,我们调用 delete_event 函数接着 * 程序就退出了 */ g_signal_connect (G_OBJECT (button), clicked, G_CALLBACK (delete_event), N
10、ULL); /* 将退出按钮插入表的下面两个象限 */ gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2); gtk_widget_show (button); gtk_widget_show (table); gtk_widget_show (window); gtk_main (); return 0;gtk2.c和gtk3.c的源代码与gtk1.c的大致相同。依照源代码分别将gtk1.c、gtk1.c、gtk1.c和3.c文件编写好。进入终端后分别编译这几个文件。编译gtk1.c的命令为:gcc gtk1.c
11、 -o gtk2 pkg-config -cflags -libs gtk+-2.0因为该程序使用了gtk编程,所以需要在后面加上参数pkg-config -cflags -libs gtk+-2.0。编译3.c的命令与题目一中程序一样为:gcc 3.c -o 3编译完成后会生成相应的两个可执行文件。最后输入./3即可执行main程序,所得结果如上图所示,一共建立了3个进程process1、 process2和 process3。点击各自的quit按钮即可关闭所在的进程。实验二源代码如下:系统调用代码:asmlinkage int sys_filecopy(char* sourceFile,c
12、har* distFile) int f1,f2,n; char buf512; mm_segment_t fs; if(f1=sys_open(sourceFile,O_RDONLY,0) =-1) printk(Cant open %sn,sourceFile); sys_exit(-1); if(f2=sys_open(distFile,O_CREAT|O_WRONLY|O_TRUNC,0666)=-1) printk(Cant creat %s,mode %on,distFile,0666); sys_exit(-1); fs=get_fs(); set_fs(get_ds(); wh
13、ile(n=sys_read(f1,buf,512)0) if(sys_write(f2,buf,n)!=n) printk(write error on file %s,distFile); sys_exit(-1); set_fs(fs); sys_close(f1); sys_close(f2); return 0;filecopy.c(测试代码): #include#include #include#include#define _NR_filecopy 337 int main(int argc,char *argv) int i; if(argc !=3) printf(error
14、!); else i=syscall(337,argv0,argv1); printf(ok!); return 0;实验步骤如下:1.将内核包linux-2.6.31.12.tar解压到 /usr/src 下。2.增加新的系统调用,修改sys.c。使用命令sudo gedit /usr/src/linux-2.6.31.12/kernel/sys.c打开sys.c文件,将系统调用的代码加入该文件中。3.修改系统调用表syscall_table_32.S::使用命令 sudo gedit /usr/src/linux-2.6.31.12/arch/x86/kernel/syscall_tabl
15、e_32.S打开系统调用表,在最后加上 .long sys_filecopy4.增加新系统调用号,修改unistd.h使用命令 sudo gedit /usr/src/linux-2.6.31.12/arch/x86/include/unistd_32.h打开该文件,在其中添加:#define _ _NR_filecopy 337。5.编译内核,依次输入以下命令:sudo cd /usr/src/linux-2.6.31.12sudo make menuconfigsudo make bzImagesudo make modulessudo make modules_installsudo c
16、p arch/i386/boot/bzImage /boot/vmlinuz-2.6.31.12sudo mkinitramfs -o initrd.img-2.6.31.12 2.6.31.126.修改grub:使用命令sudo gedit /boot/grub/grub.cfg 打开grub.cfg文件,仿照文件中的格式加入下列代码:menuentry Ubuntu, Linux 2.6.31.12 insmod ntfs set root=(hd0,8) search -no-floppy -fs-uuid -set e67496277495fb0f loopback loop0 /ub
17、untu/disks/root.disk set root=(loop0) linux /boot/vmlinuz-2.6.31.12 root=/dev/sda8 loop=/ubuntu/disks/root.disk ro quiet splash initrd /boot/inird-2.6.31.12.img7.重启,导入新的内核,测试。重启后选择Ubuntu, Linux 2.6.31.12进入,编译写好的测试文件filecopy.c。在终端中输入gcc filecopy.c -o filecopy 编译源代码,然后输入./filecopy 1.txt 2.txt运行新生成文件,如
18、果1.txt不存在,则会报错,若存在,则成功复制。运行结果如上图所示,所达成的功能与实验一相同。实验三源代码如下:device.c(驱动程序代码):#include #include #include #include MODULE_LICENSE(GPL);#define MAJOR_NUM 147 static ssize_t d_read(struct file *, char *, size_t, loff_t*);static ssize_t d_write(struct file *, const char *, size_t, loff_t*);static ssize_t d_
19、open(struct inode *,struct file *);static ssize_t d_release(struct inode *,struct file *);struct file_operations d_fops= .read=d_read, .write=d_write, .open=d_open, .release=d_release,;static char var1024=Device test:; int counter=12;static int _init device_init(void) int result; result = register_c
20、hrdev(MAJOR_NUM, device, &d_fops); if(result) printk(device register failure); else printk(device register success); return result;static void _exit device_exit(void) unregister_chrdev(MAJOR_NUM, device); printk(unloading the device.);static ssize_t d_read(struct file *filp, char *buf, size_t len, l
21、off_t *off) if(copy_to_user(buf,var,1024*sizeof(char) return - EFAULT; return sizeof(char);static ssize_t d_write(struct file *filp,const char *buf,size_t len,loff_t *off) if(copy_from_user(var+counter,buf,len*sizeof(char) return - EFAULT; counter+=len; return sizeof(char);static ssize_t d_open(stru
22、ct inode *inode,struct file *file) printk(KERN_INFO open it!n); return 0;static ssize_t d_release(struct inode *inode,struct file *file) printk(KERN_INFO close itn); return 0;module_init(device_init);module_exit(device_exit);Makefile(Makefile文件):ifneq ($(KERNELRELEASE),) #kbuild syntax.mymodule-objs
23、 :=device.o obj-m := device.o elsePWD :=$(shell pwd)KVER :=$(shell uname -r)KDIR :=/lib/modules/$(KVER)/buildall: $(MAKE) -C $(KDIR) M=$(PWD)clean: rm -f *.cmd *.o *.mod *.koendifsdevice.c(测试程序代码):#include #include #include #include #include main() int fd; char buffer1024; int num; fd=open(/dev/devi
24、ce,O_RDWR,S_IRUSR|S_IWUSR); if(fd!=-1) read(fd,buffer,1024*sizeof(char); printf(The device is %sn,buffer); printf(Please input the characters written to device:n); fgets(buffer,1024,stdin); num=strlen(buffer)-1; write(fd,buffer,num*sizeof(char); read(fd,buffer,1024*sizeof(char); printf(The device is
25、 %sn,buffer); close(fd); else printf(Device open failuren); 首先依照源代码分别创建相应的3个文件并保存。其中device.c和Makefile要保存在一个文件夹下。然后依次输入以下命令:sudo make (此时在device.c所在文件夹内会生成数个文件)sudo insmod -f device.kosudo cat /proc/devices在出现的项目中寻找device项,记住其对应的设备号(本次为147)。输入命令sudo mknod /dev/device c 147 0,其中c指创建字符设备,第一个参数为主设备号,第二个
26、从设备号为0。之后即可编译并执行测试程序了。调试过程及结果如下图所示:运行调试程序时需使用命令sudo ./sdevice,否则就会出现上图中出现的错误提示。最后使用命令sudo rmmod device即可卸载驱动。四、心得体会:此次课程设计在linux平台上进行的,还是充满了好奇的,当在同学的指导下完成部分实验时内心还是很开心的。自己对程序设计不是很感兴趣,学得也不杂样,在余建同学的帮助下完成此次课程设计的,在同学的帮助下练习了实验的操作,不过通过实验还是收获了不少,第一次切身使用linux系统,在linux系统下还进行了许多其它操作,体会到了它与windows的很大不同,当用linux完成很多平时在windows下觉得很简单的任务时,觉得很惊奇。实验操作中也学会了许多命令,了解了一些linux命令的使用方法。比如说许多命令前都要加上sudo来修改访问权限,否则系统就无法执行相关的指令,开始操作的时候总是忽略,造成错误,后来了解后才在后来的操作中没有犯同样的错误。虽然此次课程设计没有认认真真地花花很大精力去做,但是还是收获了不少。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1