logo资料库

linux 系统调用 实现文件复制.pdf

第1页 / 共14页
第2页 / 共14页
第3页 / 共14页
第4页 / 共14页
第5页 / 共14页
第6页 / 共14页
第7页 / 共14页
第8页 / 共14页
资料共14页,剩余部分请下载后查看
本科实验报告 课程名称: OS 实验报告 姓 名: 学 院: 计算机科学与技术 系: 计算机科学与技术 专 业: 计算机科学与技术 年 级: 学 号: 指导教师: 2010 年 1 月 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.程序源码 FILE *f1,*f2; #include #include #include int main() { 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'; }//将整数转换成字符串 /* 更新进度条,这样就能够看到进度条的 移动 */ gint progress_timeout( gpointer data ) { ProgressData *pdata = *)data; gdouble new_val; char s[10]; /* 使用在调整对象中设置的取值范 围计算进度条的值 */ new_val gtk_progress_bar_get_fraction (ProgressData = (pdata->pbar), (pdata->pbar)) + new_val = 0.0; (GTK_PROGRESS_BAR 0.005; if (new_val > 1.0) /* 设置进度条的新值 */ itoa(new_val*100,s); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR new_val); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),s); /* 这是一个 timeout 函数,返回 TRUE, 这样它就能够继续被调用 */ return TRUE; } /* 清除分配的内存,删除定时器(timer) */ void *widget, { gtk_timeout_remove (pdata->timer); pdata->timer = 0; pdata->window = NULL; g_free (pdata); gtk_main_quit (); } int main( int argc, char *argv[]) { ProgressData *pdata; GtkWidget *align; GtkWidget *separator; ProgressData *pdata) destroy_progress( GtkWidget 3
g_malloc (sizeof (G_OBJECT gtk_window_new G_CALLBACK GtkWidget *table; GtkWidget *button; GtkWidget *vbox; gtk_init (&argc, &argv); /* 为传递到回调函数中的数据分配内 存 */ pdata = (ProgressData)); pdata->window = (GTK_WINDOW_TOPLEVEL); gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE); g_signal_connect (pdata->window), "destroy", (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 (GTK_CONTAINER (vbox), 10); gtk_container_add (GTK_CONTAINER (pdata->window), vbox); gtk_widget_show (vbox); /* 创建一个居中对齐的对象 */ align = gtk_alignment_new (0.5, 0.5, 0, 0); gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5); gtk_widget_show (align); /* 创建进度条 */ pdata->pbar = gtk_progress_bar_new (); (pdata->pbar), 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"); gtk_container_add (GTK_CONTAINER (align), pdata->pbar); gtk_widget_show (pdata->pbar); /* 加一个定时器(timer),以更新进度条 的值 */ pdata->timer = gtk_timeout_add (100, progress_timeout, pdata); 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), table, FALSE, TRUE, 0); gtk_widget_show (table); /* 添加一个按钮,用来退出应用程序 */ button = gtk_button_new_with_label ("close"); g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy), pdata->window); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); 4
gtk_widget_grab_default (button); gtk_widget_show (button); gtk_widget_show (pdata->window); gtk_main (); return 0; } (button, /* 将按钮设置为能缺省的构件 */ GTK_WIDGET_SET_FLAGS GTK_CAN_DEFAULT); /* 将缺省焦点设置到这个按钮上,使 之成为缺省按钮,只要按回车键 * 就相当于点击了这个按钮 */ 主程序代码: #include #include #include #include #include int semid; char *finish; int p1,p2; int main (void) { if((p1=fork())==0)//创建新进程 { } else { c.程序截图 execv("./gtk1",NULL); } execv("./gtk2",NULL); if((p2=fork())==0) { } else { if (fork()==0) { 打开文件执行 } } } return; execv("./gtk3",NULL);// 3. 通过系统调用实现文件拷贝 5
a.程序说明: 要在 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; while(!feof(f1)) { s=fgetc(f1); if(s==EOF) break; fputc(s,f2); } sys_close(f1); sys_close(f2); printk("Copy complete!!\n"); } Sys.c 里的文件拷贝代码: 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 *fip,char file *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 *fip,const file char *buffer, size_t length,loff_t *offset) { int i; printk("<1>Befor write test,the message is \"%s\"\n",Messa ge); 8
分享到:
收藏