操作系统实验报告

.实验目的

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

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

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

. 实验环境

       ubuntu8.04(内核Linux-2.6.24-23

. 实验内容

    1.编写一个C程序,使用Linux下的图形库,分窗口显示三个并发进程的运行

    2.采用模块方法,添加一个新的设备驱动程序;要求添加字符设备的驱动,编写一个 程序测试所写的驱动。

    3.了解/proc文件的特点和使用方法,监控系统状态,显示系统中若干部件的使用情   况,用图形界面显示系统监控状态。

. 实验具体过程

       1. 编写一个C程序,使用Linux下的图形库,分窗口显示三个并发进程的运行

         a.程序说明

              首先是主程序通过fork函数创建新进程,然后通过调用execv打开新文件以

到并发执行三个程序的目的. 子程序则使用了GTK编程,窗口1显示一个滚动条,窗口2显示输出文本,窗口3既显示滚动条,又显示文本输出。

         b.程序源码

子程序1

//编译: gcc -o progress_bar progress_bar.c  `pkg-config   --cflags   --libs   gtk+-2.0`

 

#include

#include

GtkWidget *window;

GtkWidget *table;

GtkWidget *button;

GtkWidget *progress_bar;

// 更新进度条,这样就能够看到进度条的移动

gint progress_timeout( gpointer data ){

       gdouble value;

       int v;

       char text[20]="0%";

      //使用在调整对象中设置的取值范围计算进度条的值

       value=gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR (progress_bar))+0.01;

       if (value>1.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),"窗口1");//设置窗口标题

       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(3,5,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,5,0,1);//进度条装进表格

           gtk_widget_show(progress_bar);

        

        

           /* 加一个定时器(timer),以更新进度条的值 */

           timer=gtk_timeout_add(100,progress_timeout,data);

       /* 添加一个按钮,用来退出应用程序 */

           button = gtk_button_new_with_label ("close");

       gtk_table_attach_defaults(GTK_TABLE(table),button,0,5,2,3);//进度条装进表格

       gtk_widget_show (button);

           gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(gtk_main_quit),NULL);

      gtk_main ();

    return 0;

}

子程序2

//编译: gcc -o window_text window_text.c  `pkg-config   --cflags   --libs   gtk+-2.0`

 

#define GTK_ENABLE_BROKEN

#include

#include

 

GtkWidget *window;

GtkWidget *table;

GtkWidget *label;

GtkWidget *text;

int i=0;

gint text_timeout( gpointer data ){

        

       char buf[20];

       char temp[10];

       sprintf(temp,"%d",i);

       strcpy(buf,"show text ");

       strcat(buf,temp);

       strcat(buf,"/n");

       //buf内容插入到文本构件中

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf,-1);

       i++;

      //这是一个timeout函数,返回 TRUE,这样它就能够继续被调用

       //如果想要结束,可以在进度条到100%时,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),"窗口2");//设置窗口标题

       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(11,10,TRUE);//创建表格11*10

       gtk_container_add(GTK_CONTAINER(window),table);//table1装进窗口

       gtk_widget_show(table);//显示表格

       label=gtk_label_new("ShowText");

       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;

}

子程序3

//编译: gcc -o text_bar text_bar.c  `pkg-config   --cflags   --libs   gtk+-2.0`

#define GTK_ENABLE_BROKEN

#include

#include

GtkWidget *window;

GtkWidget *table;

GtkWidget *button;

GtkWidget *progress_bar;

GtkWidget *label;

GtkWidget *text;

int i=0;

gint text_timeout( gpointer data ){

        

       char buf[20];

       char temp[10];

       sprintf(temp,"%d",i);

       strcpy(buf,"show text_bar ");

       strcat(buf,temp);

       strcat(buf,"/n");

 

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf,-1);

       i++;

      //这是一个timeout函数,返回 TRUE,这样它就能够继续被调用

       //如果想要结束,可以在进度条到100%时,return 0;这样回调函数就会结束

      return TRUE;

}

 

// 更新进度条,这样就能够看到进度条的移动

