linux设备驱动程序的编写

更新日期:2021-10-15

来源:纯净之家


系统大全为您提供
 先介绍下我的环境,用的ubuntu发行版,kernel版本是3.8.0,《Linux设备驱动程序》一书是针对2.6.0的kernel,在这个例子中会看到一些差异。这个例子要实现的目标是,编译装载该module后,通过udev动态的生成设备节点star0,读取设备节点cat /dev/star0可以打印出星号,星号的数量可以由模块参数动态的指定。以下为源代码:
  star.h
  #ifndef STAR_H_H_H
  #define STAR_H_H_H
  #define AUTHOR "Tao Yang"
  #define DESCRIPTION "A CHAR DEVICE DIRVERS SAMPLE USING UDEV"
  #define VERSION "0.1"
  #endif
  star.c
  //module_init module_exit
  #include
  #include
  //module_param
  #include
  //printk container_of
  #include
  //dev_t MAJOR MINOR MKDEV
  #include
  //file_operations file register/unregister_chrdev_region alloc_chrdev_region register/unregister_chrdev(old)
  #include
  /

linux设备驱动程序的编写

ev cdev_init/add/del
  #include
  //copy_from_user copy_to_user
  #include
  #include
  #include "star.h"
  //define device number
  #define STAR_MAJOR 0
  #define STAR_MINOR 0
  #define STAR_DEVS 1
  #define DEVICE_NAME "star0"
  #define CLASS_NAME "star"
  static int howmany=5;
  module_param(howmany,int,S_IRUGO);
  //module info
  MODULE_AUTHOR(AUTHOR);
  MODULE_DESCRIPTION(DESCRIPTION);
  MODULE_VERSION(VERSION);
  MODULE_LICENSE("GPL");
  //device variables
  static struct class* star_class=NULL;
  static struct device* star_sysdevice=NULL;
  int star_major=STAR_MAJOR;
  int star_minor=STAR_MINOR;
  int star_nr_devs=STAR_DEVS;
  //device struct
  static struct star_dev {
  char *data;
  struct cdev cdev;
  };
  static struct star_dev star_device;
  static ssize_t star_read(struct file * filp,char * buf,size_t count,loff_t *ppos)
  {
  int i;
  char star_str[10000];
  struct star_dev *dev=filp->private_data;
  for (i=0;i
  star_str[i]='*';
  }
  star_str[howmany]=' ';
  int len=strlen(star_str);
  if(count
  return -EINVAL;
  if(*ppos!=0)
  return 0;
  if(copy_to_user(buf,star_str,len))
  return -EINVAL;
  *ppos=len;
  return len;
  }
  int star_open(struct inode *inode,struct file *filp)
  {
  struct star_dev *dev;
  dev=container_of(inode->i_cdev,struct star_dev,cdev);
  filp->private_data=dev;
  //......
  return 0;
  }
  //file operations
  static const struct file_operations star_fops = {
  .owner = THIS_MODULE,
  .read = star_read,
  .open = star_open,
  };
  static void star_setup_cdev(struct star_dev *dev,int index)
  {
  int err,devno=MKDEV(star_major,star_minor+index);
  printk(KERN_ALERT "setup cdev... ");
  cdev_init(&dev->cdev,&star_fops);
  dev->cdev.owner=THIS_MODULE;
  dev->cdev.ops=&star_fops;
  err=cdev_add(&dev->cdev,devno,1);
  if(err)
  printk(KERN_ALERT "Error %d adding star%d",err,index);
  }
  static int __init star_init(void)
  {
  int ret;
  dev_t dev;

 printk(KERN_ALERT "hello tom! ");
  if(star_major){
  dev=MKDEV(star_major,star_minor);
  ret=register_chrdev_region(dev,star_nr_devs,DEVICE_NAME);
  printk(KERN_ALERT "static! ");
  }else{
  ret=alloc_chrdev_region(&dev,star_minor,star_nr_devs,DEVICE_NAME);
  star_major=MAJOR(dev);
  printk(KERN_ALERT "dynamic! ");
  printk(KERN_ALERT "Device Major is %d! ",star_major);
  }
  if(ret<0){
  printk(KERN_ALERT "star:can't get major %d ",star_major);
  return ret;
  }
  printk(KERN_ALERT "set up cdev!");
  star_setup_cdev(&star_device,0);
  star_class=class_create(THIS_MODULE,CLASS_NAME);
  if(IS_ERR(star_class)){
  printk(KERN_ALERT "failed to register device class '%s' ",CLASS_NAME);
  }
  //with a class ,the easiest way to instantiate a device is to call device_create()
  star_sysdevice=device_create(star_class,NULL,MKDEV(star_major,0),NULL,DEVICE_NAME);
  return 0;
  }
  static void __exit star_exit(void)
  {
  device_destroy(star_class,MKDEV(star_major,star_minor));
  class_unregister(star_class);
  class_destroy(star_class);
  cdev_del(&star_device.cdev);
  printk(KERN_ALERT "goodbye... ");
  }
  module_init(star_init);
  module_exit(star_exit);
  Makefile
  ifneq ($(KERNELRELEASE),)
  obj-m:=star.o
  else
  KERNELDIR ?= 

linux设备驱动程序的编写

b/modules/$(shell uname -r)

linux设备驱动程序的编写

ild
  PWD :=$(shell pwd)
  default:
  $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  endif
  编译源代码:
  root@ubuntu:~/embedded_linux/ldd3/practice# make
  make -C 

linux设备驱动程序的编写

b/modules/3.8.0-29-generic

linux设备驱动程序的编写

ild M=/home/tom/embedded_linux/ldd3/practice modules
  make[1]: Entering directory `/usr

linux设备驱动程序的编写

c

linux设备驱动程序的编写

nux-headers-3.8.0-29-generic'
  CC [M] /home/tom/embedded_linux/ldd3/practice/star.o
  /home/tom/embedded_linux/ldd3/practice/star.c:58:1: warning: useless storage class specifier in empty declaration [enabled by default]
  /home/tom/embedded_linux/ldd3/practice/star.c: In function ‘star_read’:
  /home/tom/embedded_linux/ldd3/practice/star.c:72:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
  /home/tom/embedded_linux/ldd3/practice/star.c:66:22: warning: unused variable ‘dev’ [-Wunused-variable]
  /home/tom/embedded_linux/ldd3/practice/star.c:81:1: warning: the frame size of 10032 bytes is larger than 1024 bytes [-Wframe-larger-than=]
  Building modules, stage 2.
  MODPOST 1 modules
  CC /home/tom/embedded_linux/ldd3/practice/star.mod.o
  LD [M] /home/tom/embedded_linux/ldd3/practice/star.ko
  make[1]: Leaving directory `/usr

linux设备驱动程序的编写

c

linux设备驱动程序的编写

nux-headers-3.8.0-29-generic'
  root@ubuntu:~/embedded_linux/ldd3/practice#
  安装驱动模块:
  root@ubuntu:~/embedded_linux/ldd3/practice# insmod star.ko
  root@ubuntu:~/embedded_linux/ldd3/practice# dmesg -c
  [ 3946.696548] hello tom!
  [ 3946.699892] dynamic!
  [ 3946.699894] Device Major is 249!
  [ 3946.699895] set up cdev!  
 
  [ 3946.699896] setup cdev...
  root@ubuntu:~/embedded_linux/ldd3/practice#
  这时可以看到/dev/目录下自动生成了设备节点:
  root@ubuntu:~/embedded_linux/ldd3/practice# ls -l /dev/star0
  crw------- 1 root root 249, 0 Feb 8 14:25 /dev/star0
  root@ubuntu:~/embedded_linux/ldd3/practice#
  接下来去读取设备节点:
  root@ubuntu:~/embedded_linux/ldd3/practice# cat /dev/star0
  *****
  在加载驱动模块时,传递参数,也就是指定打印出星号的个数:
  root@ubuntu:~/embedded_linux/ldd3/practice# insmod star.ko howmany=10
  root@ubuntu:~/embedded_linux/ldd3/practice# cat /dev/star0
  **********
  root@ubuntu:~/embedded_linux/ldd3/practice#
  最后,以上是我在学习过程中写的一个精简的例子,因此很多技巧及错误处理都没有注意,主要是为了勾勒出linux设备驱动程序的宏观骨架,自己最好能通过读代码总结画出一个流程图,加深印象,代码也是配合着ldd3写的,希望能对正在读这本著作的初学者有所帮助。
  以上就是系统大全给大家介绍的如何使的方法都有一定的了解了吧,好了,如果大家还想了解更多的资讯,那就赶紧点击系统大全官网吧。 
 
本文来自系统大全http://www.win7cn.com/如需转载请注明!推荐:win7纯净版