愤怒的大鸟 发表于 2015-1-16 11:53:03

带来一篇从 Linux 内核会见用户空间内存

但不会命令而成为高手也是不可能的.这就好比学英语,什么语法都不懂,只捧着单词手册背单词是学不会英语的,但是没有单词词汇量英语水平也提不高的。
Linux内存  在Linux中,用户内存和内核内存是自力的,在各自的地点空间完成。地点空间是假造的,就是说地点是从物理内存中笼统出来的(经由过程一个冗长形貌的历程)。因为地点空间是假造的,以是能够存在良多。现实上,内核自己驻留在一个地点空间中,每一个历程驻留在本人的地点空间。这些地点空间由假造内存地点构成,同意一些带有自力地点空间的历程指向一个绝对较小的物理地点空间(在呆板的物理内存中)。不单单是便利,并且更平安。由于每一个地点空间是自力且断绝的,因而很平安。
  可是与平安性相干联的本钱很高。由于每一个历程(和内核)会有不异地点指向分歧的物理内存地区,不成能当即共享内存。侥幸的是,有一些办理计划。用户历程能够经由过程PortableOperatingSystemInterfaceforUNIX?(POSIX)共享的内存机制(shmem)共享内存,但有一点要申明,每一个历程大概有一个指向不异物理内存地区的分歧假造地点。
  假造内存到物理内存的映照经由过程页表完成,这是在底层软件中完成的(见)。硬件自己供应映照,可是内核办理表及其设置。注重这里的显现,历程大概有一个年夜的地点空间,可是很少见,就是说小的地点空间的地区(页面)经由过程页表指向物理内存。这同意历程仅为随时必要的网页指定年夜的地点空间。
.页表供应从假造地点到物理地点的映照

  因为缺少为历程界说内存的才能,底层物理内存被过分利用。经由过程一个称为paging(但是,在Linux中一般称为swap)的历程,很少利用的页面将主动移到一个速率较慢的存储设备(好比磁盘),来包容必要被会见的别的页面(见)。这一举动同意,在将很少利用的页面迁徙到磁盘来进步物理内存利用的同时,盘算机中的物理内存为使用程序更简单必要的页面供应服务。注重,一些页面能够指向文件,在这类情形下,假如页面是脏(dirty)的,数据将被冲刷,假如页面是洁净的(clean),间接丢失落。
.经由过程将很少利用的页面迁徙到速率慢且廉价的存储器,互换使物理内存空间失掉了更好的使用

  MMU-less架构
  不是一切的处置器都有MMU。因而,uClinux刊行版(微把持器Linux)撑持操纵的一个地点空间。该架构缺少MMU供应的回护,可是同意Linux运转另外一类处置器。
  选择一个页面来互换存储的历程被称为一个页面置换算法,能够经由过程利用很多算法(最少是比来利用的)来完成。该历程在哀求存储地位时产生,存储地位的页面不在存储器中(在存储器办理单位中无映照)。这个事务被称为一个页面毛病并被硬件(MMU)删除,呈现页面毛病中止后该事务由防火墙办理。该栈的具体申明见。
  Linux供应一个风趣的互换完成,该完成供应很多有效的特征。Linux互换体系同意创立和利用多个互换分区和优先权,这撑持存储设备上的互换条理布局,这些存储设备供应分歧的功能参数(比方,固态磁盘上的一级互换和速率较慢的存储设备上的较年夜的二级互换)。为SSD互换附加一个更高的优先级使其可使用直至耗尽;直到当时,页面才干被写进优先级较低的互换分区。
.地点空间和假造-物理地点映照的元素

  并非一切的页面都合适互换。思索到呼应中止的内核代码大概办理页表和互换逻辑的代码,明显,这些页面决不克不及被换出,因而它们是流动的,大概是永世地驻留在内存中。只管内核页面不必要举行互换,但是用户页面必要,可是它们能够被流动,经由过程mlock(或mlockall)函数来锁定页面。这就是用户空间内存会见函数的目标。假如内核假定一个用户传送的地点是无效的且是可会见的,终极大概会呈现内核严峻毛病(kernelpanic)(比方,由于用户页面被换出,而招致内核中的页面毛病)。该使用程序编程接口(API)确保这些界限情形被妥帖处置。
  内核API
  如今,让我们来研讨一下用户操纵用户内存的内核API。请注重,这触及内核和用户空直接口,而下一部分将研讨其他的一些内存API。用户空间内存会见函数在表1中列出。
表1.用户空间内存会见API
函数形貌access_ok反省用户空间内存指针的无效性get_user从用户空间猎取一个复杂变量put_user输出一个复杂变量到用户空间clear_user扫除用户空间中的一个块,大概将其回零。copy_to_user将一个数据块从内核复制到用户空间copy_from_user将一个数据块从用户空间复制到内核strnlen_user猎取内存空间中字符串缓冲区的巨细strncpy_from_user从用户空间复制一个字符串到内核
  正如您所希冀的,这些函数的完成架构是自力的。比方在x86架构中,您可使用./linux/arch/x86/lib/usercopy_32.c和usercopy_64.c中的源代码找到这些函数和在./linux/arch/x86/include/asm/uaccess.h中界说的字符串。
  当数据挪动函数的划定规矩触及到复制挪用的范例时(复杂VS.会萃),这些函数的感化如所示。
.利用UserSpaceMemoryAccessAPI举行数据挪动

  access_ok函数
  您可使用access_ok函数在您想要会见的用户空间反省指针的无效性。挪用函数供应指向数据块的入手下手的指针、块巨细和会见范例(不管这个地区是用来读仍是写的)。函数原型界说以下:
access_ok( type, addr, size ); 
  type参数能够被指定为VERIFY_READ或VERIFY_WRITE。VERIFY_WRITE也能够辨认内存地区是不是可读和可写(只管会见仍旧会天生-EFAULT)。该函数复杂反省地点多是在用户空间,而不是内核。
  get_user函数
  要从用户空间读取一个复杂变量,可使用get_user函数,该函数合用于复杂数据范例,好比,char和int,可是像布局体这类较年夜的数据范例,必需利用copy_from_user函数。该原型承受一个变量(存储数据)和一个用户空间地点来举行Read操纵:
get_user( x, ptr ); 
  get_user函数将映照到两个外部函数个中的一个。在体系外部,这个函数决意被会见变量的巨细(依据供应的变量存储了局)并经由过程__get_user_x构成一个外部挪用。乐成时该函数前往0,一样平常情形下,get_user和put_user函数比它们的块复制正本要快一些,假如是小范例被挪动的话,应当用它们。
  put_user函数
  您可使用put_user函数来将一个复杂变量从内核写进用户空间。和get_user一样,它承受一个变量(包括要写的值)和一个用户空间地点作为写方针:
put_user( x, ptr ); 
  和get_user一样,put_user函数被外部映照到put_user_x函数,乐成时,前往0,呈现毛病时,前往-EFAULT。
  clear_user函数
  clear_user函数被用于将用户空间的内存块清零。该函数接纳一个指针(用户空间中)和一个型号举行清零,这是以字节界说的:
clear_user( ptr, n ); 
  在外部,clear_user函数起首反省用户空间指针是不是可写(经由过程access_ok),然后挪用外部函数(经由过程内联组装体例编码)来实行Clear操纵。利用带有repeat前缀的字符串指令将该函数优化成一个十分严密的轮回。它将前往不成扫除的字节数,假如操纵乐成,则前往0。
  copy_to_user函数
  copy_to_user函数将数据块从内核复制到用户空间。该函数承受一个指向用户空间缓冲区的指针、一个指向内存缓冲区的指针、和一个以字节界说的长度。该函数在乐成时,前往0,不然前往一个非零数,指出不克不及发送的字节数。
copy_to_user( to, from, n ); 
  反省了向用户缓冲区写进的功效以后(经由过程access_ok),外部函数__copy_to_user被挪用,它反过去挪用__copy_from_user_inatomic(在./linux/arch/x86/include/asm/uaccess_XX.h中。个中XX是32大概64,详细取决于架构。)在断定了是不是实行1、2或4字节复制以后,该函数挪用__copy_to_user_ll,这就是实践事情举行的中央。在破坏的硬件中(在i486之前,WP位在办理形式下不成用),页表能够随时交换,必要将想要的页面流动到内存,使它们在处置时不被换出。i486以后,该历程只不外是一个优化的正本。
  copy_from_user函数
  copy_from_user函数将数据块从用户空间复制到内核缓冲区。它承受一个目标缓冲区(在内核空间)、一个源缓冲区(从用户空间)和一个以字节界说的长度。和copy_to_user一样,该函数在乐成时,前往0,不然前往一个非零数,指出不克不及复制的字节数。
