| 
 | 
 
 本帖最后由 huang301 于 2012-3-3 18:39 编辑  
 
main.c 
#include <linux/module.h> 
#include <linux/types.h> 
#include <linux/fs.h> 
#include <linux/errno.h> 
#include <linux/mm.h> 
#include <linux/sched.h> 
#include <linux/init.h> 
#include <linux/cdev.h> 
#include <asm/io.h> 
#include <asm/system.h> 
#include <asm/uaccess.h> 
 
#include "memdev.h" 
 
static int mem_major = MEMDEV_MAJOR; 
 
module_param(mem_major, int, S_IRUGO); 
 
struct mem_dev *mem_devp; /*设备结构体指针*/ 
 
struct cdev cdev;  
 
/*文件打开函数*/ 
int mem_open(struct inode *inode, struct file *filp) 
{ 
    struct mem_dev *dev; 
     
    /*获取次设备号*/ 
    int num = MINOR(inode->i_rdev); 
 
    if (num >= MEMDEV_NR_DEVS)  
            return -ENODEV; 
    dev = &mem_devp[num]; 
     
    /*将设备描述结构指针赋值给文件私有数据指针*/ 
    filp->private_data = dev; 
     
    return 0;  
} 
 
/*文件释放函数*/ 
int mem_release(struct inode *inode, struct file *filp) 
{ 
  return 0; 
} 
 
/*IO操作*/ 
int memdev_ioctl(struct inode *inode, struct file *filp, 
                 unsigned int cmd, unsigned long arg) 
{ 
 
    int err = 0; 
    int ret = 0; 
    int ioarg = 0; 
     
    /* 检测命令的有效性 */ 
    if (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC)  
        return -EINVAL; 
    if (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR)  
        return -EINVAL; 
 
    /* 根据命令类型,检测参数空间是否可以访问 */ 
    if (_IOC_DIR(cmd) & _IOC_READ) 
        err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); 
    else if (_IOC_DIR(cmd) & _IOC_WRITE) 
        err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); 
    if (err)  
        return -EFAULT; 
 
    /* 根据命令,执行相应的操作 */ 
    switch(cmd) { 
 
      /* 打印当前设备信息 */ 
      case MEMDEV_IOCPRINT: 
              printk("<--- CMD MEMDEV_IOCPRINT Done--->\n\n"); 
        break; 
       
      /* 获取参数 */ 
      case MEMDEV_IOCGETDATA:  
        ioarg = 1101; 
        ret = __put_user(ioarg, (int *)arg); 
        break; 
       
      /* 设置参数 */ 
      case MEMDEV_IOCSETDATA:  
        ret = __get_user(ioarg, (int *)arg); 
        printk("<--- In Kernel MEMDEV_IOCSETDATA ioarg = %d --->\n\n",ioarg); 
        break; 
 
      default:   
        return -EINVAL; 
    } 
    return ret; 
 
} 
 
/*文件操作结构体*/ 
static const struct file_operations mem_fops = 
{ 
  .owner = THIS_MODULE, 
  .open = mem_open, 
  .release = mem_release, 
  .ioctl = memdev_ioctl, 
}; 
 
/*设备驱动模块加载函数*/ 
static int memdev_init(void) 
{ 
  int result; 
  int i; 
 
  dev_t devno = MKDEV(mem_major, 0); 
 
  /* 静态申请设备号*/ 
  if (mem_major) 
    result = register_chrdev_region(devno, 2, "memdev"); 
  else  /* 动态分配设备号 */ 
  { 
    result = alloc_chrdev_region(&devno, 0, 2, "memdev"); 
    mem_major = MAJOR(devno); 
  }   
   
  if (result < 0) 
    return result; 
 
  /*初始化cdev结构*/ 
  cdev_init(&cdev, &mem_fops); 
  cdev.owner = THIS_MODULE; 
  cdev.ops = &mem_fops; 
   
  /* 注册字符设备 */ 
  cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS); 
    
  /* 为设备描述结构分配内存*/ 
  mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL); 
  if (!mem_devp)    /*申请失败*/ 
  { 
    result =  - ENOMEM; 
    goto fail_malloc; 
  } 
  memset(mem_devp, 0, sizeof(struct mem_dev)); 
   
  /*为设备分配内存*/ 
  for (i=0; i < MEMDEV_NR_DEVS; i++)  
  { 
        mem_devp.size = MEMDEV_SIZE; 
        mem_devp.data = kmalloc(MEMDEV_SIZE, GFP_KERNEL); 
        memset(mem_devp.data, 0, MEMDEV_SIZE); 
  } 
     
  return 0; 
 
  fail_malloc:  
  unregister_chrdev_region(devno, 1); 
   
  return result; 
} 
 
