您的位置:首页 > 运维架构 > Linux

如何编写Linux操作系统下的设备驱动程序

2009-10-21 12:54 543 查看
  如何编写Linux操作系统下的设备驱动程序
  序言
  Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和
  思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的
  区别.在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是
  支持函数少,只能依赖kernel中的
  他给的源代码,一是年代久远,内核版本差异太大,二则有些错误不知是否故意为之,
  总之是错误一大堆。
  源代码如下:(红色即有错之处 ,我后面再贴出自己的)
  #include <linux/types.h>
  #include <linux/fs.h>
  #include <linux/mm.h>
  #include <linux/errno.h>
  #include <asm/segment.h>
  unsigned int test_major = 0;
  static int read_test(struct inode *node,struct file *file,
  char *buf,int count) //2.4的内核定义的read入口参数不同,请见usr/src/linux-X.XX-X/include/linux/fs.h
  {
  int left;
  if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT ) //少引入了一个定义VERIFY_WRITE头文件<asm/uaccess.h>
  return -EFAULT;
  for(left = count ; left > 0 ; left--)
  {
  __put_user(1,buf,1); //在2.4内核源码中,__put_user只有两个入口参数
  /*
  * #define put_user(x,ptr)
  * __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
  */
  buf++;
  }
  return count;
  }
  static int write_tibet(struct inode *inode,struct file *file,
  const char *buf,int count) //错误同read,而且故意把write_test写成write_tibet
  {
  return count;
  }
  static int open_tibet(struct inode *inode,struct file *file )
  {
  MOD_INC_USE_COUNT;
  return 0;
  }
  static void release_tibet(struct inode *inode,struct file *file )
  {
  MOD_DEC_USE_COUNT;
  }
  //新内核的file_operations定义了更多数据类型,因此这样的方式不太好,详见我的程序
  struct file_operations test_fops = {
  NULL,
  read_test,
  write_test,
  NULL, /* test_readdir */
  NULL,
  NULL, /* test_ioctl */
  NULL, /* test_mmap */
  open_test,
  release_test, NULL, /* test_fsync */
  NULL, /* test_fasync */
  /* nothing more, fill with NULLs */
  };
  int init_module(void)
  {
  int result;
  result = register_chrdev(0, "test", &test_fops);
  if (result < 0) {
  printk(KERN_INFO "test: can't get major number\n");
  return result;
  }
  if (test_major == 0) test_major = result; /* dynamic */
  return 0;
  }
  void cleanup_module(void)
  {
  unregister_chrdev(test_major, "test");
  }
  我改正后的程序(在rethat9.0,内核版本2.4.20-8下通过):
  引用:
  //=========================================
  #define __NO_VERSION__
  #include <linux/module.h>
  #include <linux/config.h>
  #include <linux/version.h>
  #include <asm/uaccess.h>
  #include <linux/types.h>
  #include <linux/fs.h>
  #include <linux/mm.h>
  #include <linux/errno.h>
  #include <asm/segment.h>
  unsigned int test_major = 0;
  static ssize_t read_test(struct file *file,char *buf,size_t count,loff_t *f_pos)
  { int left;
  if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )
  return -EFAULT;
  for(left = count ; left > 0 ; left--)
  {
  __put_user(1,buf);
  buf++;
  }
  return count;
  }
  static ssize_t write_test(struct file *file, const char *buf, size_t count, loff_t *f_pos)
  {
  return count;
  }
  static int open_test(struct inode *inode,struct file *file )
  {
  MOD_INC_USE_COUNT;
  return 0;
  }
  static int release_test(struct inode *inode,struct file *file )
  {
  MOD_DEC_USE_COUNT;
  return 0;
  }
  struct file_operations test_fops = {
  read:read_test,
  write:write_test,
  open: open_test,
  release:release_test
  };
  int init_module(void)
  {
  int result;
  result = register_chrdev(0, "test", &test_fops);
  if (result < 0) {
  printk(KERN_INFO "test: can't get major number\n");
  return result;
  }
  if (test_major == 0) test_major = result; /* dynamic */
  return 0;
  }
  void cleanup_module(void)
  {
  unregister_chrdev(test_major, "test");
  }
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("BECKHAM");
  //===================================
  这个程序存为test.c ,它的makefile:
  CC=gcc
  MODCFLAGS:=-Wall -DMODULE -D__KERNEL__ -DLINUX -I /usr/src/linux-2.4.20-8/include
  test.o:test.c
  $(CC) $(MODCFLAGS) -c test.c
  (make file的写法见http://bbs.chinaunix.net/forum/viewtopic.php?p=2102868#2102868
  存为test.mk
  在命令行输入# make -f test.mk
  驱动程序已经编译好了,现在把它安装到系统中去。
  $ insmod -f chardev.o
  如果安装成功,在/proc/devices文件中就可以看到设备test,
  并可以看到它的主设备号。
  要卸载的话,运行
  $ rmmod test
  下一步要创建设备文件。
  mknod /dev/test c major minor
  c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。
  minor是从设备号,设置成0就可以了。
  如: mknod /dev/test c 254 0
  我们现在可以通过设备文件来访问我们的驱动程序。写一个小小的测试程序。
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  main()
  {
  int testdev;
  int i;
  char buf[10];
  testdev = open("/dev/test",O_RDWR);
  if ( testdev == -1 )
  {
  printf("Cann't open file \n");
  exit(0);
  }
  read(testdev,buf,10);
  for (i = 0; i < 10;i++)
  printf("%d\n",buf);
  close(testdev);
  }
  编译运行,看看是不是打印出全1 ?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: