华中科技大学计算机操作系统实验报告

时间:2024.4.7

实验目的

掌握Linux操作系统的使用方法;

了解Linux系统内核代码结构;

掌握实例操作系统的实现方法。

一、        实验要求

1、            掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。

l  编一个C程序,其内容为实现文件拷贝的功能;

l  编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。

2、            掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。另编写一个应用程序,调用新增加的系统调用。

实现的功能是:文件拷贝;

3、            掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序,其功能可以简单。

实现字符设备的驱动;

4、            了解和掌握/proc文件系统的特点和使用方法

l  了解/proc文件的特点和使用方法

l  监控系统状态,显示系统中若干部件使用情况

l  用图形界面实现系统监控状态。

5、            设计并实现一个模拟的文件系统(选作)

二、        实验一

1、  编一个C程序,其内容为实现文件拷贝的功能

要实现文件拷贝功能,主要用到的函数是fopen、fputc、fgetc。

主要用到的头文件:

#include <stdio.h>

#include <stdlib.h>

设计思路:由scanf函数获取2个文件名,根据其文件名和路径分别打开该2个文件,设置一个循环,从源文件复制1个字节到目的文件,直到源文件指针到文件尾,最后关闭2个文件。

在可能出错的地方需要加上相应的报错代码,并输出错误信息,以方便调试。

理清楚设计思路后,首先搭建linux下编程环境。

安装gcc:                sudo apt-get install build-essential

安装codeblocks:          sudo apt-get install codeblocks

在集成开发环境Code::Blocks IDE下根据需求写出相应的源代码copy.c ,将程序编译并生成exe可执行文件。

然后手动创建一个测试文件test.txt ,运行copy.exe文件,并输入text.txt与target.txt。

这样就能将源文件test.txt复制到目标文件target.txt

程序源代码 copy.c

#include <stdio.h>

#include <stdlib.h>

int main()

{

    char a[20],b[20];

    scanf("%s",a);

    getchar();

    scanf("%s",b);

    FILE *p=NULL,*q=NULL;

    p=fopen(a,"rb");

    if(p==NULL){printf("%s    default",a);return 0;}

    q=fopen(b,"wb+");

    char c;

    while((c=fgetc(p))!=EOF)

    {

        fputc(c,q);

    }

    printf("copy success");

    return 0;

}

2、  编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。

安装Linux下的GTK+:

sudo apt-get install build-essential

这将安装gcc/g++/gdb/make 等基本编程工具

sudo apt-get install gnome-core-devel

这将安装 libgtk2.0-dev libglib2.0-dev 等开发相关的库文件

sudo apt-get install pkg-config

用于在编译GTK程序时自动找出头文件及库文件位置

sudo apt-get install devhelp

这将安装 devhelp GTK文档查看程序

sudo apt-get install libglib2.0-doc libgtk2.0-doc

这将安装 gtk/glib 的API参考手册及其它帮助文档

sudo apt-get install glade libglade2-dev

这将安装基于GTK的界面GTK是开发Gnome窗口的c/c++语言图形库

sudo apt-get install libgtk2.0*, gtk+2.0

所需的所有文件统通下载安装完毕

       编写一个GTK+程序的基本步骤如下:

l  初始化Gtk

l  建立控件

l  登记消息与消息处理函数

l  执行消息循环函数gtk_main()

              初始化主要使用的函数有

              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,           //以下参数是指定把物件放在哪里, 及用多少个boxes

gintright_attach,

ginttop_attach,

gintbottom_attach);

在Code::Blocks IDE创建GTK+工程如下流程:

首先在codeblocks选中File,然后选择New,最后Project。出现如上图所示界面。

在该界面中选中GTK+Project然后Go进入下一步。

继续Next,直到如下图输入工程名称与路径。

然后Next->Finish

这样,就创建了一个GTK+工程。

直接运行刚才创建的GTK+工程中的默认程序,得到一个包含2个按钮的窗口界面应用,如下图所示:

