`
igp92igp
  • 浏览: 16547 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Linux设备驱动程序设计(17.2)(完)

 
阅读更多

Linux设备驱动程序设计(17.2)(完)
2010年06月05日
  访问用户空间[/b]
  核心的第一个2.1版引入了一种从核心代码访问用户空间的新(更好)方法。这个改变修正了一个长期存在的错误行为并增强了系统的性能。
  当你位核心2.1编译代码,并需要访问用户空间时,你需要包含,而不是。你还必须使用一个与2.0不同的函数集。不用说,头文件sysdep-2.1.h尽可能地照顾了这些不同,允许你在2.0上编译时使用2.1的语义。
  在用户访问中最令人注意的不同时verify_area没有了,因为多数验证都由CPU完成了。关于这个主题的细节见本章后面的“处理核心空间错误”。
  可被用来访问用户空间的新的函数集是:
  int access_ok(int type, unsigned long addr, unsigned long size);
  如果当前进程被允许访问地址addr处的内存,函数返回真(1),否则为假(0)。这个函数取代verify_area,尽管它进行较少的检查。和老的verify_area接收一样的参数,但是要快的多。在你复引用一个用户空间地址之前,这个函数应该被调用对之进行检查;如果你没有检查,用户有可能会访问和修改核心内存。本章后面的“虚拟内存”一节更细致地解释了这个问题。幸运的是,下面描述的大多数函数都替你进行了这个检查,因此你实际上并不需要调用access_ok,除非你选择这样做。
  int get_user(lvalue, address);
  在2.1核心中使用的宏get_user与我们在2.0中使用的并不相同。其返回值在成功时为0,否则为一个负的错误代码(总是-EFAULT)。这个函数的净效果是将从地址address取得的数据赋给lvalue。在通常的C语言含义中,这个宏的第一个参数必须是一个lvalue*。与2.0版中的这个函数类似,数据项的实际大小依赖于address参数类型。这个函数在内部调用access_ok。
  int __get_user(lvalue, address);
  这个函数完全类似get_user,但它不内部调用access_ok。当你访问一个已经从同一核心函数内部检查过的用户地址时,你应该调用__get_user。
  get_user_ret(lvalue, address, retval);
  这个宏是调用get_user的快捷方式,如果函数失败则返回retval。
  int put_user(expression, address);
  int __put_user(expression, address);
  put_user_ret(expression, address, retval);
  这些函数与它们的get_对应者非常类似,只是它们是向用户空间写,而不是读。成功时,值expression被写到地址address。
  unsigned long copy_from_user(unsigned long to, unsigned long from, unsigned long len);
  这个函数从用户空间复制数据到核心空间。它代替旧的memcpy_tofs调用。这个函数内部调用access_ok。返回值是未能传送的字节数。这样,如果发生错误,返回值必然大于0;在那种情况下,驱动程序返回-EFAULT,因为错误是由错误的内存访问引起的。
  unsigned long __copy_from_user(unsigned long to, unsigned long from, unsigned long len);
  这个函数与copy_from_user一样,但它不内部调用access_ok。
  caopy_from_user_ret(to, from, len, retval);
  这个宏是内部调用copy_from_user的快捷方式;如果失败,则从当前函数返回。
  unsigned long copy_to_user(unsigned long to, unsigned long from, unsigned long len);
  unsigned long __copy_to_user(unsigned long to, unsigned long from, unsigned long len);
  copy_to_user(to, from, len, retval);
  这些函数被用来将数据复制到用户空间,它们的行为非常类似于它们的copy_from的对应者。
  2.1版核心还定义了其它访问用户空间的函数:clear_user,strncpy_from_user,和strlen_user。我不打算讨论它们了,因为Linux2.0中没有这些函数,并且驱动程序的代码也很少用到它们。有兴趣的读者可以看看。
  [b]使用新的接口
[b][/b]
  访问用户空间的新的函数集初看起来可能有点令人失望,但它们的确使程序员的日子好过的多了。在Linux2.1上,不再需要显式地检查用户空间;access_ok一般不需要调用。使用新接口的代码可以直接进行数据传送。_ret函数在实现系统调用时证明是相当有用的,因为一个用户空间的失败通常导致系统调用的一个返回-EFAULT的失败。
  因此,一个典型的read实现,看起来如下:
  long new_read(struct inode *inode, struct file *filp, char *buf, unsigned long count);
  {
  /* identify your data (device-specific code) */
  if (__copy_to_user(buf, new_data, count))
  return -EFAULT;
  return count;
  }
  注意使用不进行检查的__copy_to_user是因为调用者在把数据传输分派到文件操作之前已经检查了用户空间。这就象2.0,read和write不需要调用verify_area。
  类似地,典型的ioctl实现看起来如下:
  int new_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
  {
  /* device-specific checks, if needed */
  switch(cmd){
  case NEW_GETVALUE:
  put_user_ret(new_value, (int *)arg, -EFAULT);
  break;
  case NEW_SETVALUE:
  get_user_ret(new_value, (int *)arg, -EFAULT);
  default:
  return
分享到:
评论

相关推荐

    《精通Linux 设备驱动程序开发》.(Sreekrishnan).pdf

     本书是linux设备驱动程序开发领域的权威著作。全书基于2.6内核,不仅透彻讲解了基本概念和技术,更深入探讨了其他书没有涵盖或浅尝辄止的许多重要主题和关键难点,如pcmcia、i2c和usb等外部总线以及视频、音频、...

    精通LINUX设备驱动程序开发

    78 4.5 电源管理 79 4.6 查看源代码 79 第5章 字符设备驱动程序 81 5.1 字符设备驱动程序基础 81 5.2 设备实例:系统cmos 82 5.2.1 驱动程序初始化 83 5.2.2 打开与释放 86 5.2.3 数据交换 88 5.2.4 查找 ...

    linux设备驱动程序第三版

    1. Linux 设备驱动第三版 .................................................................................................................... 5 2. 第 1 章 设备驱动简介 ....................................

    Linux程序设计 第4版.haozip01

    3.2 系统调用和设备驱动程序 80 3.3 库函数 81 3.4 底层文件访问 82 3.4.1 write系统调用 82 3.4.2 read系统调用 83 3.4.3 open系统调用 84 3.4.4 访问权限的初始值 85 3.4.5 其他与文件管理有关的系统调用 ...

    Linux程序设计 第4版.haozip02

    3.2 系统调用和设备驱动程序 80 3.3 库函数 81 3.4 底层文件访问 82 3.4.1 write系统调用 82 3.4.2 read系统调用 83 3.4.3 open系统调用 84 3.4.4 访问权限的初始值 85 3.4.5 其他与文件管理有关的系统调用 ...

    Android驱动开发权威指南

    第7章Linux设备驱动中的内存与I/O访问 7.1 CPU与内存和I/O之间的故事 7.1.1内存空间与I/O空间 7.1.2内存管理单元MMU 7.2 Linux内存管理 7.3 Linux内存访问 7.4 LinuxI/O访问 7.4.1访问I/O 7.4.2申请与释放I/O资源 ...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part3

    3.5.3 网络设备驱动程序 82 第4章 hal层深入分析 84 4.1 认识hal层 84 4.1.1 hal层的发展 84 4.1.2 过去和现在的区别 86 4.2 分析hal层源代码 86 4.2.1 分析hal moudle 86 ...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part1

    3.5.3 网络设备驱动程序 82 第4章 hal层深入分析 84 4.1 认识hal层 84 4.1.1 hal层的发展 84 4.1.2 过去和现在的区别 86 4.2 分析hal层源代码 86 4.2.1 分析hal moudle 86 ...

    LINUX操作系统(电子教案,参考答案)

    主要包括Linux的基本概念和操作,Linux的树型结构,Linux的文本编辑,Linux的安装和启动,用户管理,Shell编程技术,进程管理,C编译器,系统扩充,维护与监视,Linux的图形界面,网络的基本概念与设置,Linux在网络...

    RED HAT LINUX 6大全

    本书全面系统地介绍了Red Hat Linux 6。全书共分为五个部分,包括35章和四个附录。第一部分为Red Hat Linux的介绍和安装;第二部分为服务配置;第三部分为系统管理;第四部分为Linux编程;第五部分为附录。本书内容...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part2

    3.5.3 网络设备驱动程序 82 第4章 hal层深入分析 84 4.1 认识hal层 84 4.1.1 hal层的发展 84 4.1.2 过去和现在的区别 86 4.2 分析hal层源代码 86 4.2.1 分析hal moudle 86 ...

    LINUX安装与配置简明手册

    4.1.3 LILO程序,Linux操作系统的加载 程序 34 4.1.4 配置显示选项的考虑 35 4.1.5 系统开机引导时可以使用的服务 35 4.1.6 安装多个操作系统 36 4.2 快速解决方案 36 4.2.1 确定哪些安装盘是必需的 36 4.2.2 制作...

    understanding linux network internals

    Old Interface Between Device Drivers and Kernel: First Part of netif_rx 内核到设备驱动之间的老的接口 Section 10.6. Congestion Management 阻塞管理 Section 10.7. Processing the ...

    linux安装与配置简明手册

    4.1.3 LILO程序,Linux操作系统的加载 程序 34 4.1.4 配置显示选项的考虑 35 4.1.5 系统开机引导时可以使用的服务 35 4.1.6 安装多个操作系统 36 4.2 快速解决方案 36 4.2.1 确定哪些安装盘是必需的 36 4.2.2...

    LINUX系统管理白皮书

    3.5 SLIP和PPP驱动程序 31 第4章 串行硬件的设置 32 4.1 Modem通信软件 32 4.2 串行设备概述 32 4.3 访问串行设备 33 4.4 串行硬件 34 第5章 TCP/IP网络配置 36 5.1 proc文件系统的设置 36 5.2 二进制文件的...

    LINUX 24学时教程

    本书详细讲解了用Linux的图形配置工具配置Caldera OpenLinux,通过一个ppp与网络连接、使用K桌面环境、用StarOffice提高在家办公的效率、网络浏览、发传真、接收email及使用GIMP等图形工具。 24学时每次1小时的课程...

Global site tag (gtag.js) - Google Analytics