copy_from_user( to, from, n ); 
  该函数起首反省从用户空间源缓冲区读取的才能(经由过程access_ok),然后挪用__copy_from_user,最初挪用__copy_from_user_ll。今后入手下手,依据构架,为实行从用户缓冲区到内核缓冲区的零拷贝(不成用字节)而举行一个挪用。优化组装函数包括办理功效。
  strnlen_user函数
  strnlen_user函数也能像strnlen那样利用,但条件是缓冲区在用户空间可用。strnlen_user函数带有两个参数:用户空间缓冲区地点和要反省的最年夜长度。
strnlen_user( src, n ); 
  strnlen_user函数起首经由过程挪用access_ok反省用户缓冲区是不是可读。假如是strlen函数被挪用,maxlength参数则被疏忽。
  strncpy_from_user函数
  strncpy_from_user函数将一个字符串从用户空间复制到一个内核缓冲区,给定一个用户空间源地点和最年夜长度。
strncpy_from_user( dest, src, n ); 
  因为从用户空间复制,该函数起首利用access_ok反省缓冲区是不是可读。和copy_from_user一样,该函数作为一个优化组装函数(在./linux/arch/x86/lib/usercopy_XX.c中)完成。
  内存映照的其他形式
  下面部分切磋了在内核和用户空间之间挪动数据的办法(利用内核初始化操纵)。Linux还供应一些其他的办法,用于在内核和用户空间中挪动数据。只管这些办法一定可以供应与用户空间内存会见函数不异的功效,可是它们在地点空间之间映照内存的功效是类似的。
  在用户空间,注重,因为用户历程呈现在独自的地点空间,在它们之间挪动数据必需经由某种历程间通讯机制。Linux供应各类形式(好比,动静行列),可是最出名的是POSIX共享内存(shmem)。该机制同意历程创立一个内存地区,然后统一个或多个历程共享该地区。注重,每一个历程大概在其各自的地点空间中映照共享内存地区到分歧地点。因而必要绝对的寻址偏移(offsetaddressing)。
  mmap函数同意一个用户空间使用程序在假造地点空间中创立一个映照,该功效在某个设备驱动程序类中是罕见的,同意将物理设备内存映照到历程的假造地点空间。在一个驱动程序中,mmap函数经由过程remap_pfn_range内核函数完成,它供应设备内存到用户地点空间的线性映照。
  停止语
  本文会商了Linux中的内存办理主题,然后会商了利用这些观点的用户空间内存会见函数。在用户空间和内核空间之间挪动数据并没有外表上看起来那末复杂,可是Linux包括一个复杂的API汇合,跨平台为您办理这个庞大的义务。
</p>
不同版本的Linux命令数量不一样,这里笔者把它们中比较重要的和使用频率最多的命令。

若相依 发表于 2015-1-17 23:59:51

尽量不要提问纯属是扯蛋.学习Linux特别是自己一个人初学入手的时候没人教很困难.当然如果可以的话平时多去买些Linux书...对学习Linux很有帮助.

若天明 发表于 2015-1-21 15:18:42

为什么要学Linux呢?每个人都有不同的看法,下面我说说自己的感想吧。?

再见西城 发表于 2015-1-30 20:23:36

尽量不要提问纯属是扯蛋.学习Linux特别是自己一个人初学入手的时候没人教很困难.当然如果可以的话平时多去买些Linux书...对学习Linux很有帮助.

分手快乐 发表于 2015-2-6 15:53:32

生成新的unispimsp.ksc。”另外得到回复后如果问题解决,向帮助过你的人发个说明,让他们知道问题是怎样解决的。

活着的死人 发表于 2015-2-16 23:31:12

通过自学老师给的资料和向同学请教,掌握了一些基本的操作,比如挂载优盘,编译程序,在Linux环境下运行,转换目录等等。学了这些基础才能进行下面的模拟OS程序。?

爱飞 发表于 2015-3-5 13:58:05

即便是非英语国家的人发布技术文档,Linux也都首先翻译成英语在国际学术杂志和网络上发表。

柔情似水 发表于 2015-3-12 08:06:55

掌握硬件配置,如显卡,声卡,网卡等,硬件只要不是太老或太新一般都能被支持,作为一名Linux系统管理员建议多阅读有关硬件配置文章,对各种不支持或支持不太好的硬件有深刻的了解。

小女巫 发表于 2015-3-19 19:05:45

Linux只是个内核!这点很重要,你必须理解这一点。只有一个内核是不能构成一个操作系统的。
页: [1]
查看完整版本: 带来一篇从 Linux 内核会见用户空间内存