logo资料库

华科操作系统课程设计.doc

第1页 / 共14页
第2页 / 共14页
第3页 / 共14页
第4页 / 共14页
第5页 / 共14页
第6页 / 共14页
第7页 / 共14页
第8页 / 共14页
资料共14页,剩余部分请下载后查看
本科实验报告 课程名称: OS 实验报告 姓 名: 学 院: 计算机科学与技术 系: 计算机科学与技术 专 业: 计算机科学与技术 年 级: 学 号: 指导教师: 2007 年 4 月 15 日
一.实验目的 1.掌握 Linux 操作系统的使用方法; 2.了解 Linux 系统内核代码结构; 3.掌握实例操作系统的实现方法。 二. 实验环境 Linux-2.6.20.1(旧内核为 2.6.18.1) 三. 实验内容 1.编写一个 C 程序实现文件拷贝 2.编写一个 C 程序实现三个程序并发执行 3.通过系统调用实现文件拷贝 4.通过增加设备驱动的方法实现字符设备的驱动 5.利用 GTK 做一个任务管理器 四. 实验具体过程 1.编写一个 C 程序实现文件拷贝. a.程序说明 通过循环每次使用 fgetc 读取一个字符,直到文件末尾结束. b.程序源码 #include #include #include int main() { FILE *f1,*f2; f1=fopen("./source.txt","r"); f2=fopen("./source2.txt","w"); int s=0; while(!feof(f1)) { s=fgetc(f1); if(s==EOF) break; fputc(s,f2); } fclose(f1); fclose(f2); printf("Copy complete!!\n"); } 2. 编写一个 C 程序实现三个程序并发执行 a.程序说明 首先是主程序通过 fork 函数创建新进程,然后通过调用 execv 打开新文件以 到并发执行三个程序的目的. 2
子程序则使用了 GTK 编程,在一个窗体中放置了一个滚动条,加了个文字标签以改善视 觉效果. b.程序源码 子程序代码: #include typedef struct _ProgressData { GtkWidget *window; GtkWidget *pbar; int timer; gboolean activity_mode; } ProgressData; itoa(int i,char* string) { int power,j; j=i; for(power=1;j>=10;j/=10) power*=10; for(;power>0;power/=10) { *string++='0'+i/power; i%=power; } *string++='%'; *string='\0'; }//将整数转换成字符串 (GTK_PROGRESS_BAR (pdata->pbar)) + 0.005; if (new_val > 1.0) new_val = 0.0; /* 设置进度条的新值 */ itoa(new_val*100,s); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR new_val); gtk_progress_bar_set_text (pdata->pbar), (GTK_PROGRESS_BAR (pdata->pbar),s); /* 这是一个 timeout 函数,返回 TRUE, 这样它就能够继续被调用 */ return TRUE; } /* 清除分配的内存,删除定时器(timer) */ void *widget, destroy_progress( GtkWidget /* 更新进度条,这样就能够看到进度条的 移动 */ gint progress_timeout( gpointer data ) { ProgressData *pdata = (ProgressData *)data; gdouble new_val; char s[10]; ProgressData *pdata) gtk_timeout_remove (pdata->timer); pdata->timer = 0; pdata->window = NULL; g_free (pdata); gtk_main_quit (); { } /* 使用在调整对象中设置的取值范 char *argv[]) int main( int argc, 围计算进度条的值 */ new_val gtk_progress_bar_get_fraction { = ProgressData *pdata; GtkWidget *align; GtkWidget *separator; 3
GtkWidget *table; GtkWidget *button; GtkWidget *vbox; gtk_init (&argc, &argv); /* 为传递到回调函数中的数据分配内 存 */ pdata = g_malloc (sizeof (ProgressData)); pdata->activity_mode = !pdata->activity_mode; gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar)); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar),0.00); gtk_progress_bar_set_text (GTK_PROGRESS_BAR "0.00"); (pdata->pbar), pdata->window = gtk_window_new gtk_container_add (GTK_CONTAINER (GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE); (align), pdata->pbar); gtk_widget_show (pdata->pbar); /* 加一个定时器(timer),以更新进度条 g_signal_connect (G_OBJECT 的值 */ (pdata->window), "destroy", pdata->timer = gtk_timeout_add (100, G_CALLBACK progress_timeout, pdata); (destroy_progress), pdata); gtk_window_set_title (GTK_WINDOW (pdata->window), "这是窗口一"); gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0); vbox = gtk_vbox_new (FALSE, 5); gtk_container_set_border_width separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0); gtk_widget_show (separator); /* 行数、列数、同质性(homogeneous) */ table = gtk_table_new (2, 2, FALSE); gtk_box_pack_start (GTK_BOX (vbox), (GTK_CONTAINER (vbox), 10); table, FALSE, TRUE, 0); gtk_container_add (GTK_CONTAINER gtk_widget_show (table); (pdata->window), vbox); gtk_widget_show (vbox); /* 创建一个居中对齐的对象 */ align = gtk_alignment_new (0.5, 0.5, 0, */ /* 添加一个按钮,用来退出应用程序 button = gtk_button_new_with_label 0); ("close"); gtk_box_pack_start (GTK_BOX (vbox), g_signal_connect_swapped (G_OBJECT align, FALSE, FALSE, 5); gtk_widget_show (align); (button), "clicked", G_CALLBACK (gtk_widget_destroy), /* 创建进度条 */ pdata->pbar = gtk_progress_bar_new (); pdata->window); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); 4
/* 将按钮设置为能缺省的构件 */ GTK_WIDGET_SET_FLAGS (button, gtk_widget_grab_default (button); gtk_widget_show (button); GTK_CAN_DEFAULT); gtk_widget_show (pdata->window); /* 将缺省焦点设置到这个按钮上,使 gtk_main (); 之成为缺省按钮,只要按回车键 * 就相当于点击了这个按钮 */ return 0; 主程序代码: #include #include #include #include #include int semid; char *finish; int p1,p2; int main (void) { if((p1=fork())==0)//创建新进程 { execv("./gtk1",NULL); } else { c.程序截图 } if((p2=fork())==0) { execv("./gtk2",NULL); } else { if (fork()==0) { execv("./gtk3",NULL);// 打开文件执行 } } } return; } 3. 通过系统调用实现文件拷贝 a.程序说明: 5
要在 linux 下实现系统调用,首先修改内核中的三个文件,分别是 unistd.h,sys.c 和 syscalltable.s(这个是 2.6 版本和 2.4 版本的区别所在,2.4 版本要改的文件是 entry.s), 然后需要重新编译内核,具体步骤如下: Make clean Make bzImage Make modules Make modules_install Make install 最后一步最为关键,2.6 版本不需要手动修改 grub,只需要执行 make install 就会自动 修改 grub,然后只要在启动时选择新内核即可,完全不需要手工操作. 此外还需要一个测试文件,文件拷贝的代码当然是原先写在内核里,这里是 sys.c 文 件.编译后的内核下通过系统调用同样实现了程序一文件拷贝的效果. b.程序源码 测试程序: #include #include #include int mysyscall(char *f1,char *f2) { f1=sys_open(f1,"r"); f2=sys_open(f2,"w"); int s=0; Sys.c 里的文件拷贝代码: while(!feof(f1)) { s=fgetc(f1); if(s==EOF) break; fputc(s,f2); } sys_close(f1); sys_close(f2); printk("Copy complete!!\n"); } 6
c.程序补充说明 在原先使用 2.6.18.1 的系统上编译 2.6.20.1 的内核,编程不受影响,因为编译后我们 使用的是新内核,编译需要漫长的时间,我还发现第一次编译需要 make modules 和 make modules_install,而以后的重新编译则可以省略这两步,原因还有待进一步研究. 4.通过增加设备驱动的方法实现字符设备的驱动 a.程序说明 对于实现字符设备的驱动,首先要挂载字符设备,然后加载设备的驱动程序,然后再调 用测试程序进行测试.我们使用 mknod c 设备名称 设备号,这里 c 表示是字符设备.然后 我们可以通过 dmesg 查看每一步的进展情况.挂载设备成功后,通过分配的设备号,加载 设备的驱动,命令是 insmod 设备号.通过 lsmod 来查看所有挂载的设备,卸载设备则使 用 rmmod 设备号.所有这些完成后便可以开始测试了,编写测试程序 test.c 包含读设备 和写设备. b.程序源码 驱动的编译命令(包含在 makefile 里): ifneq ($(KERNELRELEASE),) obj-m := ljian.o else KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif 这里表示设备目标文件为 ljian.o 设备代码: #include #include #include #include #include #include #include #include #define SUCCESS 0 #define DEVICE_NAME "cdev" #define BUF_LEN 50 MODULE_LICENSE("GPL"); static int Device_Open=0; static int test_major=0;//设备号 static char Message[BUF_L EN]="test only!";// 测 试 文 本 static char *Message_Ptr; static int ljian_open(struct 7
inode *ind,struct file *fip) { printk("<1>device open:%d,%d\n",i nd->i_rdev>>8,i nd->i_rdev&0xF F); if(Device_Open) return -EBUSY; Device_Open++; Message_Ptr=Message; try_module_get( THIS_MODUL E); return SUCCESS; } static int ljian_release(struct inode *ind,struct file *fip) printk("<1>device release:%d,%d.\ n",ind->i_rdev> >8,ind->i_rdev& 0xFF); Device_Open--; module_put(THI S_MODULE); return 0; { } static ssize_t ljian_read(struct file *fip,char *buffer, size_t length,loff_t *offset) { int bytes_read=0; if(*Message_Ptr==0) return 0; printk("<1>The message is \"%s\"\n",Messa ge); while(length&& *Message_Ptr){ put_user(*(Mess age_Ptr++),buffe r++); length--; bytes_read++; } return bytes_read; } static ssize_t ljian_write(struct file *fip,const char *buffer, size_t length,loff_t *offset) { int i; printk("<1>Befor write test,the message is \"%s\"\n",Messa ge); 8
分享到:
收藏