此时,可以按此模板修改源代码,也可以删除重写。

并发进程:

创建3个如上GTK+工程,生成3个不同的exe文件。

if ((p1=fork()) == 0)

    {

        execv("../1",NULL);

    }

    else if ((p2=fork())==0)

    {

        execv("../2",NULL);

    }

    else if ((p3=fork()==0))

    {

        execv("../3",NULL);

    }

    wait();

实验截图:

实验源代码:gtk.c:

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <linux/sem.h>

#include <linux/shm.h>

int main ()

{

    pid_t p1,p2,p3;

    if ((p1=fork()) == 0)

    {

        execv("/home/linux/Desktop/1/bin/Debug/1",NULL);

    }

    else if ((p2=fork())==0)

    {

        execv("/home/linux/Desktop/2/bin/Debug/2",NULL);

    }

    else if ((p3=fork()==0))

    {

        execv("/home/linux/Desktop/3/bin/Debug/3",NULL);

    }

    wait();

    return 0;

}

#include <stdlib.h>

#include <gtk/gtk.h>

static void helloWorld (GtkWidget *wid, GtkWidget *win)

{

  GtkWidget *dialog = NULL;

  dialog = gtk_message_dialog_new (GTK_WINDOW (win), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "1");

  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);

  gtk_dialog_run (GTK_DIALOG (dialog));

  gtk_widget_destroy (dialog);

}

int main (int argc, char *argv[])

{

  GtkWidget *button = NULL;

  GtkWidget *win = NULL;

  GtkWidget *vbox = NULL;

  /* Initialize GTK+ */

  g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL);

  gtk_init (&argc, &argv);

  g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL);

  /* Create the main window */

  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  gtk_container_set_border_width (GTK_CONTAINER (win), 8);

  gtk_window_set_title (GTK_WINDOW (win), "Hello World");

  gtk_window_move (GTK_WINDOW (win), 450,320);

  gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_CENTER);

  gtk_widget_realize (win);

  g_signal_connect (win, "destroy", gtk_main_quit, NULL);

  /* Create a vertical box with buttons */

  vbox = gtk_vbox_new (TRUE, 6);

  gtk_container_add (GTK_CONTAINER (win), vbox);

  button = gtk_button_new_from_stock (GTK_STOCK_DIALOG_INFO);

  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (helloWorld), (gpointer) win);

  gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);

  button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);

  g_signal_connect (button, "clicked", gtk_main_quit, NULL);

  gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);

  /* Enter the main loop */

  gtk_widget_show_all (win);

  gtk_main ();

  return 0;

}

三、        实验二

Linux内核,简单来说就是一套用来控制计算机最底层的硬件设备,如处理器、内存、硬盘等的一种软件,一般称为操作系统,在Linux术语中称为内核。其中包含的模块有存储管理、CPU和进程管理、文件系统、设备管理和驱动、网络通信,以及系统的初始化(引导)、系统调用等。

这次题目就是要更改Linux内核中的”系统调用”模块,在其中添加自定义的函数,实现功能是文件拷贝。

工作流程基本如下:

流程图: 终止:   结束

1.        下载并解压内核

到官方网站http://www.kernel.org/下载内核linux-2.6.32,打开终端,使用下列命令对其解压到目录/usr/src:

sudo tar -xjvf linux-2.6.32.tar.bz2 -C /usr/src

该目录用来存放内核的源码。

2.        修改内核

首先以root超级用户登录操作系统,要对系统调用模块的源码添加一个自定义函数,即对/usr/src/linux-2.6.32/kernel/sys.c进行修改,在该源码的最后添加下列函数的源码:

asmlinkage int sys_mycall(char* sourceFile,char* destFile)

{  

    int source=sys_open(sourceFile,O_RDONLY,0);

    int  dest=0;

    if(source>0)

          dest=sys_open(destFile,O_WRONLY|O_CREAT|O_TRUNC,0600);

    char buf[4096];

    mm_segment_t fs;

    fs = get_fs();

    set_fs(get_ds());

    int i;

    if(source>0 && dest>0)

{

       do{          

           i=sys_read(source,buf,4096);   

           sys_write(dest,buf,i);   

           }

        while(i);

i=1;

}

   

    else {printk("Error!");i=-1;}

    sys_close(source);

    sys_close(dest);

    set_fs(fs);

    return i;

}

修改完函数之后,接下来要修改系统调用号所对应的函数名,即修改/usr/src/linux-2.6.32/arch/x86/include/asm/unistd_32.h

该文件定义了系统调用号,我们只要找一没被使用的系统调用号,用该号给我们自定义函数使用,比如

#define __NR_sys_mycall          337

/*定义系统调用sys_mycall 的系统调用号为337*/

                     修改完系统调用号后,接下来要修改系统调用表,即/usr/src/linux-2.6.32/arch/x86/kernel/syscall_table_32.S,这个文件是用汇编语言编写的,因此要让自定义的系统调用相对于其他系统调用的顺序337个,写上.long sys_mycall   /*337*/

                    

                     基本修改完以上源码后,接下来对其进行默认的净化、设置等。

使用下列代码对其源码进行处理

sudo make mrproper       净化解压后的源代码

sudo make menuconfig            对内核选项进行配置

如果这一步有错误可能是正在使用的系统没有安装必要的库文件,如ncurses、libncurses*,这时候需要输入如下指令来安装

首先回到系统根目录

sudo apt-get install ncurses

sudo 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-2.6.32/arch/i386/boot/bzImage /boot/vmlinuz-2.6.32-mykernel

2)创建初始RAM磁盘——initrd

在创建之前先安装必要的程序

apt-get install bootcd-mkinitramfs

mkinitramfs -o /boot/initrd.img-2.6.32

                     3)更新grub

在/boot/grub/grub.cfg中, 复制一段旧的核心代码,并将里面linux和initrd中的路径改为新增的,注意不能用update-grub2

在/boot中复制一个旧的config-xxxxxx做为自己的

4)cd /boot

cp initrd.img-2.6.32 initrd-2.6.32.old

以上是备份initrid,下面是修改

depmod –a

update-initramfs -k 2.6.32 –c

cd /tmp

gzip -dc /boot/initrd.img-2.6.32| cpio -id

touch lib/modules/2.6.32/modules.dep

find ./ | cpio -H newc -o > /boot/initrd.img-2.6.32.new

gzip /boot/initrd.img-2.6.32.new

cd /boot

mv initrd.img-2.6.32.new.gz initrd.img-2.6.32

                     5)重开机测试

5.        测试功能

用C语言编写测试程序testsys.c,源代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <linux/unistd.h>

#include <asm/unistd.h>

int main()

{

    printf("1:A->B\tA:123.txt   B:456.txt\n");//A存在,B存在

    getchar();

    int i=syscall(337,"123.txt","456.txt");

    printf("%d\n\n",i);

    printf("2:A->B\tA:123.txt   B:empty.txt\n");//A存在,B不存在

    getchar();

    i=syscall(337,"123.txt","empty.txt");

    printf("%d\n\n",i);

    printf("3:A->B\tA:emptyA.txt   B:empty.txt\n");//A不存在,B存在

    getchar();

    i=syscall(337,"emptyA.txt","empty.txt");

    printf("%d\n\n",i);

    printf("4:A->B\tA:emptyA.txt   B:emptyB.txt\n");//A不存在,B不存在

    getchar();

    i=syscall(337,"emptyA.txt","emptyB.txt");

    printf("%d\n\n",i);

    return 0;

}

系统调用337号功能,拷贝文件。

A文件存在,B文件存在:拷贝成功,返回1

A文件存在,B文件不存在:创建B文件,拷贝成功,返回1

