文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>2.6内核字符驱动程序

2.6内核字符驱动程序

时间:2006-12-05  来源:kf701

目录
学习使用说明
1. 驱动程序源代码
2. Makefile
3. 加载脚本代码
4. 读测试
5. 写测试

首先你要有一份2.6内核的源码,然后编译并运行它。
在已运行了你编译的内核的系统里编译此驱动程序: $> make
编译成功后,以root身份运行加载脚本: $> ./chardev_load.sh
一切完成后,就可以测试你的驱动程序了。
此驱动程序的输出全部写到了 /var/log/debug 文件中,你可以如下查看:
$> tail -f /var/log/debug
我用的是 Linux debian 2.6.18.3,一切运行良好。

     1  /*
     2   *  chardev.c  kf701  2006/12/05
     3   *  /dev/kf701_chardev0  /proc/devices
     4   */
     5  #include <linux/init.h>
     6  #include <linux/kernel.h>
     7  #include <linux/module.h>
     8  #include <linux/fs.h>
     9  #include <asm/uaccess.h>
    10  #include <linux/cdev.h>
    11
    12  static int      chardev_open(struct inode *, struct file *);
    13  static int      chardev_release(struct inode *, struct file *);
    14  static ssize_t  chardev_read(struct file *, char __user *, size_t, loff_t *);
    15  static ssize_t  chardev_write(struct file *, const char __user *, size_t, loff_t *);
    16
    17  #define SUCCESS 0
    18  #define DEVICE  "kf701_chardev"
    19
    20  int major = 233;
    21  int minor = 0;
    22
    23  struct file_operations fops = {
    24          .owner =        THIS_MODULE,
    25          .read =         chardev_read,
    26          .write =        chardev_write,
    27          .open =         chardev_open,
    28          .release =      chardev_release,
    29  };
    30
    31  struct my_dev{
    32          uint8_t *buf;
    33          uint32_t size;
    34          uint32_t index;
    35          struct semaphore sem;
    36          struct cdev cdev;
    37  } kf701_dev;
    38
    39  static int __init chardev_init(void)
    40  {
    41          // 1. 分配主设备号
    42          dev_t devno = MKDEV( major, minor );
    43          int ret = register_chrdev_region( devno, 1, DEVICE );
    44          if( ret < 0 )
    45          {
    46            printk(KERN_DEBUG "register major number failed with %d\n", ret);
    47            return ret;
    48          }
    49          printk(KERN_DEBUG "%s:register major number OK\n",DEVICE);
    50
    51          // 2. 注册设备
    52          cdev_init( &kf701_dev.cdev, &fops );
    53          kf701_dev.cdev.ops = &fops;
    54          kf701_dev.cdev.owner = THIS_MODULE;
    55          ret = cdev_add( &kf701_dev.cdev, devno, 1 );
    56          if( ret < 0 )
    57          {
    58            printk(KERN_DEBUG "register device failed with %d\n", ret);
    59            return ret;
    60          }
    61          printk(KERN_DEBUG "%s:register device OK\n",DEVICE);
    62
    63          // 3. 分配本驱动要使用的内存
    64          kf701_dev.index = 0;
    65          kf701_dev.size = 1024;
    66          kf701_dev.buf = kmalloc( kf701_dev.size, GFP_KERNEL );
    67          if( NULL == kf701_dev.buf )
    68          {
    69            printk(KERN_DEBUG "kmalloc failed\n");
    70            return -ENOMEM;
    71          }
    72          printk(KERN_DEBUG "%s:kmalloc buffer OK\n",DEVICE);
    73
    74          // 初始化信号量
    75          init_MUTEX( &(kf701_dev.sem) );
    76          printk(KERN_DEBUG "%s:init semaphore OK\n",DEVICE);
    77
    78          return SUCCESS;
    79  }
    80
    81  static void __exit chardev_exit(void)
    82  {
    83          dev_t devno = MKDEV( major, minor );
    84          cdev_del( &kf701_dev.cdev );
    85          unregister_chrdev_region( devno, 1 );
    86
    87          printk(KERN_DEBUG "%s:unregister device OK\n",DEVICE);
    88  }
    89
    90  int chardev_open(struct inode *inode, struct file *file)
    91  {
    92          struct my_dev *dev = container_of(inode->i_cdev, struct my_dev, cdev);
    93          file->private_data = dev;
    94
    95          printk(KERN_DEBUG "%s:open OK\n",DEVICE);
    96          return SUCCESS;
    97  }
    98
    99  int chardev_release(struct inode *inode, struct file *file)
   100  {
   101          printk(KERN_DEBUG "%s:release OK\n",DEVICE);
   102          return SUCCESS;
   103  }
   104
   105  ssize_t chardev_read(struct file *file, char __user *buf, size_t count,loff_t *offset)
   106  {
   107          struct my_dev *dev = file->private_data;
   108          ssize_t retval = 0;
   109
   110          if( down_interruptible(&dev->sem) )
   111                  return -ERESTARTSYS;
   112          printk(KERN_DEBUG "%s:read down sem OK\n",DEVICE);
   113
   114          if( 0 == dev->index )
   115                  goto out;
   116          if( *offset >= dev->index )
   117                  goto out;
   118          if( (*offset+count) > dev->index )
   119                  count = dev->index - *offset;
   120          if( copy_to_user(buf, dev->buf + *offset, count) )
   121          {
   122                  retval = -EFAULT;
   123                  goto out;
   124          }
                *offset += count;
   125          retval = count;
   126
   127  out:
   128          up(&dev->sem);
   129          printk(KERN_DEBUG "%s:read up sem OK\n",DEVICE);
   130          return retval;
   131  }
   132
   133  //  omit offset argument for write
   134  ssize_t chardev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
   135  {
   136          struct my_dev *dev = file->private_data;
   137          ssize_t retval = -ENOMEM;
   138
   139          if( down_interruptible(&dev->sem) )
   140                  return -ERESTARTSYS;
   141          printk(KERN_DEBUG "%s:write down sem OK\n",DEVICE);
   142
   143          if( count > dev->size )
   144                  goto out;
   145          if( copy_from_user(dev->buf, buf, count) )
   146          {
   147                  retval = -EFAULT;
   148                  goto out;
   149          }
   150          dev->index = count;
   151          retval = count;
   152
   153  out:
   154          up(&dev->sem);
   155          printk(KERN_DEBUG "%s:write up sem OK\n",DEVICE);
   156          return retval;
   157  }
   158
   159  module_init(chardev_init);
   160  module_exit(chardev_exit);
   161  MODULE_AUTHOR("kf701.ye at gmail.com");
   162  MODULE_DESCRIPTION("Study for kf701");
   163  MODULE_SUPPORTED_DEVICE(DEVICE);
   164  MODULE_LICENSE("GPL");