gint progress_timeout( gpointer data ){

       gdouble value;

       int v;

       char text[20]="0%";

      //使用在调整对象中设置的取值范围计算进度条的值

       value=gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress_bar))+0.01;

       if (value>1.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[]){

       GtkWidget *vscrollbar;

       int timer;

       gpointer data;

        

       gtk_init(&argc,&argv);//在任何构件生成之前完成

       window=gtk_window_new(GTK_WINDOW_TOPLEVEL);//创建窗口

       gtk_window_set_title(GTK_WINDOW(window),"窗口3");//设置窗口标题

       gtk_widget_set_usize(window, 400, 400);//设置窗口大小

       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(10,8,TRUE);//创建表格10*8

       gtk_widget_show(table);//显示表格

       gtk_container_add(GTK_CONTAINER(window),table);//table1装进窗口

 

       label=gtk_label_new("ShowText");

       gtk_table_attach_defaults(GTK_TABLE(table),label,0,8,1,2);

           gtk_widget_show (label);

       text=gtk_text_new(NULL,NULL);//创建文本构件

       gtk_widget_show(text);//显示文本构件

       //将文本构件装进表格

       gtk_table_attach_defaults(GTK_TABLE(table),text,0,7,2,9);

 

       //创建滚动条并设置其与文本同步

       vscrollbar=gtk_vscrollbar_new(GTK_TEXT(text)->vadj);

       gtk_widget_show (vscrollbar);//显示垂直滚动条

       gtk_table_attach_defaults (GTK_TABLE (table), vscrollbar,7,8,2,9);//将滚动条装进表格

       timer=gtk_timeout_add(1000,text_timeout,data);

           /* 创建进度条 */

           progress_bar=gtk_progress_bar_new();

       gtk_table_attach_defaults(GTK_TABLE(table),progress_bar,0,8,0,1);//进度条装进表格

           gtk_widget_show(progress_bar);

        

        

           /* 加一个定时器(timer),以更新进度条的值 */

           timer=gtk_timeout_add(100,progress_timeout,data);

       /* 添加一个按钮,用来退出应用程序 */

           button = gtk_button_new_with_label ("close");

       gtk_table_attach_defaults(GTK_TABLE(table),button,3,5,9,10);//进度条装进表格

       gtk_widget_show (button);

           gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(gtk_main_quit),NULL);

        

      gtk_main ();

   

    return 0;

}

主程序:

#include

#include

#include

#include

#include

int semid;

char *finish;

int p1,p2;

int main (void){

       if((p1=fork())==0){//创建新进程

              execv("./progress_bar",NULL);

       }

       else{                               

              if((p2=fork())==0){

              execv("./window_text",NULL);

              }

              else{

                     execv("./text_bar",NULL);

              }

               

       }

       return 0;

}

 

 

 

 

 

               

 

 

 

 

 

 

程序运行结果:

 

2.采用模块方法,添加一个新的设备驱动程序 ;要求添加字符设备的驱动,编写一个 程序测试所写的驱动

a.程序说明

              对于实现字符设备的驱动,首先要挂载字符设备,然后加载设备的驱动程序,然后再调用测试程序进行测试.首先编译自己写的驱动,编译成功后再用“insmod mydev.ko”来装载驱动,接着创建设备节点,用户进程通过/dev/mydev这个路径就可以访问到这个全局变量虚拟设备了,使用“mknod 路径(如/dev/mydev) c 主设备号 次设备号来实现,卸载设备使用“rmmod 设备名通过cat /proc/devices来查看所有挂载的设备,所有这些完成后便可以开始测试了,编写测试程序test.c包含读设备和写设备.

              注意:在编译设备时,如果采用命令行编译,很有可能会提示找不到头文件,这个或许是因为你的linux系统没有内核头文件的源码包,可以采用编写makefile文件来编译设备,如果还不行,可以去下载一个内核源码包,重新编译内核,或者干脆还一个linux系统。

b.程序源代码

字符设备源代码

#include

#include

#include

#include

#include

#include

MODULE_LICENSE("Dual BSD/GPL");

int mydev_major = 0;

char *buffer=" ";

ssize_t mydev_write (struct file *filp, const char __user *buf, size_t count,loff_t *pos){

       int ret;

       ret=copy_from_user(buffer,buf,count);

       return 1;

}

//buf是用户进程空间的一个地址.但是在mydev_read被调用时,系统进入核心态.

//所以不能使用buf这个地址,必须用copy_to_user,这是kernel提供的一个函数,用于向用户传送数据.

ssize_t mydev_read(struct file *filp, char __user *buf,size_t count, loff_t *pos){

       int ret;

       ret=copy_to_user(buf,buffer,count);

       return 1;

}

struct file_operations mydev_fops ={ //系统调用和驱动程序关联起来

       .read = mydev_read,

       .write = mydev_write,

       .owner = THIS_MODULE

};

int mydev_init(void){

       if((mydev_major=register_chrdev (0, "mydev", &mydev_fops))>=0){

              printk("register success!/n");

       return 1;

       }

       else{

              printk("register failed!/n");

              return 0;

       }

}

void mydev_cleanup(void){

       unregister_chrdev (mydev_major, "mydev");

}

