Q:一直知道内核和用户态的数据交互前都需要 校验地址的合法性,一般都用copy_from/to_user完成数据拷贝,那么为什么要这样呢??

A:看了一些blog以及Stack Overflow 主要说的是安全性:

Linux Kernel: How does copy_to_user work?
Why can't you just call, say, memcpy? Two reasons.
One, the kernel is capable of writing to any memory. User process's can't. copy_to_user needs to check dst to ensure it is accessible and writable by the current process.
Two, depending on the architecture, you can't simply copy data from kernel to user-space. You might need to do some special setup first, invalidate certain caches, or use special operations.
而内核可以访问任意内存。copy_to_user需要 通过当前进程来 检查目标的可写权限   (而用户 进程无法检查内核空间目标地址的 写权限 )
同时:检查指针所指的内存是否有效

 
设想一下:我们在写file_opeteration的write函数时:write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)/read(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
1、buf地址不合法
2、buf地址合法,内核还没有给它映射物理地址
3、如果buf是个一个内核地址, read的时候不就是内核到内核的拷贝么??
 
所以为了解决上述问题就有了copy_xx_user-----------
  • 地址检查,不合法返回
  • copy_xx_user 使用精心布置的访存汇编实现,并指这个汇编指令所在的地址全部登记起来(称为extable表)。出现2时------>会发生缺页异常,进入内核do_page_fault流程;然后检查出错的PC地址是不是早已在extable登记好的,如果是,同表示该缺页异常是copy_from_user/copy_to_user函数产生的。最后才检查该地址是否为该进程的合法地址,如果是则分配物理页并处理,否则就是非法地址,把进程给杀死(发送sigsegv信号)


 
顺便有几个疑问??参考:https://www.cnblogs.com/alantu2018/p/8527077.html   http://www.mysixue.com/?p=114#33   这些blog写的详细
1、为什么会产生page fault?
2、发生缺页的上下文是否可以位于内核态
有可能在内核态,但这种情况下,发生缺页的地址只能位于用户态地址空间,而且也只能为exceptions table中预先定义好的异常,如果exceptions table中没有预先定义的处理,或者缺页的地址位于内核态地址空间,则表示错误,进入oops流程。通常属于异常,会导致oops。、、-----copy_xx_user干的就是这事
    /*
* If we're in an interrupt, have no user context or are running
* in an atomic region then we must not take the fault:
*/
if (unlikely(in_atomic() || !mm)) {mm 为空表示内核线程
bad_area_nosemaphore(regs, error_code, address);
return;
}

3、发生缺页的地址是否可以位于内核态地址空间----
有可能,发生缺页的内核态地址仅可能位于vmalloc区;在使用Vmalloc分配物理内存时,确实进行了映射,创建了页表项。
但是,其修改的仅为内核的主内核页表,并没有更新相关进程的页表;进程访问时,相关进程的页表中并没有Vmalloc分配内存相应的页表项,所以会触发page fault
//该分支表明发生缺页时是发生在访问内核空间时
if (unlikely(address >= TASK_SIZE)) {
//表示 代码是在内核态访问内核态不存在 的地址,转到vmalloc_fault处理分支,可能是访问了不连续的内核页面
if (!(error_code & 5))
goto vmalloc_fault;
//做相应出错处理
goto bad_area_nosemaphore;
}

关于内存管理文章见连接:

https://files.cnblogs.com/files/codestack/fp%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86.zip

 
1、内核页表中的内容为所有进程共享,每个进程都有自己的“进程页表”,“进程页表”中映射的线性地址包括两部分:
用户态
内核态
其中,内核态地址对应的相关页表项,对于所有进程来说都是相同的(因为内核空间对所有进程来说都是共享的),而这部分页表内容其实就来源于“内核页表”,即每个进程的“进程页表”中内核态地址相关的页表项都是“内核页表”的一个拷贝。
2、“内核页表”由内核自己维护并更新,在vmalloc区发生page fault时,将“内核页表”同步到“进程页表”中。以32位系统为例,内核页表主要包含两部分:
线性映射区
vmalloc区
其中,线性映射区即通过TASK_SIZE偏移进行映射的区域,对32系统来说就是0-896M这部分区域,映射对应的虚拟地址区域为TASK_SIZE-TASK_SIZE+896M。这部分区域在内核初始化时就已经完成映射,并创建好相应的页表,即这部分虚拟内存区域不会发生page fault。
vmalloc区,为896M-896M+128M,这部分区域用于映射高端内存,有三种映射方式:vmalloc、固定、临时,这里就不像述了。。
以vmalloc为例(最常使用),这部分区域对应的线性地址在内核使用vmalloc分配内存时,其实就已经分配了相应的物理内存,并做了相应的映射,建立了相应的页表项,但相关页表项仅写入了“内核页表”,并没有实时更新到“进程页表中”,内核在这里使用了“延迟更新”的策略,将“进程页表”真正更新推迟到第一次访问相关线性地址,发生page fault时,此时在page fault的处理流程中进行“进程页表”的更新:

都知道的copy_from_user的更多相关文章

  1. 3年Java开发都知道的Redis数据结构和通用命令

    Redis的数据结构 Redis支持多种不同的数据结构,包括5种基础数据结构和几种比较复杂的数据,这些数据结构可以满足不同的应用场景. 五种基础数据结构 String:字符串,是构建其他数据结构的基础 ...

  2. What every computer science major should know 每一个计算机科学专业的毕业生都应该都知道的

    Given the expansive growth in the field, it's become challenging to discern what belongs in a modern ...

  3. C# 范型约束 new() 你必须要知道的事

    C# 范型约束 new() 你必须要知道的事 注意:本文不会讲范型如何使用,关于范型的概念和范型约束的使用请移步谷歌. 本文要讲的是关于范型约束无参构造函数 new 的一些底层细节和注意事项.写这篇文 ...

  4. 每个极客都应该知道的Linux技巧

    每个极客都应该知道的Linux技巧 2014/03/07 | 分类: IT技术 | 0 条评论 | 标签: LINUX 分享到:18 本文由 伯乐在线 - 欣仔 翻译自 TuxRadar Linux. ...

  5. 隔壁小孩都要知道的Drupal配置

    i春秋作家:Arizona 原文来自:隔壁小孩都要知道的Drupal配置 隔壁小孩都要知道的Drupal配置 Drupal是一个开源的PHP内容管理系统,具有相当复杂的架构.它还具有强大的安全模型.感 ...

  6. PDB文件:每个开发人员都必须知道的 PDB Files

    PDB文件:每个开发人员都必须知道的   PDB Files: What Every Developer Must Knowhttp://www.wintellect.com/CS/blogs/jro ...

  7. 每一个JavaScript开发者都应该知道的10道面试题

    JavaScript十分特别.而且差点儿在每一个大型应用中起着至关关键的数据.那么,究竟是什么使JavaScript显得与众不同,意义非凡? 这里有一些问题将帮助你了解其真正的奥妙所在:   1.你能 ...

  8. 每个开发者都应该知道的SOLID原则

    每个开发者都应该知道的SOLID原则 单一职责原则(SRP) 它为什么违反了 SRP? 这种设计将来会带来什么问题? 开闭原则(OCP) 如何使它(AnimalSound)符合 OCP? 里氏替换原则 ...

  9. 程序员必须要知道的Hadoop的一些事实

    程序员必须要知道的Hadoop的一些事实.现如今,Apache Hadoop已经无人不知无人不晓.当年雅虎搜索工程师Doug Cutting开发出这个用以创建分布式计算机环境的开源软...... 1: ...

随机推荐

  1. Oracle函数总结

    <Trunc()> 描       述(实际应用):截取小数或者日期整数 简      介:https://baike.baidu.com/item/trunc/9657216?fr=al ...

  2. 【二分图】HEOI2012 朋友圈

    题目内容 洛谷链接 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着. 一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大 ...

  3. 【图论】HDU 5961 传递

    题目内容 题目链接 我们称一个有向图G是传递的当且仅当对任意三个不同的顶点a,若G中有 一条边从a到b且有一条边从b到c ,则G中同样有一条边从a到c. 我们称图G是一个竞赛图,当且仅当它是一个有向图 ...

  4. python 爬虫 循环分页

    import osfrom time import sleepimport fakerimport requestsfrom lxml import etreefake = faker.Faker() ...

  5. Jira 8.5.1 安装教程

    Jira安装教程 一.CentOS设置 1. 更换阿里源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/rep ...

  6. 分布式事务说的的2PC、3PC、TCC是啥

    目录 2PC(Two Phase Commit) 3PC(Three Phase Commit) TCC(Try-Confirm-Cancel) 2PC(Two Phase Commit) 顾名思义, ...

  7. Pytest学习(二) - 断言的使用

    一.前言 学习pytest总会习惯性的和unittest对比使用,自然就断言pytest和unittest也是有些区别的. 二.断言对比 unittest 断言 assertEqual(a, b) # ...

  8. Anderson《空气动力学基础》5th读书笔记 第2记——流体静力学初步

    与物体在水中受到水的浮力一样,空气中的物体也会受到空气的浮力,但由于这个浮力往往比较小,实际中的很多问题我们常常将它忽略,而对于像热气球这样的靠空气的浮力产生升力的飞行器来说,空气的浮力是不能忽略的. ...

  9. codevs1298, hdu1392 (凸包模板)

    题意: 求凸包周长. 总结: 测试模板. 代码: #include <iostream> #include <cstdio> #include <cstring> ...

  10. 10 个 Python 初学者必知编码小技巧

    技巧 #1 字符串翻转 a = "codementor">>> print "Reverse is",a[::-1]翻转后的结果为 rotne ...