+ -
当前位置:首页 → 问答吧 → 今天我終於找到組織了

今天我終於找到組織了

时间:2011-01-21

来源:互联网

RT
这代码我写挺久了,今天拿来测试不成功
当然以前写的时候测试是成功的,不过是在我同学的笔记本上编写和测试的
现在回到家是用家里的电脑测试,ubuntu是8.04的
谁帮我测试下有什么问题,谢谢了

mydev.c
代码:
/***************************************************************************
*   mydev.c
*    -------------------
*   版本号      : v1.0
*   原始作者   :  天使之翼
*   创建时间   : 2009-8-16
*   文件说明   : 设备驱动的处理程序
*   实现功能   : 设备驱动的加载,卸载,打开,释放,读写,控制,定位
*   修改列表   :
*   
***************************************************************************/


#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>

#define BUF_SIZE   0x1000      //缓冲区大小
#define CLEAR_BUF  0x1          //清空缓冲区
#define MYDEV_NAME "mydev"      //设备名
#define MYDEV_MAJOR  240      //主设备号

static int mydev_major = MYDEV_MAJOR;

//自定义的设备结构体
typedef struct mydev
{
   struct cdev cdev;
   unsigned char buf[BUF_SIZE];
}MYDEV;

MYDEV *p_mydev;


/***************************************************************************
功能:   打开设备
参数:   设备节点指针, 设备文件结构体指针
返回值:   0   成功
      非0  失败
***************************************************************************/
int mydev_open(struct inode *inode, struct file *filp)
{
   filp->private_data = p_mydev;  //将自定义设备结构体指针赋给文件私有数据指针
   return 0;
}



/***************************************************************************
功能:   释放设备
参数:   设备节点指针, 设备文件结构体指针
返回值:   0   成功
      非0  失败
***************************************************************************/
int mydev_release(struct inode *inode, struct file *filp)
{
   return 0;
}



/***************************************************************************
功能:   控制设备
参数:   设备节点指针, 设备文件结构体指针, 控制命令, 用户空间传递的自定义的数据
返回值:   0   成功
      非0  失败
***************************************************************************/
static int mydev_ioctl(struct inode *inode, struct file *filp,
                  unsigned int cmd, unsigned long arg)
{
   MYDEV *p_mydev = filp->private_data;

   switch(cmd)
   {
      case CLEAR_BUF:
         memset(p_mydev->buf, 0, BUF_SIZE);
         printk(KERN_INFO "buf is set to zero\n");
         break;
      
      default:
         return -EINVAL;
   }
   
   return 0;
}



/***************************************************************************
功能:   读设备
参数:   设备文件结构体指针, 用户空间传递的缓冲区指针, 读取的字节数, 当前读写位置
返回值:   读取的字节数  成功
      错误值       失败
***************************************************************************/
static ssize_t mydev_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
   unsigned long p = *ppos;
   unsigned int count = size;
   int ret = 0;
   MYDEV *p_mydev = filp->private_data;

   if(p >= BUF_SIZE)
   {
      return count ? -ENXIO : 0;
   }

   if(count > BUF_SIZE - p)
   {
      count = BUF_SIZE - p;
   }

   if(copy_to_user(buf, (void *)(p_mydev->buf + p), count))
   {
      ret = -EFAULT;
   }
   else
   {
      *ppos += count;
      ret = count;
      printk(KERN_INFO "read %d bytes(s) from %ld\n", count, p);
   }

   return ret;
}



/***************************************************************************
功能:   写设备
参数:   设备文件结构体指针, 用户空间传递的缓冲区指针, 写入的字节数, 当前读写位置
返回值:   写入的字节数  成功
      错误值       失败
***************************************************************************/
static ssize_t mydev_write(struct file *filp, const char __user *buf,
                     size_t size, loff_t *ppos)
{
   unsigned long p = *ppos;
   unsigned int count = size;
   int ret = 0;
   MYDEV *p_mydev = filp->private_data;

   if(p >= BUF_SIZE)
   {
      return count ? -ENXIO : 0;
   }

   if(count > BUF_SIZE - p)
   {
      count = BUF_SIZE - p;
   }

   if(copy_from_user(p_mydev->buf + p, buf, count))
   {
      ret = -EFAULT;
   }
   else
   {
      *ppos += count;
      ret = count;
      printk(KERN_INFO "written %d bytes(s) from %ld\n", count , p);
   }

   return ret;
}