module_init(mydev_init);

module_exit(mydev_cleanup);

 

 

 

 

 

makefile文件

ifneq ($(KERNELRELEASE),)

       obj-m := mydev.o

else

       KERNELDIR ?= /lib/modules/$(shell uname -r)/build

       PWD := $(shell pwd)

default:

       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

install:

       sudo insmod mydev.ko

unstall:

       sudo rmmod mydev

clean:

       rm -rf *.o *.ko .*.cmd *.mod.c .tmp_versions

测试程序源代码:

#include "fcntl.h"

#include "unistd.h"

#include "stdio.h"

#include "sys/types.h"

#include "sys/stat.h"

#include

 

int main()

{

       char buf[32];

       int fd;

       printf("please input:");

       scanf("%s",buf);

       fd=open("/dev/mydev",O_RDWR); //要在根用户下运行

       if(write(fd,buf,32)<0){

              printf("error in write/n");

       }

       if(read(fd,buf,32)<0)

       {

              printf("error in read/n");

              return 0;

       }

       else

       {

              printf("The content readed from mydev is : %s/n",buf);

              return 1;

       }

}

程序编译及运行如下:(都要在根用户下进行

先在终端 输入:make

接着                make install(或者insmod mydev.ko)

然后输入          cat /proc/devices  查看字符设备是否已经挂载,如下

 

 

 

 

 

可见分配的主设备号为253

然后输入       mknod /dev/mydev c 253 0  创建设备节点

然后测试程序:gcc -o test test.c

                     ./test

结果如下:please input:dsakfdja

                The content readed from mydev is : dsakfdja

最后卸载设备:make unstall(或者rmmod mydev

删除设备节点:rm /dev/mydev

通过:cat /proc/devices 查看设备是否已经卸载

 

 

 

 

 

 

3.了解/proc文件的特点和使用方法,监控系统状态,显示系统中若干部件的使用情 况,用图形界面显示系统监控状态。

       主要参考书目:<教程>>,百度,google

       a.程序说明:

        1。首先编写GTK界面:

        创建窗口;

        然后创建表格,将表格添加进窗口,创建一个菜单条放在表格的第一行,再创建5个按钮放在第二行,靠左对齐,在第二行的最右添加一个标签,用于显示系统时间;

        创建一个状态栏放在表格最末行;

        在第三行至倒数第二行的表格中创建一个框架;

        在框架中又创建一个表格:在表格中创建一个文本构件(当按钮点击时产生事件,在文本构件中实时显示对应按钮的信息。

        2。读取/proc中的信息:

        /proc/stat读取cpu各状态的时间,进而算出cpu利用率;

        /proc/meminfo读取内存总量和可用内存,算出内存利用率;

        /proc这个目录下读取数字文件夹的数量,即是进程总数;

        /proc/cpuinfo读取cpu的信息;

        /proc/meminfo读取内存信息;

        /proc/进程号/status读取进程名,/proc/进程号/statm读取进程占用内存大      小,进而显示出进程相关信息;

        /proc/partitions读取硬盘信息;

        /proc/sys/kernel/hostname读取主机名;

        /proc/version读取内核版本;

        为了格式化显示这些读取的信息,使用了strtok字符串分割函数,sprintf函数可以从某种规则中读取出自己需要的字符串,sscanf函数则是连接两个字符串最好的操作参数。

        3。事件处理及实时显示

        事件处理用gtk_signal_connect,实时显示则用gtk_timeout_add调用回调函数来达到每隔一段时间更新显示。

                   b.程序源代码

//编译时如下: gcc -o proctemppd proctemppd.c `pkg-config   --cflags   --libs   gtk+-2.0` 

 

#define GTK_ENABLE_BROKEN

#include

#include

#include"dirent.h"

#include"unistd.h"

#include"sys/file.h"

#include"fcntl.h"

#include"string.h"

#include"time.h"

#include"math.h"

#include

#include

struct Process{

       char name[25];

       char pro_id[10];

       char cpu_take[10];

       char mem_take[10];

}pro[200];

char *title[5]={"CPU","Mem","Proc","Disk","Sys"};

char *title1[5]={"cpu version&run state","memory state","process state","disk information","system time&kernel version"};

GtkWidget *text;

GtkWidget *table;

GtkWidget *table1;//定义表格

GtkWidget *frame;//定义框架

GtkWidget *button[5],*label1,*cpu_rate_label,*process_label,*mem_rate_label,*time_label;//定义标签

gint length;

int mem_flag,pro_flag;//定义两个标志变量,用来判断是否结束回调函数

 

GtkWidget *CreateMenuItem(GtkWidget *,char *);

GtkWidget *CreateMenuFile(GtkWidget *);

GtkWidget *CreateMenuShutDown(GtkWidget *);

GtkWidget *CreateMenuHelp(GtkWidget *);

gint cpu_rate_ava(void);

gint mem_rate(void);

gint process_num(void);

gint mem_timeout(void);

gint pro_timeout(void);

gint sys_time(void);

 

void cpu_button_clicked(GtkWidget *,gpointer *);

void mem_button_clicked(GtkWidget *,gpointer *);

void pro_button_clicked(GtkWidget *,gpointer *);

void disk_button_clicked(GtkWidget *,gpointer *);

void sys_button_clicked(GtkWidget *,gpointer *);

 

int select_name(char name[]){

       int i;

       for(i=0;name[i]!=0;i++)

              if(isalpha(name[i])||name[i]=='.')

              return 0;

       return 1;

}

void delete_event(GtkWidget *window,gpointer data){//回调函数,退出窗口管理程序

       gtk_main_quit();

}

void restart(GtkWidget *window,gpointer data){//回调函数,重启

       system("reboot");

}

void shutdown(GtkWidget *window,gpointer data){//回调函数,关机

       system("halt");

}

void aboutgtk(GtkWidget *window,gpointer data){//输出有关gtk的信息

       GtkWidget *dialog,*label,*dtable,*text;

      char *buf="Library to build graphical user interfaces (GUIs)/noriginally for X Window. Designed to be small, /nefficient, flexible. Coded in C, in very object-oriented/n ";

       dialog=gtk_dialog_new();

       gtk_widget_set_usize(dialog, 200, 200);

       gtk_container_set_border_width(GTK_CONTAINER(dialog),5);//设置窗口边框宽度

       dtable=gtk_table_new(11,10,TRUE);//创建表格11*10

       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),dtable, TRUE, TRUE, 0);

       gtk_widget_show(dtable);//显示表格

       label=gtk_label_new("AboutGtk");

       gtk_table_attach_defaults(GTK_TABLE(dtable),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(dtable),text,0,10,1,11);

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf,-1);

       gtk_widget_show(dialog);

}

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

       GtkWidget *window;//定义窗口

       gint i;

 

       GtkWidget *vscrollbar,*hscrollbar;//定义滚动条

       GtkWidget *notebook;//定义笔记本

       GtkWidget *status_bar;//定义状态栏

        

       GtkWidget *MenuBar;/*定义菜单条*/

       GtkWidget *MenuItemFile,*MenuItemShutDown,*MenuItemHelp;

 

       gpointer data;

       gint sign;

 

       gtk_init(&argc,&argv);//在任何构件生成之前完成

       window=gtk_window_new(GTK_WINDOW_TOPLEVEL);//创建窗口

       gtk_window_set_title(GTK_WINDOW(window),"Source Manager");//设置窗口标题

       gtk_widget_set_usize(window, 480, 500);//设置窗口大小

       gtk_container_set_border_width(GTK_CONTAINER(window),5);//设置窗口边框宽度

       gtk_widget_show(window);//显示窗口

       table=gtk_table_new(12,10,TRUE);//创建表格11*10

       gtk_widget_show(table);//显示表格

       gtk_container_add(GTK_CONTAINER(window),table);//table1装进窗口

       for(i=0;i<5;i++){

              button[i]=gtk_button_new_with_label(title[i]);

              gtk_table_attach_defaults(GTK_TABLE(table),button[i],i,i+1,1,2);           

              gtk_widget_show(button[i]);

       }

       frame=gtk_frame_new(NULL);//创建框架

       gtk_container_set_border_width(GTK_CONTAINER(frame),0);//设置框架边框宽度

       //设置框架的风格

      gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);

       gtk_table_attach_defaults(GTK_TABLE(table),frame,0,10,2,11);

       gtk_widget_show(frame);//显示框架

       table1=gtk_table_new(12,11,TRUE);//创建表格12*11

       gtk_widget_show(table1);//显示表格

       gtk_container_add(GTK_CONTAINER(frame),table1);//将表格放入框架

       text=gtk_text_new(NULL,NULL);//创建文本框构件

       //buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));//获得文本框缓冲区

       gtk_widget_show(text);//显示文本构件

       //将文本构件装进表格

       gtk_table_attach_defaults(GTK_TABLE(table1),text,0,10,1,12);

       //创建滚动条并设置其与文本同步

       vscrollbar=gtk_vscrollbar_new(GTK_TEXT(text)->vadj);

       gtk_widget_show (vscrollbar);//显示垂直滚动条

       gtk_table_attach_defaults (GTK_TABLE (table1), vscrollbar,10,11,1,12);//将滚动条装进表格

 

       label1=gtk_label_new("进程名/t/t进程号/t/t占用内存");

        

       gtk_table_attach_defaults(GTK_TABLE(table1),label1,0,11,0,1);

 

       time_label=gtk_label_new(" ");//显示系统时间

       sign=gtk_timeout_add(100,(GtkFunction)sys_time,data);

       gtk_table_attach_defaults(GTK_TABLE(table),time_label,8,10,1,2);

       gtk_widget_show(time_label);

       //以下为点击按钮的时间响应函数

       gtk_signal_connect(GTK_OBJECT(button[0]),"clicked",GTK_SIGNAL_FUNC(cpu_button_clicked),NULL);

       gtk_signal_connect(GTK_OBJECT(button[1]),"clicked",GTK_SIGNAL_FUNC(mem_button_clicked),NULL);

       gtk_signal_connect(GTK_OBJECT(button[2]),"clicked",GTK_SIGNAL_FUNC(pro_button_clicked),NULL);

       gtk_signal_connect(GTK_OBJECT(button[3]),"clicked",GTK_SIGNAL_FUNC(disk_button_clicked),NULL);

       gtk_signal_connect(GTK_OBJECT(button[4]),"clicked",GTK_SIGNAL_FUNC(sys_button_clicked),NULL);

        

 

       MenuBar=gtk_menu_bar_new();/*创建菜单条*/

       gtk_table_attach_defaults(GTK_TABLE(table),MenuBar,0,10,0,1);

       MenuItemFile=CreateMenuItem(MenuBar,"File");/*调用创建菜单项函数*/

       CreateMenuFile(MenuItemFile);/*调用创建子菜单函数*/

       MenuItemShutDown=CreateMenuItem(MenuBar,"ShutDown");

       CreateMenuShutDown(MenuItemShutDown);/*调用创建子菜单函数*/

       MenuItemHelp=CreateMenuItem(MenuBar,"Help");

       CreateMenuHelp(MenuItemHelp);/*调用创建子菜单函数*/

       gtk_widget_show(MenuBar);

 

       status_bar = gtk_statusbar_new ();   /*创建状态栏*/  

           gtk_table_attach_defaults(GTK_TABLE(table),status_bar,0,10,11,12);//将状态栏装进表格

           gtk_widget_show (status_bar);  /*显示状态栏*/

 

 

       process_label=gtk_label_new("");//创建显示进程数的标签

       sign=gtk_timeout_add(100,(GtkFunction)process_num,data);

       gtk_widget_show(process_label);//显示标签

       gtk_table_attach_defaults(GTK_TABLE(table),process_label,0,2,11,12);//在状态栏中显示进程总数

 

       cpu_rate_label=gtk_label_new(" ");//创建显示cpu占用率的标签

       sign=gtk_timeout_add(100,(GtkFunction)cpu_rate_ava,data);

       gtk_widget_show(cpu_rate_label);//显示标签

       gtk_table_attach_defaults(GTK_TABLE(table),cpu_rate_label,3,5,11,12);//在状态栏中显示cpu占用率

       //printf("/n%.2f",cpu_rate);

 

       mem_rate_label=gtk_label_new(" ");//创建显示内存占用率的标签

       sign=gtk_timeout_add(100,(GtkFunction)mem_rate,data);

       gtk_widget_show(mem_rate_label);//显示标签

       gtk_table_attach_defaults(GTK_TABLE(table),mem_rate_label,6,10,11,12);//在状态栏中显示内存占用率

        

       GtkWidget *wi;

       cpu_button_clicked(wi,data);//执行程序时默认显示cpu信息

 

       gtk_signal_connect(GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(delete_event),NULL);

       gtk_main();

}

 

GtkWidget *CreateMenuItem(GtkWidget *MenuBar,char *test){

       GtkWidget *MenuItem;

       MenuItem=gtk_menu_item_new_with_label(test);/*创建菜单项*/

       gtk_menu_shell_append(GTK_MENU_SHELL(MenuBar),MenuItem);/*把菜单项加入菜单条*/

       gtk_widget_show(MenuItem);

       return MenuItem;

}

 

GtkWidget *CreateMenuFile(GtkWidget *MenuItem){

       GtkWidget *Menu;/*定义子菜单*/

       GtkWidget *Exit;

       Menu=gtk_menu_new();/*创建子菜单*/

       Exit=CreateMenuItem(Menu,"Exit");/*调用创建菜单项函数*/

       gtk_signal_connect(GTK_OBJECT(Exit),"activate",GTK_SIGNAL_FUNC(delete_event),NULL);

       gtk_menu_item_set_submenu(GTK_MENU_ITEM(MenuItem),Menu);/*把父菜单项于子菜单联系起来*/

       gtk_widget_show(Menu);

}

 

GtkWidget *CreateMenuShutDown(GtkWidget *MenuItem){

       GtkWidget *Menu;/*定义子菜单*/

       GtkWidget *Restart,*ShutDown;

       Menu=gtk_menu_new();/*创建子菜单*/

       ShutDown=CreateMenuItem(Menu,"ShutDown");/*调用创建菜单项函数*/

       Restart=CreateMenuItem(Menu,"Restart");

       gtk_signal_connect(GTK_OBJECT(Restart),"activate",GTK_SIGNAL_FUNC(restart),NULL);

       gtk_signal_connect(GTK_OBJECT(ShutDown),"activate",GTK_SIGNAL_FUNC(shutdown),NULL);

       gtk_menu_item_set_submenu(GTK_MENU_ITEM(MenuItem),Menu);/*把父菜单项于子菜单联系起来*/

       gtk_widget_show(Menu);

}

