2006年03月31日

又看了个电影:《百慕大》,悬念是渲染得够味了,可给我更多的感觉却是胡扯,当茶余饭后的谈资却是不错。

2006年03月05日

Linux课程设计已经过去了,不过组成原理的就快来了,但是我还是想抽点时间来学习C++,废话少说,现在就开始吧。

2006年03月03日

今天课程设计检查,结果很是令我满意,虽然没有按照预定的忙上两个星期,但这段时间还是很辛苦的。现在可以放下一个阶段了,也该准备下个星期的组成原理课程设计了。组成课设可要抓紧时间认真对待了,不能像这次这样糊里糊涂了!哈哈,准备迎接下一个好心情了!

此文叙述了增加copy系统功能调用(本次实验同时做了p,v操作的系统功能调用,但我的那个程序的原创部分太少,不便贴出)的方法,在2.4.22内核下编译通过。可以任意使用,主要有以下几个步骤:

1,在/usr/src/linux-2.4.22/kernel/sys.c的最后添加:

asmlinkage void sys_mycopy(char * infile,char * outfile)
{
 int infiled,outfiled,count;
 char buf[256];
 mm_segment_t fs; //堆栈保护
 fs=get_fs();
 set_fs(get_ds());
 infiled=sys_open(infile,O_RDONLY,0);
 if(infiled== -1)
  printk("Opening InFile Failed !\n");
 outfiled=sys_open(outfile,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR);
 if(outfiled== -1)
  printk("Open or Creat OutFile Failed !\n");

 while((count=sys_read(infiled,buf,256))>0)
  if(sys_write(outfiled,buf,count)!=count)
   printk("Writing Failed !\n");
  if(count==-1)
   printk("Reading Failed !\n");
  sys_close(infiled);
  sys_close(outfiled);
  set_fs(fs);
}

2

/usr/include/asm/unistd.h/usr/src/linux-2.4.22/include/asm-i386/unistd.h两个unistd.h文件中添加:

#define __NR_mycopy  235

注意:末尾的号是可以修改的,但最好不要超过255,若相同的号已经被使用可以将原来的替换掉(加上注释)。

 3,在/usr/src/linux-2.4.22/arch/i386/kernel/entry.s文件中添加:

.long SYMBOL_NAME(sys_mycopy)

注意:若此文件的最后一项的有关数据是根据表长而定的则不必修改,否则修改,使其值加1(因为增加了一个系统功能)。

4,依次执行:make mrproper (若是第一次编译,此命令跳过),make xconfig ( 修改File Systems表项,将其中有关ext3文件格式都选择为 Y,根据你的CPU型号修改CPU选项( 左面由上到下第三项)等等,例如有的需要修改对usb的支持,请看各项的帮助信息),make dep,make clean ,make bzImage(若此步没有错误则基本成功),make modules ,make modules_install ,make install 。

5,修改boot/grub/grub.conf中的内容,将表下相关系统(本系统为2.4.22一行末尾)的=LABL=/改为表前几行中的硬盘号(如=/dev/hda8),重新启动系统,进入刚刚编译成的内核。

6,编写测试程序:

源码:

//testcopy.c

#include<linux/unistd.h>
_syscall2(int,mycopy,char *, infile,char * ,outfile)
int errno;
int main(int argc,char * argv[])
{
 mycopy(argv[1],argv[2]);
 return 0;
}
编译:gcc testcopy.c -o testcopy

运行:./testcopy

.long SYMBOL_NAME(sys_mycopy)

注意:若此文件的最后一项的有关数据是根据表长而定的则不必修改,否则修改,使其值加1(因为增加了一个系统功能)。

4,依次执行:make mrproper (若是第一次编译,此命令跳过),make xconfig ( 修改File Systems表项,将其中有关ext3文件格式都选择为 Y,根据你的CPU型号修改CPU选项( 左面由上到下第三项)等等,例如有的需要修改对usb的支持,请看各项的帮助信息),make dep,make clean ,make bzImage(若此步没有错误则基本成功),make modules ,make modules_install ,make install 。

5,修改boot/grub/grub.conf中的内容,将表下相关系统(本系统为2.4.22一行末尾)的=LABL=/改为表前几行中的硬盘号(如=/dev/hda8),重新启动系统,进入刚刚编译成的内核。

6,编写测试程序:

源码:

//testcopy.c

#include<linux/unistd.h>
_syscall2(int,mycopy,char *, infile,char * ,outfile)
int errno;
int main(int argc,char * argv[])
{
 mycopy(argv[1],argv[2]);
 return 0;
}
编译:gcc testcopy.c -o testcopy

运行:./testcopy

在redhat2.4.20-8下编译通过:

由于本程序窗口部分由glad工具编制,源代码不易贴出,现只给出部分回调函数的代码:

1,“退出”按钮回调函数:

void
on_button9_clicked                     (GtkButton       *button,
                                        gpointer         user_data)
{
 gtk_main_quit();
}

2,“关机”按钮回调函数:

void
on_button10_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
 system("halt");
}

3,“重新启动”按钮回调函数:

void
on_button11_clicked                    (GtkButton       *button,
                                        gpointer         user_data)
{
 system("reboot");
}

4,“主机名”字符块回调函数:

void
on_label38_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 FILE * fp;
 char buf[256];
 fp=fopen("/proc/sys/kernel/hostname","r");
 fgets(buf,256,fp);
 fclose(fp);
 gtk_label_set_text(widget,buf);
}

5,“CPU型号”字符块回调函数:

void
on_label45_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 
 FILE * fp;
 int i,j=0;
 char buf[256],buf1[256];
   fp=fopen("/proc/cpuinfo","r");
 for(i=0;i<5;i++){
  fgets(buf,256,fp);
 }
 for(i=0;i<256;i++){
  if(buf[i]==’:') break;
 }
 i+=2;
 for(;i<256;i++){
  if(buf[i]==’ ‘) break;
 }
 i+=1;
 while(i<256){
  if(buf[i]==’ ‘){
   i++;
  }
  else{
   buf1[j]=buf[i];
   j++;
   i++;
  }
 }
 fclose(fp);
  gtk_label_set_text(widget,buf1);//cpu型号
}

6,“CPU主频”回调函数:

void
on_label46_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 
 FILE * fp;
 int i,j=0;
 char buf[256],buf1[256];
   fp=fopen("/proc/cpuinfo","r");
 for(i=0;i<7;i++){
  fgets(buf,256,fp);
 }
 for(i=0;i<256;i++){
  if(buf[i]==’:') break;
 }
 i+=2;
 j=0;
 for(;i<256;i++){
  if(buf[i]==’ ‘) break;
  else{
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\0′;
 fclose(fp);
  gtk_label_set_text(widget,buf1);//cpu型号
}

7,“系统版本号”回调函数:

void
on_label39_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 FILE * fp;
 char buf[256];
 fp=fopen("/proc/sys/kernel/osrelease","r");
 fgets(buf,256,fp);
 fclose(fp);
 gtk_label_set_text(widget,buf);
}

8,“系统运行时间”回调函数:

void timeout_label40 (GtkWidget *widget,gpointer user_data){

FILE * fp;
 int i,j;
 char buf[64],buf1[64];
 fp=fopen("/proc/uptime","r");
 fgets(buf,64,fp);
 j=0;
 for(i=0;i<64;i++){
  if(buf[i]==’ ‘) break;
  else {
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\0′;
 fclose(fp);
 
 gtk_label_set_text(widget,buf1);
}

void
on_label40_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 gtk_timeout_add(200,timeout_label40,widget);
}

9,“CPU运行时间”回调函数:

void timeout_label42 (GtkWidget *widget,gpointer user_data)
{
 
 FILE * fp;
 int i,j;
 char buf[64],buf1[64];
 fp=fopen("/proc/uptime","r");
 fgets(buf,64,fp);
 for(i=0;i<64;i++){
  if (buf[i]==’ ‘) break;
 }
 i++;
 j=0;
 for(;i<64;i++){
  if(buf[i]==’ ‘) break;
  else {
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\\’;
 buf1[j+1]=’0′;
 fclose(fp);
 gtk_label_set_text(widget,buf1);
}

void
on_label42_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 gtk_timeout_add(200,timeout_label42,widget);
}

10,“内存信息”回调函数:

void
on_label51_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 FILE * fp;
 int i,j;
 char buf[256],buf1[256];
 fp=fopen("/proc/meminfo","r");
 fgets(buf,256,fp);
 fgets(buf,256,fp);
 for(i=0;i<256;i++){
  if (buf[i]==’:') break;
 }
 i++;
 for(;i<256;i++){
  if (buf[i]!=’ ‘) break;
 }
 j=0;
 for(;i<256;i++){
  if(buf[i]==’ ‘) break;
  else {
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\0′;
 fclose(fp);
 gtk_label_set_text(widget,buf1);
}

11,“SWAP信息”回调函数:

void
on_label53_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 FILE * fp;
 int i,j;
 char buf[256],buf1[256];
 fp=fopen("/proc/meminfo","r");
 fgets(buf,256,fp);
 fgets(buf,256,fp);
 fgets(buf,256,fp);
 for(i=0;i<256;i++){
  if (buf[i]==’:') break;
 }
 i++;
 for(;i<256;i++){
  if (buf[i]!=’ ‘) break;
 }
 j=0;
 for(;i<256;i++){
  if(buf[i]==’ ‘) break;
  else {
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\0′;
 fclose(fp);
 gtk_label_set_text(widget,buf1);
}

12,“内存使用信息”回调函数:

void timeout_label52 (GtkWidget  *widget,gpointer user_data)
{
 FILE * fp;
 int i,j;
 char buf[256],buf1[256];
 fp=fopen("/proc/meminfo","r");
 fgets(buf,256,fp);
 fgets(buf,256,fp);
 for(i=0;i<256;i++){
  if (buf[i]==’:') break;
 }
 i++;
 for(;i<256;i++){
  if (buf[i]!=’ ‘) break;
 }
 for(;i<256;i++){
  if (buf[i]==’ ‘) break;
 }
 for(;i<256;i++){
  if (buf[i]!=’ ‘) break;
 }
 j=0;
 for(;i<256;i++){
  if(buf[i]==’ ‘) break;
  else {
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\0′;
 fclose(fp);
 gtk_label_set_text(widget,buf1);
}
void
on_label52_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 gtk_timeout_add(200,timeout_label52,widget);
}

13,“SWAT使用信息”回调函数:

void timeout_label54 (GtkWidget *widget, gpointer user_data)
{
 FILE * fp;
 int i,j;
 char buf[256],buf1[256];
 fp=fopen("/proc/meminfo","r");
 fgets(buf,256,fp);
 fgets(buf,256,fp);
 fgets(buf,256,fp);
 for(i=0;i<256;i++){
  if (buf[i]==’:') break;
 }
 i++;
 for(;i<256;i++){
  if (buf[i]!=’ ‘) break;
 }
 for(;i<256;i++){
  if (buf[i]==’ ‘) break;
 }
 for(;i<256;i++){
  if (buf[i]!=’ ‘) break;
 }
 j=0;
 for(;i<256;i++){
  if(buf[i]==’ ‘) break;
  else {
   buf1[j]=buf[i];
   j++;
  }
 }
 buf1[j]=’\0′;
 fclose(fp);
 gtk_label_set_text(widget,buf1);
}

void
on_label54_realize                     (GtkWidget       *widget,
                                        gpointer         user_data)
{
 gtk_timeout_add(200,timeout_label54,widget);
}

14,“进程显示”函数(此函数写在main.c中):

void procc_see(GtkWidget * window)
{
  GtkWidget *widget,*view;
  GtkTextBuffer * buffer;
  FILE *fp;
  GtkTextIter p;
  int i;
  char *buf=malloc(2048*sizeof(char));

  fp=popen("ps -l -x","r");
  /*for(i=0;i<12288;i++)
  {
    fscanf(fp,"%c",&buf[i]);
    if(buf[i]==’\0′)break;
  }
  view = lookup_widget(window,"textview1");
  buffer=gtk_text_buffer_new(NULL);
  gtk_text_view_set_buffer(GTK_TEXT_VIEW(view), buffer);
  gtk_text_buffer_set_text(buffer,buf,-1);*/

  widget=lookup_widget(window,"textview1");
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
  buffer = gtk_text_buffer_new(gtk_text_buffer_get_tag_table(buffer));
  gtk_text_view_set_buffer(GTK_TEXT_VIEW(widget), buffer);
  g_object_unref(G_OBJECT(buffer));
  gtk_text_buffer_get_end_iter(buffer, &p);
  while((i = fread(buf, 1, sizeof(buf), fp)) > 0) {
 GError *err = NULL;
 gsize br, bw;
 gchar *text;
 if(!(text = g_locale_to_utf8(buf, i, &br, &bw, &err))) {
     g_printerr("Failed locale to UTF-8 conversion: %s\n", err->message);
     g_clear_error(&err);
     break;
 }
 gtk_text_buffer_insert(buffer, &p, text, bw);
 g_free(text);
    }
  pclose(fp);
}

15,“查看系统类型”回调函数:和前面“查看系统版本”的回调函数是一样的,只不过要用到的文件不同。

不做赘述。

最后,用命令:./autogen.sh和make install 编译。

说明:此进程管理器实现的功能较少,不过,用此模式编写的程序很容易扩充,主要是回调函数的编写,相关内容请查看有关书籍或Google!

虚拟一个简单的字符设备驱动,在Red Hat2.4.20-8下通过:(该程序采用转自网络的代码修改而成,详细情况请查看http://bbs.whnet.edu.cn/main.html :Linux版块 —–>精华区—–> 编程解疑—–> linux课设总结之字符设备驱动)

1,编写源文件:

#define  __NO_VERSION__ 
#include<linux/version.h> /*以下是本程序包含的头文件*/
#include<linux/module.h>
#include<linux/config.h>
#include<asm/uaccess.h>
#include<linux/types.h>
#include<linux/fs.h> 
#include<linux/mm.h>
#include<linux/errno.h>
#include<asm/segment.h>
#define BUFSIZE 256  /*设备中包含的最大字符数*/

char * temp;  /*该指针用于为这个虚拟的设备分配内存空间*/
unsigned int major = 0;
static ssize_t device_read(struct file * file,char * buf,size_t count,loff_t * f_pos)
{
 int i;
 if(count>BUFSIZE){  /*如果要求读出的数目多于设备固有的数目则提示并返回*/
 printk("Can’t Read , the Count is to Big !\n");
 return  -EFAULT;
 }
 for(i = 0;i < count;i++)  /*否则,进行读出操作*/
  {__put_user(temp[i],buf);
         buf++;
        }    
 return count;
}

static ssize_t device_write(struct file * file,const char * buf,size_t count,loff_t * f_pos)
{
 int i;
 if(count>BUFSIZE){  /*要求写入的数目比设备的容量大则提示并返回*/
 printk("Can’t Write , the Count is to Big\n");  
 return  -EFAULT;
 }
 for(i = 0;i < count;i++)  /*否则,进行写入操作*/
  {__get_user(temp[i],buf);
         buf++;
        }    
 return count;
}

static int device_open(struct inode * inode,struct file * file) /*打开设备函数*/
{
 temp = (char *)kmalloc(BUFSIZE,GFP_KERNEL);  /*为设备分配内存空间*/
 MOD_INC_USE_COUNT;
 return 0;
}

static int device_release(struct inode * inode,struct file * file)
{
 kfree(temp);   /*释放设备占用内存空间*/
 MOD_DEC_USE_COUNT;
 return 0;
}

struct file_operations fops = { /*填充file_operations结构*/
 read:device_read,
        write:device_write,
        open:device_open,
        release:device_release
};
   
int init_module(void)  /*登记设备函数,insmod时调用*/
{
 int num;
 num = register_chrdev(0,"mydriver",&fops); /*系统自动返回一个未被占用的设备号*/
 if(num < 0){     /*登记未成功,提示并返回*/
  printk("Can’t Got the Major Number !\n");
    return num;
 }
 if(major == 0)
 major = num;
 return 0;
}

void cleanup_module(void)  /*释放设备函数,rmmod时调用*/
{
 unregister_chrdev(major,"mydriver");
}

命名为"mydriver.c"

2,编译文件:

gcc -O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -I/usr/src/linux-2.4.20-8/include -c mydriver.c

3,装载驱动:

insmod -f mydriver.o

用:lsmod可以看到mydriver.o

用:cat /proc/mydevice查看该设备的主设备号,在我的系统上为254

4,创建设备文件:mknod /dev/myDriver c 254 0 (其中myDriver为文件名,注意和下面的测试程序中打开的文件名一致,c代表此为字符设备,254位主设备号,0为从设备号,一般为0)
5,编译测试程序:test.c

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(void)
{
 int fd;
 int i;
  char *buf="1234567890abcdefghij\n";
  char buf1[22];
 
 fd = open("/dev/myDriver",O_RDWR); /*此处myDriver和建立设备文件时的名称一致*/
 if (fd == -1)
 {
  printf("Can’t open file \n");
  exit(-1);
 }   
 write(fd,buf,22);
 read(fd,buf1,22);
 for(i=0;i<22;i++)
    printf("%c",buf1[i]);
 close(fd);
 return 0;
}

编译并运行:gcc test.c -o test

                       ./test

注:以上只声明了增加驱动程序的步骤和给出了源代码 ,详细情况请见文首的链接。

:

编写一函数,实现文件的拷贝功能,此函数参数为命令行输入的两个文件名,在Red Hat2.4.20-8下实现:

#include<fcntl.h>
#include<sys/stat.h>
#define BUFSIZE 255 
int main(int argc, char * argv[])
{
 char buf[BUFSIZE];
 int infiled,outfiled,count;
 
 infiled=open(argv[1],O_RDONLY);
 if(infiled==-1){ 
  printf("Opening infile failed!\n");
 }
 outfiled=open(argv[2],(O_WRONLY | O_CREAT | O_TRUNC),(S_IRUSR | S_IWUSR | S_IXUSR));
 if(outfiled==-1){
  printf("Opening outfile failed!\n");
 }
 else{
  while((count=read(infiled,buf,sizeof(buf)))>0){
   if(write(outfiled,buf,count)!=count)
    printf("Writing data failed!\n");
  }
 }
 if(count==-1)
  printf("Reading data failed!\n");
 close(infiled);
 close(outfiled);
}