A文件不存在,B文件存在:B文件不变,拷贝失败,返回-1

A文件不存在,B文件不存在:拷贝失败,返回-1

运行结果截图如下:

【实验心得】

本次实验让我学到了许多东西,尤其是编译内核安装内核部分。我上网查阅了许多资料,受益匪浅。

另外,由于GTK是自学自用的一门语言,在自学过程中会受益匪浅。重视网络工具的利用,每当遇见不知道、不确定或者错误但自己无法修改的地方时我总会在网上找到前人已经遇见并且解决的相同问题,进而解决自身问题。最终自己也会学到很多东西。

更多相关推荐:
大学计算机基础实验报告

大学计算机基础课程实验报告手册学院年级专业姓名学号2220xx319xx20xx任课教师上机地点以上由学生填写实验教师签字西南大学计算机与信息科学学院计算机基础教育系年月日1一实验说明本课程实验分为一般性实验验...

大学计算机基础实验报告

大学计算机基础教学班级课程教师实验报告学号姓名实验辅导教师西南交通大学20xx年9月大学计算机基础实验报告实验一微机基本操作与上网冲浪教学班级学号姓名实验日期实验地点机房指导教师签名实验成绩一实验目的1掌握计算...

《大学计算机Ⅱ》实验报告实验一

广东金融学院实验报告课程名称:大学计算机Ⅱ

北理大学计算机实验基础 实验九 实验报告表

五实验报告学号姓名班级实验时间年月日实验报告图像生成与图像处理一填写下载图像的相关数据二查看左侧的图像请填写相应的图像编码三计算机中实际存储的图像可能有数几百万像素为了减少图像存储的空间有一种游程压缩方法可以减...

大学计算机一实验报告二

广东金融学院实验报告课程名称:大学计算机Ⅰ柠檬,lemon,那个和柠檬一样单纯的女生的名字,她说,她喜欢柠檬的苦涩与酸甜,就像,她一样。像柠檬一样的女生,她的爱情,是那般的青涩、酸甜,也让她有了前所未有的幸福。…

大学计算机Ⅱ》实验报告实验一

广东金融学院实验报告课程名称大学计算机第1页共2页实验一计算机组装与维护实验第3页共2页实验一计算机组装与维护实验第5页共2页

大学计算机基础网页制作实验报告

网页制作报告计算机基础网页制作报告20xx913网页制作报告目录一制作目的3二制作内容3三遇到的问题及解决方案3四报告成果截图展示4五制作体会5网页制作报告一制作目的掌握Dreamweaver的基本操作掌握网页...

大学计算机基础实验报告

大学计算机基础课程实验报告手册学院年级专业姓名学号2220xx319xx20xx任课教师上机地点以上由学生填写实验教师签字西南大学计算机与信息科学学院计算机基础教育系年月日1一实验说明本课程实验分为一般性实验验...

大学计算机基础实验报告4

浙江越秀外国语学院实验报告用纸

北京理工大学计算机实验三报告表[1]

实验三实验报告表实验名称字符编码与信息交换学号姓名班级实验时间实验报告表31西文字符显示过程编码记录表实验报告表32汉字显示过程编码记录表实验报告表33不同字体的字型码

华中科技大学计算机学院C++实验报告 实验三

课程实验报告课程名称面向对象程序设计实验名称面向对象的整型栈编程院系计算机科学与技术专业班级学号姓名指导教师日面向对象程序设计实验报告一需求分析1题目要求整型栈是一种先进后出的存储结构对其进行的操作通常包括判断...

华中科技大学计算机学院C++实验报告 实验四

课程实验报告课程名称面向对象程序设计实验名称面向对象的整型队列编程院系计算机科学与技术专业班级学号姓名指导教师年日面向对象程序设计实验报告一需求分析1题目要求整型队列是一种先进后出的存储结构对其进行的操作通常包...

大学计算机实验报告(48篇)