GtkWidget *CreateMenuHelp(GtkWidget *MenuItem){

       GtkWidget *Menu;/*定义子菜单*/

       GtkWidget *AboutGtk;

       Menu=gtk_menu_new();/*创建子菜单*/

       AboutGtk=CreateMenuItem(Menu,"AboutGtk");/*调用创建菜单项函数*/

       gtk_signal_connect(GTK_OBJECT(AboutGtk),"activate",GTK_SIGNAL_FUNC(aboutgtk),NULL);

       gtk_menu_item_set_submenu(GTK_MENU_ITEM(MenuItem),Menu);/*把父菜单项于子菜单联系起来*/

       gtk_widget_show(Menu);

}

gint sys_time(void){//显示系统时间

       time_t timep;

       struct tm *p;

       char buf[20],temp[5];

       time(&timep);

       p=localtime(&timep); /*取得当地时间*/

       sprintf(buf,"%d",p->tm_hour);

       sprintf(temp,"%d",p->tm_min);

       strcat(buf,":");

       strcat(buf,temp);

       sprintf(temp,"%d",p->tm_sec);

       strcat(buf,":");

       strcat(buf,temp);

       gtk_label_set_text(GTK_LABEL(time_label),buf);

       return 1;

}

//实时显示cpu占用率

gint cpu_rate_ava(void){//计算从系统启动到现在cpu的利用率

       char buffer[1024*5];

       char *match;

       FILE *fp;

       size_t bytes;

       char show[5];

       float cpu_rate;

       char text_cpu[14]="CPU : ";

       //GtkWidget *cpu_rate_label;

       int user,nice,system,idle;

          fp = fopen("/proc/stat","r");

          if (fp == 0){

            printf("open /proc/stat file error/n");

            return 0;

        }

 

       bytes = fread(buffer, 1, sizeof(buffer),fp);

 

       fclose(fp);

       if (bytes == 0 || bytes == sizeof(buffer)){

       printf("readBytes NULL OR large than buffer /n");

       return 0;

       }

       buffer[bytes] = '/0';

 

       match = strstr (buffer, "cpu");

       if (match == NULL){

       printf("match error/n");

       return 0;

       }

 

        sscanf (match ,"cpu %d %d %d %d", &user, &nice, &system, &idle);

       cpu_rate=100*(user+nice+system)/(float)(user+nice+system+idle);

        //printf( "user :%d nice: %d sys: %d idle %d cpu_rate: %.2f%%/n",user, nice, system, idle,cpu_rate);

 

       sprintf(show,"%.2f",cpu_rate);

       strcat(text_cpu,show);

       strcat(text_cpu,"%");

        

       gtk_label_set_text(GTK_LABEL(cpu_rate_label),text_cpu);

 

       return 1;

}