下面是Makefile内容:
     1
     2  ###
     3  # study
     4  # kf_701
     5  # 2006-12-4
     6  ###
     7
     8  #obj-m += hello.o
     9  obj-m += chardev.o
    10
    11  all:
    12          make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    13  clean:
    14          make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

加载脚本代码如下:

     1  #!/bin/sh
     2
     3  module="chardev"
     4  device="kf701_chardev"
     5  mode=666
     6
     7  echo "insmod now"
     8  /sbin/insmod ./$module.ko || exit 1
     9
    10  rm -f /dev/${device}0
    11
    12  major=$(awk "{ if(\$2 == \"${device}\") print \$1;}" /proc/devices)
    13
    14  echo "mknod now"
    15  mknod /dev/${device}0 c $major 0
    16
    17  group="staff"
    18  grep -q '^staff:' /etc/group || group="wheel"
    19
    20  echo "chgrp now"
    21  chgrp $group /dev/${device}0
    22  chmod $mode /dev/${device}0
    23

下面是读测试方法:
$> cat /dev/kf701_chardev0

写测试如下命令:

$> echo "only for test" > /dev/kf701_chardev0
相关阅读 更多 +
排行榜 更多 +
风度

风度

游戏工具 下载
大姨妈月经提醒

大姨妈月经提醒

健康医疗 下载
海岸线小说网

海岸线小说网

浏览阅读 下载