• 驱动编写及编译例子


    通用驱动程序基于globalmem共享内存的驱动编写write、read、ioctl、lseek函数globalmem.c

      1 #include <linux/module.h>
      2 #include <linux/types.h>
      3 #include <linux/fs.h>
      4 #include <linux/errno.h>
      5 #include <linux/mm.h>
      6 #include <linux/sched.h>
      7 #include <linux/init.h>
      8 #include <linux/cdev.h>
      9 #include <asm/io.h>
     10 #include <asm/system.h>
     11 #include <asm/uaccess.h>
     12 
     13 #define GLOBALMEM_SIZE 0x1000  /*全局内存最大4KB*/
     14 #define MEM_CLEAR 0x1 /*清零全局内存*/
     15 #define GLOBALMEM_MAJOR 250 /*预设的globalmem的主设备号*/
     16 
     17 static int globalmem_major = GLOBALMEM_MAJOR;
     18 /*globalmem设备结构体*/
     19 struct globalmem_dev {
     20 struct cdev cdev; /*cdev结构体*/
     21 unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/
     22  };
     23 
     24 struct globalmem_dev *globalmem_devp; /*设备结构体指针*/
     25 /*文件打开函数*/
     26 int globalmem_open(struct inode *inode, struct file *filp)
     27 {
     28 /*将设备结构体指针赋值给文件私有数据指针*/
     29   filp->private_data = globalmem_devp;
     30   return 0;
     31 }
     32 /*文件释放函数*/
     33 int globalmem_release(struct inode *inode, struct file *filp)
     34 {
     35  return 0;
     36 }
     37 
     38 /* ioctl设备控制函数 */
     39 static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned
     40   int cmd, unsigned long arg)
     41 {
     42  struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
     43 
     44   switch (cmd) {
     45   case MEM_CLEAR:
     46      memset(dev->mem, 0, GLOBALMEM_SIZE);
     47      printk(KERN_INFO "globalmem is set to zero
    ");
     48      break;
     49 
     50    default: 
     51      return - EINVAL;
     52   }
     53 
     54   return 0;
     55 }
     56 
     57 /*读函数*/
     58 static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,
     59   loff_t *ppos)
     60 {
     61   unsigned long p = *ppos;
     62   unsigned int count = size;
     63   int ret = 0;
     64 struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
     65 
     66 /*分析和获取有效的写长度*/
     67   if (p >= GLOBALMEM_SIZE)
     68      return 0;
     69   if (count > GLOBALMEM_SIZE - p)
     70      count = GLOBALMEM_SIZE - p;
     71 
     72 /*内核空间→用户空间*/
     73   if (copy_to_user(buf, (void *)(dev->mem + p), count)) {
     74      ret = - EFAULT;
     75   } else {
     76      *ppos += count;
     77      ret = count;
     78 
     79      printk(KERN_INFO "read %u bytes(s) from %lu
    ", count, p);
     80   }
     81 
     82   return ret;
     83 }
     84 
     85 /*写函数*/
     86 static ssize_t globalmem_write(struct file *filp, const char _ _user *buf,
     87   size_t size, loff_t *ppos)
     88 {
     89   unsigned long p = *ppos;
     90   unsigned int count = size;
     91   int ret = 0;
     92 struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
     93 
     94 /*分析和获取有效的写长度*/
     95   if (p >= GLOBALMEM_SIZE)
     96      return 0;
     97   if (count > GLOBALMEM_SIZE - p)
     98      count = GLOBALMEM_SIZE - p;
     99 
    100  /*用户空间→内核空间*/
    101    if (copy_from_user(dev->mem + p, buf, count))
    102       ret = - EFAULT;
    103    else {
    104       *ppos += count;
    105       ret = count; 
    106  
    107       printk(KERN_INFO "written %u bytes(s) from %lu
    ", count, p);
    108    }
    109  
    110    return ret;
    111  }
    112  
    113  /* seek文件定位函数 */
    114  static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)
    115  {
    116    loff_t ret = 0;
    117    switch (orig) {
    118  case 0: /*相对文件开始位置偏移*/
    119       if (offset < 0)  {
    120         ret = - EINVAL;
    121         break;
    122       }
    123       if ((unsigned int)offset > GLOBALMEM_SIZE) {
    124         ret = - EINVAL;
    125         break;
    126       }
    127       filp->f_pos = (unsigned int)offset;
    128       ret = filp->f_pos;
    129       break;
    130  case 1: /*相对文件当前位置偏移*/
    131       if ((filp->f_pos + offset) > GLOBALMEM_SIZE) {
    132         ret = - EINVAL;
    133         break;
    134       }
    135       if ((filp->f_pos + offset) < 0) {
    136         ret = - EINVAL;
    137         break;
    138       }
    139       filp->f_pos += offset;
    140       ret = filp->f_pos;
    141       break;
    142    default:
    143       ret = - EINVAL;
    144       break;
    145    }
    146    return ret;
    147  }
    148  
    149  /*文件操作结构体*/
    150  static const struct file_operations globalmem_fops = {
    151    .owner = THIS_MODULE,
    152    .llseek = globalmem_llseek,
    153    .read = globalmem_read,
    154    .write = globalmem_write,
    155    .ioctl = globalmem_ioctl,
    156    .open = globalmem_open,
    157    .release = globalmem_release,
    158  };
    159  
    160  /*初始化并注册cdev*/ 
    161  static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
    162  {
    163    int err, devno = MKDEV(globalmem_major, index);
    164  
    165    cdev_init(&dev->cdev, &globalmem_fops);
    166    dev->cdev.owner = THIS_MODULE;
    167    err = cdev_add(&dev->cdev, devno, 1);
    168    if (err)
    169       printk(KERN_NOTICE "Error %d adding globalmem %d", err, index);
    170  }
    171  
    172  /*设备驱动模块加载函数*/
    173  int globalmem_init(void)
    174  {
    175    int result;
    176    dev_t devno = MKDEV(globalmem_major, 0);
    177  
    178  /* 申请设备号*/
    179    if (globalmem_major)
    180       result = register_chrdev_region(devno, 1, "globalmem");
    181  else { /* 动态申请设备号 */
    182       result = alloc_chrdev_region(&devno, 0, 1, "globalmem");
    183       globalmem_major = MAJOR(devno);
    184    }
    185    if (result < 0)
    186       return result;
    187  
    188  /* 动态申请设备结构体的内存*/
    189    globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
    190  if (!globalmem_devp) { /*申请失败*/
    191       result = - ENOMEM;
    192       goto fail_malloc;
    193    }
    194  
    195    memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
    196  
    197    globalmem_setup_cdev(globalmem_devp, 0);
    198    return 0;
    199  
    200  fail_malloc:
    201    unregister_chrdev_region(devno, 1);
    202    return result;
    203  }
    204  
    205  /*模块卸载函数*/
    206  void globalmem_exit(void)
    207  {
    208  cdev_del(&globalmem_devp->cdev); /*注销cdev*/
    209  kfree(globalmem_devp); /*释放设备结构体内存*/
    210  unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);/*释放设备号*/
    211  }
    212  
    213  MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
    214  MODULE_LICENSE("Dual BSD/GPL");
    215   
    216  module_param(globalmem_major, int, S_IRUGO);
    217  
    218  module_init(globalmem_init);
    219  module_exit(globalmem_exit);

    驱动编译Makefile:

     1 $(warning KERNELRELEASE=$(KERNELRELEASE))
     2 
     3 ifeq ($(KERNELRELEASE),)
     4 
     5 KERNELDIR ?= /home/tom/fs2416/linux-2.6.39-FS2416
     6 PWD := $(shell pwd)
     7 
     8 modules:
     9     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    10 
    11 modules_install:
    12     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
    13 
    14 clean:
    15     rm -rf *.o core *.ko *~ .depend .*.cmd *.mod.c .tmp_versions Module* modules*
    16 
    17 .PHONY:
    18     modules modules_install clean
    19 
    20 else
    21     obj-m := globalmem.o
    22 endif

    其中:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 的操作:$(MAKE) -C $(KERNELDIR)进入内核源码目录下执行主Makefile,其中会定义KERNELRELEASE常量;M=$(PWD) modules进入当前目录,执行当前目录下的Makefile,生产模块;
    -C是表示进入$(KERNELDIR)目录执行makefile,M指定要生成的外部模块的目录。

    Use make M=dir to specify directory of external module to build 

  • 相关阅读:
    [Windows]Windows的访问控制模型
    [C/C++]宽字符与控制台程序
    [SQL Server]自动化附加和分离数据库
    [ASP.NET]自动发送邮件功能的实现
    [Windows]Windows路径探究
    asp.net中怎么样获取前一页地址
    CheckBox全选CheckBoxList
    远程SQL插入数据
    SQL存储过程调用作业的方法
    [转]javascript 调用后台函数
  • 原文地址:https://www.cnblogs.com/minuse/p/3322449.html
Copyright © 2020-2023  润新知