//实时显示内存占用率

gint mem_rate(void){//计算内存使用率

       int mem_fd;

       int MemFree,MemTotal,MemUsed,i=0,j=0;

       char buf[1000],buf1[1000]=" ",buf2[100]=" ",buf3[100]=" ",buf4[100]=" ",string[20];

       char *p;

       char Mem[100]=" ";

       mem_fd=open("/proc/meminfo",O_RDONLY);

       read(mem_fd,buf,1000);

       close(mem_fd);

       strcat(buf1,strtok(buf,"/n"));

       strcat(buf2,buf1);

 

       for(i=0;i<100&&buf2[i]!='/0';i++)

              if(buf2[i]>='0'&&buf2[i]<='9')buf3[j++]=buf2[i];

       buf3[j]='/0';

       MemTotal=atoi(buf3);

       strcat(buf1,strtok(NULL,"/n"));

       strcpy(buf2,buf1);

 

       j=0;

       for(;i<100&&buf2[i]!='/0';i++)

              if(buf2[i]>='0'&&buf2[i]<='9')buf4[j++]=buf2[i];

       buf4[j]='/0';

       MemFree=atoi(buf4);

       MemUsed=MemTotal-MemFree;

       //printf("MemUsed:%dkB/MemTotal:%dkB/n",MemUsed,MemTotal);

       MemTotal=MemTotal/1024;

       MemUsed=MemUsed/1024;

       strcpy(Mem,"Memory:");

       sprintf(string,"%d",MemUsed);//将整数转换成字符串

       strcat(Mem,string);

       strcat(Mem,"M/");

       sprintf(string,"%d",MemTotal);

       strcat(Mem,string);

       strcat(Mem,"M");

       gtk_label_set_text(GTK_LABEL(mem_rate_label),Mem);

 

       return 1;

}