/***************************************************************************
功能:   定位
参数:   设备文件结构体指针, 偏移量, 何处移动
返回值:   当前读写位置  成功
      错误值      失败
***************************************************************************/
static loff_t mydev_llseek(struct file *filp, loff_t offset, int whence)
{
   loff_t ret = 0;

   switch(whence)
   {
      case 0:
         if(offset < 0)
         {
            ret = -EINVAL;
            break;
         }
         
         if((unsigned int)offset > BUF_SIZE)
         {
            ret = -EINVAL;
            break;
         }

         filp->f_pos = (unsigned int)offset;
         ret = filp->f_pos;
         break;
      
      case 1:
         if((filp->f_pos + offset) > BUF_SIZE)
         {
            ret = -EINVAL;
            break;
         }

         if((filp->f_pos + offset) < 0)
         {
            ret = -EINVAL;
            break;
         }
         
         filp->f_pos += offset;
         ret = filp->f_pos;
         break;
   }

   return ret;
}


//文件操作结构体
static struct file_operations mydev_fops =
{
   .owner      = THIS_MODULE,
   .open       = mydev_open,
   .release    = mydev_release,
   .read       = mydev_read,
   .write      = mydev_write,
   .ioctl       = mydev_ioctl,
   .llseek      = mydev_llseek,
};



/***************************************************************************
功能:   初始化并注册cdev
参数:   自定义的设备结构体指针, 次设备号
返回值:   无
***************************************************************************/
static void mydev_setup_cdev(MYDEV *p_mydev, int index)
{
   dev_t devno;
   int errno;

   devno = MKDEV(mydev_major, index);
   cdev_init(&p_mydev->cdev, &mydev_fops);
   p_mydev->cdev.owner = THIS_MODULE;
   p_mydev->cdev.ops = &mydev_fops;
   
   errno = cdev_add(&p_mydev->cdev, devno, 1);  //注册cdev
   if(errno)
   {
      printk(KERN_INFO "Error %d adding LED %d\n", errno, index);
   }
}



/***************************************************************************
功能:   加载设备驱动模块
参数:   无
返回值:   0   成功
      非0  失败
***************************************************************************/
int mydev_init(void)
{
   int ret;
   dev_t devno;
   
   devno = MKDEV(mydev_major, 0);
   if(mydev_major)
   {
      ret = register_chrdev_region(devno, 1, MYDEV_NAME);  //申请设备号
   }
   else
   {
      ret = alloc_chrdev_region(&devno, 0, 1, MYDEV_NAME);  //动态申请设备号
      mydev_major = MAJOR(devno);
   }

   if(ret < 0)
   {
      return ret;
   }

   p_mydev = kmalloc(sizeof(MYDEV), GFP_KERNEL);
   if(!p_mydev)
   {
      ret = -ENOMEM;
      goto fail_malloc;
   }
   memset(p_mydev, 0, sizeof(MYDEV));
   
   mydev_setup_cdev(p_mydev, 0);
   return 0;

   fail_malloc:
   unregister_chrdev_region(devno, 1);
   return ret;
}



/***************************************************************************
功能:   卸载设备驱动模块
参数:   无
返回值:   无
***************************************************************************/
void mydev_exit(void)
{
   cdev_del(&p_mydev->cdev);  //注销cdev
   kfree(p_mydev);  //释放自定义设备结构体
   unregister_chrdev_region(MKDEV(mydev_major, 0), 1);  //释放设备号
}


module_init(mydev_init);
module_exit(mydev_exit);

MODULE_AUTHOR("Xie HoneYong");
MODULE_LICENSE("Dual BSD/GPL");


main.c
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

#define CLEAR_BUF  0x1  //清空缓冲区
#define DEVICE_FILENAME "/dev/mydev"

int main(void)
{
   int handle;
   char buf[128] = "Hello World!";

   handle = open(DEVICE_FILENAME, O_RDWR | O_NDELAY);
   printf("handle = %d\n", handle);
   if(handle < 0)
   {
      printf("open mydev device failure!\n");
   }
   else
   {
      printf("open mydev device successful!\n");
      printf("buf = %s\n", buf);
      write(handle, buf, sizeof(buf));

      memset(buf, 0, sizeof(buf));
      lseek(handle, 0, SEEK_SET);
      read(handle, buf, sizeof(buf));
      printf("buf = %s\n", buf);

      ioctl(handle, CLEAR_BUF, 0);
      lseek(handle, 0, SEEK_SET);
      memset(buf, 0, sizeof(buf));
      read(handle, buf, sizeof(buf));
      printf("buf = %s\n", buf);
   }

   return 0;
}


编译:
make
gcc main.c -o main

插入模块:
sudo insmod mydev.ko

删除模块:
sudo rmmod mydev.ko

查看模块:
lsmod

测试:
./main

查看内核输出:
dmesg

如果成功的话会看到输出读取和写入多少数据的

作者: 天使ッ翼   发布时间: 2011-01-21