/*模块卸载函数*/ 
static void memdev_exit(void) 
{ 
  cdev_del(&cdev);   /*注销设备*/ 
  kfree(mem_devp);     /*释放设备结构体内存*/ 
  unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*释放设备号*/ 
} 
 
MODULE_AUTHOR("KPBoy huang"); 
MODULE_LICENSE("GPL"); 
 
module_init(memdev_init); 
module_exit(memdev_exit); 
 
 
 
memdev.h 
#ifndef _MEMDEV_H_ 
#define _MEMDEV_H_ 
 
#include <linux/ioctl.h> 
 
#ifndef MEMDEV_MAJOR 
#define MEMDEV_MAJOR 0   /*预设的mem的主设备号*/ 
#endif 
 
#ifndef MEMDEV_NR_DEVS 
#define MEMDEV_NR_DEVS 2    /*设备数*/ 
#endif 
 
#ifndef MEMDEV_SIZE 
#define MEMDEV_SIZE 4096 
#endif 
 
/*mem设备描述结构体*/ 
struct mem_dev                                      
{                                                         
  char *data;                       
  unsigned long size;        
}; 
 
/* 定义幻数 */ 
#define MEMDEV_IOC_MAGIC  'k' 
 
/* 定义命令 */ 
#define MEMDEV_IOCPRINT   _IO(MEMDEV_IOC_MAGIC, 1) 
#define MEMDEV_IOCGETDATA _IOR(MEMDEV_IOC_MAGIC, 2, int) 
#define MEMDEV_IOCSETDATA _IOW(MEMDEV_IOC_MAGIC, 3, int) 
 
#define MEMDEV_IOC_MAXNR 3 
 
#endif /* _MEMDEV_H_ */ 
应用程序app-ioctl.c 
#include <stdio.h> 
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 
 
#include "memdev.h"  /* 包含命令定义 */ 
 
int main() 
{ 
        int fd = 0; 
        int cmd; 
        int arg = 0; 
        char Buf[4096]; 
         
         
        /*打开设备文件*/ 
        fd = open("/dev/memdev0",O_RDWR); 
        if (fd < 0) 
        { 
                printf("Open Dev Mem0 Error!\n"); 
                return -1; 
        } 
         
        /* 调用命令MEMDEV_IOCPRINT */ 
        printf("<--- Call MEMDEV_IOCPRINT --->\n"); 
        cmd = MEMDEV_IOCPRINT; 
        if(ioctl(fd,cmd,&arg)< 0) 
        { 
                printf("Call cmd MEMDEV_IOCPRINT fail\n"); 
                return -1; 
        } 
         
         
        /* 调用命令MEMDEV_IOCSETDATA */ 
        printf("<--- Call MEMDEV_IOCSETDATA --->\n"); 
        cmd = MEMDEV_IOCSETDATA; 
        arg = 2007; 
        if (ioctl(fd, cmd, &arg) < 0) 
        { 
                printf("Call cmd MEMDEV_IOCSETDATA fail\n"); 
                return -1; 
        } 
 
         
        /* 调用命令MEMDEV_IOCGETDATA */ 
        printf("<--- Call MEMDEV_IOCGETDATA --->\n"); 
        cmd = MEMDEV_IOCGETDATA; 
        if (ioctl(fd, cmd, &arg) < 0) 
        { 
                printf("Call cmd MEMDEV_IOCGETDATA fail\n"); 
                return -1; 
        } 
        printf("<--- In User Space MEMDEV_IOCGETDATA Get Data is %d --->\n\n",arg);         
         
        close(fd); 
        return 0;         
} 
 
安照程序分析应该是: 
<--- Call MEMDEV_IOCPRINT ---> 
<---CMD MEMDEV_IOCPRINT Done---> 
<--- Call MEMDEV_IOCSETDATA ---> 
<----In Kernel MEMDEV_IOCSETDATA ioarg = 2007---> 
<--- Call MEMDEV_IOCGETDATA ---> 
<--- In User Space MEMDEV_IOCGETDATA Get Data is 1101 --->   
 
 
实际执行的结果却是,请问大家这是什么原因啊 
[root@EmbedSky /]# ./app-ioctl  
<--- Call MEMDEV_IOCPRINT ---> 
<---CMD MEMDEV_IOCPRINT Done---> 
 
<----In Kernel MEMDEV_IOCSETDATA ioarg = 2007---> 
 
<--- Call MEMDEV_IOCSETDATA ---> 
<--- Call MEMDEV_IOCGETDATA ---> 
<--- In User Space MEMDEV_IOCGETDATA Get Data is 1101 --->                                           |   
 
 
 
 |