//实时显示进程总数

gint process_num(void){

       DIR * dir;

       struct dirent * ptr;

       char show[5];

       int total=0;

       char text_value[100]="进程总数:";

              //统计进程总数

       dir =opendir("/proc");

       while((ptr = readdir(dir))!=NULL){

              if(select_name(ptr->d_name)){

              total++;

              }

       }

       sprintf(show,"%3d",total);

       strcat(text_value,show);

       closedir(dir);

 

       gtk_label_set_text(GTK_LABEL(process_label),text_value);

 

}

//显示cpu信息的按钮事件

void cpu_button_clicked(GtkWidget *widget,gpointer *data){

       int cpu_fd,i;

       char buf[1000],buf1[1000]=" ";

       char *p;

 

       pro_flag=0;

       mem_flag=0;

 

       cpu_fd=open("/proc/cpuinfo",O_RDONLY);

       read(cpu_fd,buf,1000);

       close(cpu_fd);

       strcat(buf1,strtok(buf,"/n"));

       while(p=strtok(NULL,"/n")){

              strcat(buf1,"/n ");

              strcat(buf1,p);

       }

       gtk_frame_set_label(GTK_FRAME(frame),"cpu version&run state");

       gtk_widget_hide(label1);

       length=gtk_text_get_length(GTK_TEXT(text));//获取当前文本的字符数

       gtk_text_backward_delete(GTK_TEXT(text),length);//从当前插入点向前删除length个字符

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf1,-1);//从当前插入点开始插入字符串,-1表示将整个字符串插入

}

//显示内存信息的回调函数

gint mem_timeout(void){

       int mem_fd;

       char buf[1000],buf1[1000]=" ";

       char *p;

       gint sign;

       gpointer gdata;

 

       if(!mem_flag)return 0;//退出回调函数

       mem_fd=open("/proc/meminfo",O_RDONLY);

       read(mem_fd,buf,1000);

       close(mem_fd);

       strcat(buf1,strtok(buf,"/n"));

       while(p=strtok(NULL,"/n")){

              strcat(buf1,"/n ");

              strcat(buf1,p);

       }

       gtk_frame_set_label(GTK_FRAME(frame),"memory state");

       gtk_widget_hide(label1);

       length=gtk_text_get_length(GTK_TEXT(text));

       gtk_text_backward_delete(GTK_TEXT(text),length);

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf1,600);

        

       return 1;

}

//点击内存按钮后的事件    

void mem_button_clicked(GtkWidget *widget,gpointer *data){

       gint sign;

       gpointer gdata;

       mem_flag=1;

       pro_flag=0;

       mem_timeout();

       //调用回调函数

       sign=gtk_timeout_add(1000,(GtkFunction)mem_timeout,gdata);

}

//显示进程信息的回调函数

