| 
			
		 | 
		
			
				
					
	
		
			
 			Posted on 2008-02-10 18:53  ZelluX 阅读(930)  评论(0)  编辑  收藏  所属分类:  Linux 、 System 
			 
			
		 
		/proc文件系统不是直接从内核的存储区中读写数据,二是通过回调函数实现文件读写的。struct proc_dir_entry有一对读写操作函数指针read_proc_t, write_proc_t。 
一个编写内核模块操作proc文件系统的例子,书上的源程序是在2.4.18下跑起来的,改了三个地方在2.6.23下成功运行。当然Makefile也按照2.6中make modules的方式写了。
 
1. 去掉MODULE_VERSION宏的定义,和头文件冲突。 
2. 去掉MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT,2.6中的改变
 Preventing premature unloading 
In 2.4 modules, the MOD_INC_USE_COUNT macro is used to prevent unloading of the module while there is an open file. The 2.6 kernel, however, knows not to unload a module that owns a character device that's currently open.  
However, this requires that the module be explicit in specifying ownership of character devices, using the THIS_MODULE macro. You also have to take out all calls to MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT.  
The 2.6 kernel considers modules that use the deprecated facility to be unsafe, and does not permit their unloading, even with rmmod -f.  
3. 去掉proc_mknod增加一个tty设备文件那部分代码,2.6中去掉了这个函数,貌似要用udev代替,以后再看了。
 
修改后代码:
    
 #include <linux/module.h> 
 #include <linux/kernel.h> 
 #include <linux/init.h> 
 #include <linux/proc_fs.h> 
 #include <linux/sched.h> 
 #include <asm/uaccess.h> 
  
 #define MODULE_NAME "proc_example" 
  
 #define FOOBAR_LEN 8 
  
  struct fb_data_t  { 
     char name[FOOBAR_LEN + 1]; 
     char value[FOOBAR_LEN + 1]; 
 }; 
  
 static struct proc_dir_entry *example_dir, *foo_file, 
         *bar_file, *jiffies_file, *tty_device, *symlink; 
  
 struct fb_data_t foo_data, bar_data; 
  
 static int proc_read_jiffies(char *page, char **start, 
         off_t off, int count, int *eof, void *data) 
   { 
     int len; 
     // MOD_INC_USE_COUNT; 
     len = sprintf(page, "jiffies = %ld\n", jiffies); 
     // MOD_DEC_USE_COUNT; 
     return len; 
 } 
  
 static int proc_read_foobar(char *page, char **start, 
         off_t off, int ocunt, int *eof, void *data) 
   { 
     int len; 
     struct fb_data_t *fb_data = (struct fb_data_t *) data; 
     // MOD_INC_USE_COUNT; 
     len = sprintf(page, "%s = '%s'\n", fb_data->name, fb_data->value); 
     // MOD_DEC_USE_COUNT; 
     return len; 
 } 
  
 static int proc_write_foobar(struct file *file, const char *buffer, 
         unsigned long count, void *data) 
   { 
     int len; 
     struct fb_data_t *fb_data = (struct fb_data_t *) data; 
     // MOD_INC_USE_COUNT; 
     if (count > FOOBAR_LEN) 
         len = FOOBAR_LEN; 
     else 
         len = count; 
  
      if (copy_from_user(fb_data->value, buffer, len))  { 
         // MOD_DEC_USE_COUNT; 
         return -EFAULT; 
     } 
  
     fb_data->value[len] = '\0'; 
     // MOD_DEC_USE_COUNT; 
     return len; 
 } 
  
 int init_module() 
   { 
     int rv = 0; 
  
      /**//* Create directory */ 
     example_dir = proc_mkdir(MODULE_NAME, NULL); 
      if (example_dir == NULL)  { 
         rv = -ENOMEM; 
         goto out; 
     } 
  
     example_dir->owner = THIS_MODULE; 
     jiffies_file = create_proc_read_entry("jiffies", 0444, 
             example_dir, proc_read_jiffies, NULL); 
  
      if (jiffies_file == NULL)  { 
         rv = -ENOMEM; 
         goto no_jiffies; 
     } 
  
     jiffies_file->owner = THIS_MODULE; 
  
      /**//* Create regular files foo and bar */ 
     foo_file = create_proc_entry("foo", 0644, example_dir); 
      if (foo_file == NULL)  { 
         rv = -ENOMEM; 
         goto no_foo; 
     } 
  
     strcpy(foo_data.name, "foo"); 
     strcpy(foo_data.value, "foo"); 
     foo_file->data = &foo_data; 
     foo_file->read_proc = proc_read_foobar; 
     foo_file->write_proc = proc_write_foobar; 
     foo_file->owner = THIS_MODULE; 
  
     bar_file = create_proc_entry("bar", 0644, example_dir); 
      if (bar_file == NULL)  { 
         rv = -ENOMEM; 
         goto no_bar; 
     } 
  
     strcpy(bar_data.name, "bar"); 
     strcpy(bar_data.value, "bar"); 
     bar_file->data = &bar_data; 
     bar_file->read_proc = proc_read_foobar; 
     bar_file->write_proc = proc_write_foobar; 
     bar_file->owner = THIS_MODULE; 
  
      /**//* Create device file tty */ 
     // tty_device = proc_mknod("tty", S_IFCHR | 0666, example_dir, MKDEV(5,0)); 
     // if (tty_device == NULL) { 
     //     rv = -ENOMEM; 
     //     goto no_tty; 
     // } 
     // 
     // tty_device->owner = THIS_MODULE; 
  
      /**//* Create linkage file jiffies_too */ 
     symlink = proc_symlink("jiffies_too", example_dir, "jiffies"); 
  
      if (symlink == NULL)  { 
         rv = -ENOMEM; 
         goto no_symlink; 
     } 
  
     symlink->owner = THIS_MODULE; 
  
     printk(KERN_INFO "%s 1.0 initialized\n", MODULE_NAME); 
     return 0; 
  
 no_symlink: 
     remove_proc_entry("tty", example_dir); 
 // no_tty: 
 //     remove_proc_entry("bar", example_dir); 
 no_bar: 
     remove_proc_entry("foo", example_dir); 
 no_foo: 
     remove_proc_entry("jiffies", example_dir); 
 no_jiffies: 
     remove_proc_entry("MODULE_NAME", NULL); 
 out: 
     return rv; 
 } 
  
 void cleanup_module() 
   { 
     remove_proc_entry("jiffies_too", example_dir); 
 //  remove_proc_entry("tty", example_dir); 
     remove_proc_entry("bar", example_dir); 
     remove_proc_entry("foo", example_dir); 
     remove_proc_entry("jiffies", example_dir); 
     remove_proc_entry(MODULE_NAME, NULL); 
  
     printk(KERN_INFO "%s 1.0 removed\n", MODULE_NAME); 
 } 
  
 MODULE_DESCRIPTION("proc examples"); 
 EXPORT_NO_SYMBOLS; 
  
 
	 
	
	    
    
 
				
			 
		 |