| 
		    
                    
   下面就开始写子程序.  
    
        
            | 
             #include <linux/types.h>  #include <linux/fs.h>  #include <linux/mm.h>  #include <linux/errno.h>  #include <asm/segment.h>  
            unsigned int test_major = 0;  
            static int read_test(struct inode *node, struct file *file, char *buf, int count)  {    int left;  
              if (verify_area(VERIFY_WRITE, buf, count) == -EFAULT )      return -EFAULT;  
              for(left = count ; left > 0 ; left--)    {      __put_user(1, buf, 1);      buf++;    }  
              return count;  } 
             | 
         
    
 
  这个函数是为read调用准备的.当调用read时,read_test()被调用,它把用户的缓冲区全部写1.buf 是read调用的一个参数.它是用户进程空间的一个地址.但是在read_test被调用时,系统进入核心态.所以不能使用buf这个地址,必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据.另外还有很多类似功能的函数.请参考.在向用户空间拷贝数据之前,必须验证buf是否可用。   这就用到函数verify_area.  
    
        
            | 
             static int write_tibet(struct inode *inode, struct file *file, const char *buf, int count)  {    return count;  }  
            static int open_tibet(struct inode *inode, struct file *file )  {    MOD_INC_USE_COUNT;    return 0;  }  
            static void release_tibet(struct inode *inode, struct file *file )  {    MOD_DEC_USE_COUNT;  } 
  
             | 
         
    
 
  这几个函数都是空操作.实际调用发生时什么也不做,他们仅仅为下面的结构提供函数指针。  
    
        
            struct file_operations test_fops =  {    NULL,    read_test,    write_test,    NULL, /* test_readdir */    NULL,    NULL, /* test_ioctl */    NULL, /* test_mmap */    open_test,    release_test, NULL, /* test_fsync */    NULL, /* test_fasync */    /* nothing more, fill with NULLs */  };  | 
         
    
 
  设备驱动程序的主体可以说是写好了。现在要把驱动程序嵌入内核。驱动程序可以按照两种方式编译。一种是编译进kernel,另一种是编译成模块(modules),如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。  
    
        
            | 
             int init_module(void)  {    int result;  
              result = register_chrdev(0, "test", &test_fops);  
              if (result < 0)    {      printk(KERN_INFO "test: can't get major number\n");      return result;    }  
              if (test_major == 0) test_major = result; /* dynamic */      return 0;  }  
             | 
         
    
 
		    
                       
		      
		      
		   |