gint pro_timeout(void){

       DIR * dir;

       struct dirent * ptr;

       int fdfrom;

       int total=0;

       int bytesread;

       char buffer[80];

       char text_value[100]="进程总数   ";

       char show[5];

       char buff[100]=" ";

       int i=0,j;

       char path_statm[30];

       char path_status[30];

 

       if(!pro_flag)return 0;

 

       dir =opendir("/proc");

       while((ptr = readdir(dir))!=NULL){

              if(select_name(ptr->d_name)){

              strcpy(pro[i].pro_id,ptr->d_name);

              i++;total++;

              }

       }

       //printf("%d/n",total);

       sprintf(show,"%3d",total);

       strcat(text_value,show);

       closedir(dir);

       gtk_frame_set_label(GTK_FRAME(frame),"process state");

 

       length=gtk_text_get_length(GTK_TEXT(text));

       gtk_text_backward_delete(GTK_TEXT(text),length);

       for(i=0;i

              strcpy(path_statm,"/proc/");

              strcpy(path_status,"/proc/");

              strcat (path_statm,pro[i].pro_id);

              strcat (path_statm,"/statm");

              strcat (path_status,pro[i].pro_id);

              strcat (path_status,"/status");

              fdfrom=open(path_status,O_RDONLY);//为了读取进程名

              bytesread=read(fdfrom,buffer,30);

              if(bytesread<=0)

              printf("read error!/n");

              strtok(buffer,": ");

              strcpy(pro[i].name,strtok(NULL,"/n"));

              close(fdfrom);

              fdfrom=open(path_statm,O_RDONLY);//为了读取进程占用内存大小

              bytesread=read(fdfrom,buffer,30);

              if(bytesread<=0)

              printf("read error!/n");

              strcat(pro[i].mem_take,strtok(buffer," "));

              strcat(pro[i].mem_take,"kb");

              close(fdfrom);

              strcat(buff,pro[i].name);

              for(j=strlen(pro[i].name);j<27;j++)//调整格式

                     strcat(buff," ");

              strcat(buff,pro[i].pro_id);

              for(j=strlen(pro[i].pro_id);j<16;j++)

                     strcat(buff," ");

              strcat(buff,pro[i].mem_take);

              strcat(buff,"/n");

 

              gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buff,-1);

              strcpy(pro[i].mem_take," ");

              strcpy(buff," ");

              }

       gtk_widget_show(label1);

       return 1;

}

//显示进程信息的按钮事件 

void pro_button_clicked(GtkWidget *widget,gpointer *data){

       gpointer gdata;

       pro_flag=1;

       mem_flag=0;

       pro_timeout();

       //调用进程信息的回调函数

       gtk_timeout_add(10000,(GtkFunction)pro_timeout,gdata);

 

}

//显示硬盘信息的按钮事件

void disk_button_clicked(GtkWidget *widget,gpointer *data){         

       int disk_fd,i;

       char buf[1000],buf1[1000]=" ";

       char *p;

 

       pro_flag=0;

       mem_flag=0;

 

       disk_fd=open("/proc/partitions",O_RDONLY);

       read(disk_fd,buf,1000);

       close(disk_fd);

       strcat(buf1,strtok(buf,"/n"));

       while(p=strtok(NULL,"/n")){

              strcat(buf1,"/n/n ");

              strcat(buf1,p);

       }

       gtk_frame_set_label(GTK_FRAME(frame),"disk information");

       gtk_widget_hide(label1);

       length=gtk_text_get_length(GTK_TEXT(text));

       gtk_text_backward_delete(GTK_TEXT(text),length);

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf1,-1);

}

//显示内核信息的按钮事件

void sys_button_clicked(GtkWidget *widget,gpointer *data){

       int sys_fd,i,hour,second,minute;

       char buf[2000]=" ",buf1[1000];

       char *p;

       char showm[20];

       int time_run;

       time_t timep;

       char *sys_info[]={"/proc/sys/kernel/hostname","/proc/version"};

 

       pro_flag=0;

       mem_flag=0;

 

       gtk_frame_set_label(GTK_FRAME(frame),"kernel version");

       gtk_widget_hide(label1);

       strcat(buf,"/n/n/n/nhostname : ");

       sys_fd=open(sys_info[0],O_RDONLY);

       read(sys_fd,buf1,1000);

       close(sys_fd);

       strcat(buf,strtok(buf1,"/n"));

       strcat(buf,"/n");

       strcat(buf,"/n/nkernel vertion : ");

       sys_fd=open(sys_info[1],O_RDONLY);

       read(sys_fd,buf1,1000);

       close(sys_fd);

       strcat(buf,strtok(buf1,"("));

       strcat(buf,"/n");

 

       length=gtk_text_get_length(GTK_TEXT(text));

       gtk_text_backward_delete(GTK_TEXT(text),length);

       gtk_text_insert(GTK_TEXT(text),NULL,NULL,NULL,buf,-1); 

}

 

c.程序运行结果:

 

1。整体框架

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2。状态栏

 

3

 

 

 

 

 

 

 

3。内存实时显示:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4。进程实时显示:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5。显示硬盘信息

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6。显示内核信息

 

                             

        

 

 

 

 

 

 

 

 

 

 

 

 

7。点击help显示有关gtk的信息

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(课程实验报告,gtk,table,signal,button,null,menu)