1. msr分区移动到硬盘后部
MSR分区(Microsoft Reserved Partition,缩写MSR)即Microsoft 保留 (MSR) 分区。是每个 在GUID 分区表 (GPT) 上的 Windows操作系统(Windows 7以上)都要求的分区。系统组件可以将 MSR 分区的部分分配到新的分区以供它们使用。
例如,将基本 GPT 磁盘转换为动态磁盘后,系统分配的 MSR 分区将被用作“逻辑磁盘管理器”(LDM) 元数据分区。
中文名
MSR分区
外文名
Microsoft Reserved Partition
缩写
MSR
定义
Microsoft 保留 (MSR) 分区
平台
Windows
区分举例
MSR 分区的大小会因 GPT 磁盘的大小不同而发生变化。对于小于 16 GB 的磁盘,MSR 分区为 32 MB。对于大于 16 GB 的磁盘,MSR 分区为 128 MB。MSR 分区在“磁盘管理”中不可见,在Diskpart、Diskgenius等磁盘工具里可见,但是用户无法在 MSR 分区上存储或删除数据。
用WIN8系统安装版分区时,系统自动划分出“分区1、2、3”,它们是Win8的特有分区。其中300MB为恢复区,100MB为系统分区,128MB为MSR分区。[1]
对于在GPT磁盘上的Windows操作系统,MSR分区不是必须的,可以删除不受影响。
MSR分区的创建,可以使用此命令:
create partition msr [size=<n>] [offset=<n>] [noerr],单位为MB,
实例,如果要创建一个128MB的MSR分区:
create partition msr size=128
分享你的世界
我要分享见解,
点击发布
纠错
参考资料
[1] Win8实测.ZOL.COM.CN [引用日期2012-10-31]
秦皇岛军队文职报名通道开启,名额有限,速来报名!
文职广告
秦皇岛负债逾期 无力偿还 信用卡逾期高额利息怎么办?|
全国债务逾期咨询中心广告
纵横卓创组装电脑旗舰店 升级包 购买主机修改、加装、升级配置专用连接 按需选配,请勿乱拍 2T机械升级成4T机械
¥200 元
纵横卓创组装电脑旗舰店 升级包 购买主机修改、加装、升级配置专用连接 按需选配,请勿乱拍 1T机械升级成4T机械
¥300 元
纵横卓创组装电脑旗舰店 升级包 购买主机修改、加装、升级配置专用连接 按需选配,请勿乱拍 1T机械升级成2T机械
¥100 元
京东广告
大家还在搜
移动硬盘分区
msr
esp和msr分区
分区
广告
实力唱将,魅力舞姬,超多主播在YY直播等你
相关推荐
MSR分区_相关术语
系统保留分区用于存放系统引导文件
查看词条
4K对齐高级格式化的分区技术
查看词条
移动硬盘分区将一个硬盘分成逻辑区
查看词条
系统盘无需用户干预的程序
查看词条
盘符磁盘存储设备的标识符
查看词条
硬盘对拷盘对盘的数据克隆
查看词条
低级格式化格式化之前的一件工作
查看词条
BIOS中英文对照表电脑开机设置中英对照
查看词条
磁盘清理空间上提高读取性能
查看词条
词条贡献者
该词条共有30人参与编辑,查看全部
词条有帮助,感谢贡献者
意见反馈权威合作网络协议
网络是免费编辑平台,无收费代编服务 | 详情
Bai 京ICP证030173号
编辑
传视频
TA说
在
2. H3C MSR20-40 命令行里如何配置固定外网IP上网 DHCP需要开起来 具体命令是怎样的
首先要确定你的接入方式,用的是什么协议,是pppoe协议的还是专线连接的。。
如果是pppoe协议的就得有相应的封装模块,如果是专线,直接把网线接到rj-45网口上就行;
然后登陆路由器命令行,进入相应的wan端口配置地址,通过在外网口配置nat基本就OK了。
以下配置假设Ethernet0/0为局域网接口,Ethernet0/1为外网口。
1、配置内网接口(Ethernet0/0):
[MSR20-20] interface Ethernet0/0
[MSR20-20- Ethernet0/0]ip add 192.168.1.1 24
2、使用动态分配地址的方式为局域网中的PC分配地址
[MSR20-20]dhcp server ip-pool 1
[MSR20-20-dhcp-pool-1]network 192.168.1.0 24
[MSR20-20-dhcp-pool-1]dns-list 202.96.134.133
[MSR20-20-dhcp-pool-1] gateway-list 192.168.1.1
3、配置nat
[MSR20-20]nat address-group 1 公网IP 公网IP
[MSR20-20]acl number 3000
[MSR20-20-acl-adv-3000]rule 0 permit ip
4、配置外网接口(Ethernet0/1)
[MSR20-20] interface Ethernet0/1
[MSR20-20- Ethernet0/1]ip add 公网IP
[MSR20-20- Ethernet0/1] nat outbound 3000 address-group 1
加默缺省路由
[MSR20-20]route-stac 0.0.0.0 0.0.0.0 外网网关
总结:
在2040路由器下面,
配置外网口,
配置内网口,
配置acl 作nat,
一条默认路由指向电信网关. ok!
3. 家用车买宝来好还是朗逸好具体些。。
朗逸好很多部位的保护上达到满分。我们可以从官方的说明上得到数据:朗逸的正面100%重叠刚性壁障碰撞试验得分达到了13.67分,其中头部、颈部和大腿方面的保护都得到了满分;在40%正面偏置碰撞试验中,朗逸得到了16分的满分成绩,而在侧面碰撞试验,朗逸的腹部和骨盆碰撞结果都得到了4分的满分成绩,此项测试的得分也达到了15.74分,仅差0.26分就可以获得满分,这一成绩是C-NCAP有史以来A类乘用车中的最好成绩。 1在主动安全系统方面,朗逸采用了Teves公司最新一代的MK70 MABS系统,更好地结合了ABS、EBD、MSR发动机阻力矩控制和MASR发动机介入的牵引力控制,大大降低车辆失控的可能性。刹车片采用了NAO陶瓷材质,配有米其林轮胎,非常适合车速较低的中国道路,而且还能显著降低制动噪音,在低温状况下,也延长了制动盘的寿命,降低了保养成本。 2此外,当轮胎压力低于标准超过25-30%时,轮胎气压监控系统TPR就通过仪表板中的警告灯提醒驾驶员,避免行车威胁。朗逸还有一个同级车中独有的装备,当ABS判断出驾驶员采取了紧急制动时,紧急制动报警装置会打开车尾双跳灯,以提醒后方车辆及时作出反应,防止追尾。 在工艺应用上保持了为了制造高质量的LAVIDA朗逸,上海大众建造了全新的符合大众集团最新康采恩标准的LAVIDA朗逸车身生产线,增加了61台工业机器人,包含2台激光焊接机器人,并首次引入了奥迪柔性制造中心技术,大量使用了更节能环保的一体式中频点焊设备,以及国际上最先进的机器人滚折边技术和中频凝胶技术。大众备受赞誉的激光焊接工艺此次也应用在了LAVIDA朗逸上,其激光焊缝总长度近10m。 3另外,为了打造LAVIDA朗逸的完美车身,此次上海大众还采用国际先进的模具设计和制造技术,全新开发了LAVIDA朗逸冲压模具,以确保零件尺寸的精确和表面质量的优良。与此同时,在LAVIDA朗逸的生产过程中,还大量应用了整体冲压成形技术,采用尽量大尺寸的合理的车身总成分块,从而加强了车身的整体性,不仅使车身刚度得到加强,在碰撞时具有更高的安全性,也提高了车身装配尺寸精度,使产品更加精细美观。高分秘密在于精良的制造工艺 首先是冲压工艺,作为生产制造的第一步,冲压工艺在很大程度上决定了产品品质的高低。据悉,此次上海大众采用国际先进的模具设计和制造技术,全新开发了朗逸冲压模具,并且生产过程中,还大量应用了整体冲压成形技术,采用尽量大尺寸的合理的车身总成分块,从而加强了车身的整体性。这种设计不仅使车身刚度得到加强,在碰撞时具有更高的安全性,还提高了车身装配尺寸精度,使产品更加精细美观。另外,在与车身安全性密切相关的门板防撞板、中柱内板等安全件上,上海大众还应用了热成形工艺。热成形工艺本来是用于航空航天领域的一种技术,主要用于加工在常温下不容易成形的超高强度材料,目前国内仅有极少数汽车厂家使用这种高端技术。 冲压工艺主要是为了塑造身板,接下来就是车身制造,了确保朗逸的车身质量,此次上海大众依照大众集团最新康采恩标准,对朗逸车身生产线进行了全面提升,增加了61台工业机器人,包含2台激光焊接机器人,并首次引入了奥迪柔性制造中心技术,大量使用了更节能环保的一体式中频点焊设备,以及国际上最先进的机器人滚折边技术和中频凝胶技术。 据介绍,大众备受赞誉的激光焊接工艺此次在朗逸上也有广泛应用,其激光焊缝总长度近10米,这在同级别车里是不多见的,甚至可以和一般的中高级轿车相媲美。 轿车制造过程中最难安排、最难控制的就是总装工艺,轿车的密封性和驾驶过程中的噪音大小都取决于总装工艺。为了将朗逸打造成名副其实的精品轿车,此次上海大众也采用高标准严格把好总装这一关。在朗逸的装配过程中,上海大众使用了大量高精度电动拧紧工具,并实现重要螺栓拧紧数据上网,以确保装配精度和 100%合格率。这种严密的数据记录方式一般只用于发动机装配,在总装生产线上广泛使用这项技术使上海大众在国内同行业处于绝对领先水平。朗逸还采用了驾驶舱模块化装配,大大提高了整车的刚度和密封性、安全性,减少了行车过程中的噪音,并能经受住同行业中时间最长的雨淋测试的考验。 众所周知,日系车在汽车碰撞测试中屡创佳绩,常常获得五星的美誉,但这毕竟是碰撞试验,现实中我们目睹更多的情况却是日系车在触目惊心的交通事故中被撞得面目全非,甚至出现一分为二的惨像,日系车津津乐道的吸能这时也通常哑然失语,开始羡慕车身强度惊人的德系车。还是那句话,主被动安全配置要重视,精益求精的制造工艺更要提倡,不过说到底,自己养成良好的驾驶习惯是关键。 人性化 LAVIDA朗逸的空间和动力虽然值得称道,不过充满中国元素的内饰更能体现上海大众的造车理念,那就是为普通消费者制造高品质的大众车。与外形设计一样,LAVIDA朗逸的内饰设计也是全新的。运用大众的设计理念,结合中国消费者的审美观念,上海大众的本土设计团队设计出了更加贴近中国市场的内饰。 LAVIDA朗逸的内饰保持了大众车系整洁、严谨的设计理念,同时融入中国消费者追求高级的思想,在形体设计上采用了以曲线和圆形为主的元素,这与大众车系方正而传统的设计,有很大的不同,没有了老式的呆板增加了几分时尚高雅,给人眼前一亮的感觉。 朗逸的不少小细节做得很细致,让我有"惊喜"的感觉。”一位在上海大众4S店中做保养的朗逸车主这样评价自己的爱车。长、宽、高分别为4608mm、1743mm和1465mm的LAVIDA,其轴距达到了2610mm。宽敞的空间让驾驶者和乘坐者倍感舒适。而朗逸外观车灯上的设计科技感和时尚感非常强,在实用性上也超越了不少车型,这更让不少购车者“一见钟情”。 内饰上,朗逸摆脱了德式风格的古板和严肃,添加了不少充满情趣的中式风格。在配置方面,2.0L的后视镜、三辐式多功能方向盘等标配让人感到满意;USB接口和MP3功能、真皮打孔座椅等诸多配置也都显出不同一般的细致;定速巡航、倒车雷达则主要为安全驾驶考虑,非常实用和必要。转向灯后延 延伸转向灯的长度,能够更为有效的提醒后面的行人及车辆。这个细节可能会被很多消费者所忽视,不过它的作用却不可小觑,尤其是在晚上转弯时会非常实用,过往车辆有更多机会看到转向灯,在安全性方面就多了一份保险。倒车雷达 当距离障碍物1.2m时会发出“嘀嘀”声,当车辆与障碍物距离缩小至0.3m时将转变成连续音。如果倒车时车速大于15Km/h,那将出现雷达无法识别障碍物的情况。倒车雷达对于刚从驾校毕业的菜鸟车主来说可谓得力助手,当车子在小区里的停车位上稳当挺好后,想必会有小小的成就感吧。自动感应雨刷 雨刷调节按钮一般在方向盘上,驾驶员可以根据雨量的大小自己调节,遇到雨雪等恶劣天气时的确有些麻烦;而雨刷自动感应,通过车内后视镜下面的一个感应器,来控制雨刷的速度。雨越大,雨刷速度就越大,非常方便。 后备箱锁的设计 后备箱没有锁眼,所以通过撬坏锁芯的方法偷盗物品在朗逸上行不通。开启后备箱只能通过遥控钥匙或者驾驶员门上的开启按钮。值得一提的是,朗逸在后备箱内还设置了一个逃生拉线,如果你被困在后备箱内,可以通过拉动这个拉线从内部打开后备箱逃生。尽管这个功能正常情况下不大用到,不过有备无患啦。 发动机下护板 行车时防止石砺飞入机舱室,一般来说,家用车辆的底盘都不会很高,这样的结果是为了降低汽车的重心从而获得更好的稳定性,不过弊端就是遇到坎坷的道路会损坏底盘,而发动机护板就能起到很好的保护作用。另外平滑的地盘让气流通过更加顺畅,减少阻力的同时还能在一定程度上保证行车时车身更加稳定。 音响系统 朗逸配置的虚拟6碟CD/MP3播放机,可以通过抓轨技术将CD-AUDIO格式盘片的音乐存入车辆内置的FLASH存储介质中,可存储播放音乐大 7.5小时。当您听完1/4盘CD,整张CD的内容就已经存储完毕。支持SD、USB、AUX接口,确保了各种媒体文件的方便导入,以上介质中所能被识别的播放文件格式包括ISO-MPEG、AUDIO、LAYER-3(MP3)和WINDOWS MEDIA AUDIO(WMA)等,对于喜欢音乐、追求时尚的潮人很有吸引力哟。 此外,除了不错的音响系统,朗逸还配备了意大利Pasubio高透气真皮座椅,而车内甲醛含量控制在1mg/100g,比国家室内空气质量标准严格9倍。 环保 Tiptronic 6挡手自动一体变速箱不仅使得朗逸的动力输出表现出色,而且也起到了节油环保的作用。这款6速Tiptronic手/自动一体变速箱的动态换挡程序可提供D档(标准型-经济省油)和S档(运动型-动力澎湃)两种不同换档模式。它可以根据驾驶者提出的驾驶要求自行分析行驶情况,自动寻找与行驶条件相匹配的换档时机。当然,如果想追求更此次驾乘感受的用户也可以将自动挡转换为手动挡。 在Tiptronic 6速变速箱的设定中,不用超过60 km/h车主就能享受到第6档齿轮的省油体验,而传统4速自动变速箱可能还只工作在第3档。发动机转速的差异决定了两者油耗成绩的高低。据调查,朗逸车主对朗逸的油耗情况基本满意,有一位接受采访的车主说当他驾驶2.0L自动版车型在“全程满载并开启空调的国道路段”行驶时,平均油耗约为 8L/100km左右。 除此之外,当驾驶者使用“最佳化模式”时,这款变速箱可以更合理的利用发动机在不同转速下的动力输出,即充分发挥出其动力潜能。而在换档模式自动学习功能的帮助下,换档时上下档位间冲击小,使得驾驶更平稳舒适。 检举 回答人的补充 2009-10-31 19:07 13万的裸车还是蛮多的,一般家用推荐朗逸,虽说平台比较落后,当时毕竟挂着大众的牌子,做工,安全方面还是可以的!如果喜欢运动风格的,推荐两厢福克斯,自己家就是09款两厢福克斯1.8AT。福克斯虽说是两厢车,当时空间还是不错的,特别宽度,比琪达,思域都要宽,甚至可以跟B级车有的一拼,09款的福克斯无论在外型内饰方面都有了不小的提高,对于这点还是比较满意的。还有底盘是采用跟沃尔沃S40同一平台的技术生产出来的,是这个价位性价比最高的底盘了!操控跟悬挂都是福克斯的主打绝对不会另车主失望。虽说日系车省油,但是付出的代价往往比较大,很多日系车连防撞梁都没有,底盘的钢条更是细得可怕!安全方面福克斯做得还是不错的! 检举 回答人的补充 2009-10-31 19:13 主要建议以下几款
标致307,宝来,福克斯,世嘉, 速腾(以上包括两、三厢的)
以上几款是A级车真正的王牌车型
都是欧美车型,安全、操控很好。
底盘调校,悬挂,刹车很好、
使用的钢材很好,品质保证啊。
特别是钢材,比如日本车就是一超薄铁皮车
还有刹车,悬挂啊差别很明显
油耗在这个级别不是最大的问题,当然以上几个福克斯要相对油耗高点
其他的都很合适,相比一般的日本车也就高1个样子。
买车啊,还是欧洲的好
主要是安全,而且欧洲车造车的工艺、技术和理念,是其他的完全比不了的 宝来简洁,不过简洁的似乎有点单调了,这个还是得看个人审美倾向吧,其实新款也没有以前好看!外观是不一样,就是钣金,车漆和老宝来都差很多,更别提里面的内饰,真皮座椅的品质,简直不是一个档次的。老宝来是最好的(已停产),现在的新宝来我不建议买!如果您喜欢宝来,趁宝来经典还没停产,赶紧买宝来经典吧,还能找到原来宝来的影子【透露着微微的旧时代好莱坞电影的感觉(个人体会)】。现在家用车刮运动风啊,运动轿跑大受欢迎啊,一则是外观动感、帅气、时尚,二则是动力充沛、配置丰富,推荐款性价比高的国产自主车:比亚迪L3吧,顶着年度最受欢迎新车的光环,很是闪耀。
4. 安装Windows 8 分区时 系统分区 恢复 MSR(保留)
MSR分区(Microsoft Reserved Partition,缩写MSR)即Microsoft 保留 (MSR) 分区。
MSR分区(Microsoft Reserved Partition,缩写MSR)即Microsoft 保留 (MSR) 分区。是每个 在GUID分区表(GPT) 上的 Windows操作系统(windows7以上)都要求的分区。
系统组件可以将 MSR 分区的部分分配到新的分区以供它们使用。例如,将基本 GPT 磁盘转换为动态磁盘后,系统分配的 MSR 分区将被用作“逻辑磁盘管理器”(LDM) 元数据分区。
5. 汽车OBD中的MI是指什么
OBD作为一个专有名词的缩写,其全称为On Board Diagnostics,中文的意思是:车载自动诊断系统。这套系统能在汽车运行过程中实时监测发动机电控系统及车辆的其它功能模块的工作状况,如有发现工况异常,则根据特定的算法判断出具体的故障,并以诊断故障代码(DTC,Diagnostic Trouble Codes)的形式存储在系统内的存储器上。系统自诊断后得到的有用信息可以为车辆的维修和保养提供帮助,维修人员可以利用汽车原厂专用仪器读取故障码,从而可以对故障进行快速定位,以便于对车辆的修理,减少人工诊断的时间。
6. 宝马车的ASC是什么意思
一个名词而已。。 ABS:电子刹车防抱死控制,车速在35km/h以上,刹车时作用。 ASC:加速防滑刹车控制,车辆起步时及以后任何时刻进入戒备作用状态。 MSR:发动机扭力控制,ASC动作时,控制发动机动力下降。 ECD:电子刹车力分配。 DBC:动态刹车控制。 DSC:电子刹车车身稳定系统。 新的宝马车E38、E39、E46、E65/E66、E53车型上均安装ASC或DSC系统。 ASC系统监测四轮车速及节气门信号,用以控制发动机扭力输出。 ASC+T控制系统在ABS系统功能上加装MSR功能,用以监测行驶中车轮转速不一致,对自动调节刹车力及发动机动力输出。此功能又同时可以通过ASC开关解除。 DSC控制系统在ASC控制功能上增加对车辆水平横向移动及甩尾旋转运动时的自动监测功能。通过转向角度传感器、横向加速传感器、旋转加速传感器监测,调节四轮刹车力自动分配动作降低发动机扭矩及变速箱减档操作。达到车辆动态行驶中车身稳定功能。 EMF:电子停车驻动系统7. CPU和CPUID是什么关系
在 Linux 2.4 内核中,用户态 Ring3 代码请求内核态 Ring0 代码完成某些功能是通过系统调用完成的,而系统调用的是通过软中断指令(int 0x80)实现的。在 x86 保护模式中,处理 INT 中断指令时,CPU 首先从中断描述表 IDT 取出对应的门描述符,判断门描述符的种类,然后检查门描述符的级别 DPL 和 INT 指令调用者的级别 CPL,当 CPL<=DPL 也就是说 INT 调用者级别高于描述符指定级别时,才能成功调用,最后再根据描述符的内容,进行压栈、跳转、权限级别提升。内核代码执行完毕之后,调用 IRET 指令返回,IRET 指令恢复用户栈,并跳转会低级别的代码。
其实,在发生系统调用,由 Ring3 进入 Ring0 的这个过程浪费了不少的 CPU 周期,例如,系统调用必然需要由 Ring3 进入 Ring0(由内核调用 INT 指令的方式除外,这多半属于 Hacker 的内核模块所为),权限提升之前和之后的级别是固定的,CPL 肯定是 3,而 INT 80 的 DPL 肯定也是 3,这样 CPU 检查门描述符的 DPL 和调用者的 CPL 就是完全没必要。正是由于如此,Intel x86 CPU 从 PII 300(Family 6,Model 3,Stepping 3)之后,开始支持新的系统调用指令 sysenter/sysexit。sysenter 指令用于由 Ring3 进入 Ring0,SYSEXIT 指令用于由 Ring0 返回 Ring3。由于没有特权级别检查的处理,也没有压栈的操作,所以执行速度比 INT n/IRET 快了不少。
不同系统调用方式的性能比较:
下面是一些来自互联网的有关 sysenter/sysexit 指令和 INT n/IRET 指令在 Intel Pentium CPU 上的性能对比:
表1:系统调用性能测试测试硬件:Intel® Pentium® III CPU, 450 MHzProcessor Family: 6 Model: 7 Stepping: 2
用户模式花费的时间 核心模式花费的时间
基于 sysenter/sysexit 指令的系统调用 9.833 microseconds 6.833 microseconds
基于中断 INT n 指令的系统调用 17.500 microseconds 7.000 microseconds
数据来源:[1]
数据来源:[2]
表2:各种 CPU 上 INT 0x80 和 SYSENTER 执行速度的比较
CPU Int0x80 sysenter
Athlon XP 1600+ 277 169
800MHz mode 1 athlon 279 170
2.8GHz p4 northwood ht 1152 442
上述数据为对 100000 次 getppid() 系统调用所花费的 CPU 时钟周期取的平均值
数据来源[3]
自这种技术推出之后,人们一直在考虑在 Linux 中加入对这种指令的支持,在 Kernel.org 的邮件列表中,主题为 "Intel P6 vs P7 system call performance" 的大量邮件讨论了采用这种指令的必要性,邮件中列举的理由主要是 Intel 在 Pentium 4 的设计上存在问题,造成 Pentium 4 使用中断方式执行的系统调用比 Pentium 3 以及 AMD Athlon 所耗费的 CPU 时钟周期多上 5~10 倍。因此,在 Pentium 4 平台上,通过 sysenter/sysexit 指令来执行系统调用已经是刻不容缓的需求。
sysenter/sysexit 系统调用的机制:
在 Intel 的软件开发者手册第二、三卷(Vol.2B,Vol.3)中,4.8.7 节是关于 sysenter/sysexit 指令的详细描述。手册中说明,sysenter 指令可用于特权级 3 的用户代码调用特权级 0 的系统内核代码,而 SYSEXIT 指令则用于特权级 0 的系统代码返回用户空间中。sysenter 指令可以在 3,2,1 这三个特权级别调用(Linux 中只用到了特权级 3),而 SYSEXIT 指令只能从特权级 0 调用。
执行 sysenter 指令的系统必须满足两个条件:1.目标 Ring 0 代码段必须是平坦模式(Flat Mode)的 4GB 的可读可执行的非一致代码段。2.目标 RING0 堆栈段必须是平坦模式(Flat Mode)的 4GB 的可读可写向上扩展的栈段。
在 Intel 的手册中,还提到了 sysenter/sysexit 和 int n/iret 指令的一个区别,那就是 sysenter/sysexit 指令并不成对,sysenter 指令并不会把 SYSEXIT 所需的返回地址压栈,sysexit 返回的地址并不一定是 sysenter 指令的下一个指令地址。调用 sysenter/sysexit 指令地址的跳转是通过设置一组特殊寄存器实现的。这些寄存器包括:
SYSENTER_CS_MSR - 用于指定要执行的 Ring 0 代码的代码段选择符,由它还能得出目标 Ring 0 所用堆栈段的段选择符;
SYSENTER_EIP_MSR - 用于指定要执行的 Ring 0 代码的起始地址;
SYSENTER_ESP_MSR-用于指定要执行的Ring 0代码所使用的栈指针
这些寄存器可以通过 wrmsr 指令来设置,执行 wrmsr 指令时,通过寄存器 edx、eax 指定设置的值,edx 指定值的高 32 位,eax 指定值的低 32 位,在设置上述寄存器时,edx 都是 0,通过寄存器 ecx 指定填充的 MSR 寄存器,sysenter_CS_MSR、sysenter_ESP_MSR、sysenter_EIP_MSR 寄存器分别对应 0x174、0x175、0x176,需要注意的是,wrmsr 指令只能在 Ring 0 执行。
这里还要介绍一个特性,就是 Ring0、Ring3 的代码段描述符和堆栈段描述符在全局描述符表 GDT 中是顺序排列的,这样只需知道 SYSENTER_CS_MSR 中指定的 Ring0 的代码段描述符,就可以推算出 Ring0 的堆栈段描述符以及 Ring3 的代码段描述符和堆栈段描述符。
在 Ring3 的代码调用了 sysenter 指令之后,CPU 会做出如下的操作:
1. 将 SYSENTER_CS_MSR 的值装载到 cs 寄存器
2. 将 SYSENTER_EIP_MSR 的值装载到 eip 寄存器
3. 将 SYSENTER_CS_MSR 的值加 8(Ring0 的堆栈段描述符)装载到 ss 寄存器。
4. 将 SYSENTER_ESP_MSR 的值装载到 esp 寄存器
5. 将特权级切换到 Ring0
6. 如果 EFLAGS 寄存器的 VM 标志被置位,则清除该标志
7. 开始执行指定的 Ring0 代码
在 Ring0 代码执行完毕,调用 SYSEXIT 指令退回 Ring3 时,CPU 会做出如下操作:
1. 将 SYSENTER_CS_MSR 的值加 16(Ring3 的代码段描述符)装载到 cs 寄存器
2. 将寄存器 edx 的值装载到 eip 寄存器
3. 将 SYSENTER_CS_MSR 的值加 24(Ring3 的堆栈段描述符)装载到 ss 寄存器
4. 将寄存器 ecx 的值装载到 esp 寄存器
5. 将特权级切换到 Ring3
6. 继续执行 Ring3 的代码
由此可知,在调用 SYSENTER 进入 Ring0 之前,一定需要通过 wrmsr 指令设置好 Ring0 代码的相关信息,在调用 SYSEXIT 之前,还要保证寄存器edx、ecx 的正确性。
如何得知 CPU 是否支持 sysenter/sysexit 指令
根据 Intel 的 CPU 手册,我们可以通过 CPUID 指令来查看 CPU 是否支持 sysenter/sysexit 指令,做法是将 EAX 寄存器赋值 1,调用 CPUID 指令,寄存器 edx 中第 11 位(这一位名称为 SEP)就表示是否支持。在调用 CPUID 指令之后,还需要查看 CPU 的 Family、Model、Stepping 属性来确认,因为据称 Pentium Pro 处理器会报告 SEP 但是却不支持 sysenter/sysexit 指令。只有 Family 大于等于 6,Model 大于等于 3,Stepping 大于等于 3 的时候,才能确认 CPU 支持 sysenter/sysexit 指令。
Linux 对 sysenter/sysexit 系统调用方式的支持
在 2.4 内核中,直到最近的发布的 2.4.26-rc2 版本,没有加入对 sysenter/sysexit 指令的支持。而对 sysenter/sysexit 指令的支持最早是2002 年,由 Linus Torvalds 编写并首次加入 2.5 版内核中的,经过多方测试和多次 patch,最终正式加入到了 2.6 版本的内核中。
http://kerneltrap.org/node/view/531/1996
http://lwn.net/Articles/18414/
具体谈到系统调用的完成,不能孤立的看内核的代码,我们知道,系统调用多被封装成库函数提供给应用程序调用,应用程序调用库函数后,由 glibc 库负责进入内核调用系统调用函数。在 2.4 内核加上老版的 glibc 的情况下,库函数所做的就是通过 int 指令来完成系统调用,而内核提供的系统调用接口很简单,只要在 IDT 中提供 INT 0x80 的入口,库就可以完成中断调用。
在 2.6 内核中,内核代码同时包含了对 int 0x80 中断方式和 sysenter 指令方式调用的支持,因此内核会给用户空间提供一段入口代码,内核启动时根据 CPU 类型,决定这段代码采取哪种系统调用方式。对于 glibc 来说,无需考虑系统调用方式,直接调用这段入口代码,即可完成系统调用。这样做还可以尽量减少对 glibc 的改动,在 glibc 的源码中,只需将 "int $0x80" 指令替换成 "call 入口地址" 即可。
下面,以 2.6.0 的内核代码配合支持 SYSENTER 调用方式的 glibc2.3.3 为例,分析一下系统调用的具体实现。
内核在启动时做的准备
前面说到的这段入口代码,根据调用方式分为两个文件,支持 sysenter 指令的代码包含在文件 arch/i386/kernel/vsyscall-sysenter.S 中,支持int中断的代码包含在arch/i386/kernel/vsyscall-int80.S中,入口名都是 __kernel_vsyscall,这两个文件编译出的二进制代码由arch/i386/kernel/vsyscall.S所包含,并导出起始地址和结束地址。
2.6 内核在启动的时候,调用了新增的函数sysenter_setup(参见arch/i386/kernel/sysenter.c),在这个函数中,内核将虚拟内存空间的顶端一个固定地址页面(从0xffffe000开始到0xffffeffff的4k大小)映射到一个空闲的物理内存页面。然后通过之前执行CPUID的指令得到的数据,检测CPU是否支持sysenter/sysexit指令。如果CPU不支持,那么将采用INT调用方式的入口代码拷贝到这个页面中,然后返回。相反,如果CPU支持SYSETER/SYSEXIT指令,则将采用SYSENTER调用方式的入口代码拷贝到这个页面中。使用宏 on_each_cpu在每个CPU上执行enable_sep_cpu这个函数。
在enable_sep_cpu函数中,内核将当前CPU的TSS结构中的ss1设置为当前内核使用的代码段,esp1设置为该TSS结构中保留的一个256字节大小的堆栈。在X86中,TSS结构中ss1和esp1本来是用于保存Ring 1进程的堆栈段和堆栈指针的。由于内核在启动时,并不能预知调用sysenter指令进入Ring 0后esp的确切值,而应用程序又无权调用wrmsr指令动态设置,所以此时就借用esp1指向一个固定的缓冲区来填充这个MSR寄存器,由于Ring 1根本没被启用,所以并不会对系统造成任何影响。在下面的文章中会介绍进入Ring 0之后,内核如何修复ESP来指向正确的Ring 0堆栈。关于TSS结构更细节的应用可参考代码include/asm-i386/processor.h)。
然后,内核通过wrmsr(msr,val1,val2)宏调用wrmsr指令对当前CPU设置MSR寄存器,可以看出调用宏的第三个参数即edx都被设置为0。其中SYSENTER_CS_MSR的值被设置为当前内核用的所在代码段;SYSENTER_ESP_MSR被设置为esp1,即指向当前CPU的 TSS结构中的堆栈;SYSENTER_EIP_MSR则被设置为内核中处理sysenter指令的接口函数sysenter_entry(参见 arch/i386/kernel/entry.S)。这样,sysenter指令的准备工作就完成了。
通过内核在启动时进行这样的设置,在每个进程的进程空间中,都能访问到内核所映射的这个代码页面,当然这个页面对于应用程序来说是只读的。我们通过新版的ldd工具查看任意一个可执行程序,可以看到下面的结果:
[root@test]# file dynamic
dynamic: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
[root@test]# ldd dynamic
linux-gate.so.1 => (0xffffe000)
libc.so.6 => /lib/tls/libc.so.6 (0x4002c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
这个所谓的"linux-gate.so.1"的内容就是内核映射的代码,系统中其实并不存在这样一个链接库文件,它的名字是由ldd自己起的,而在老版本的ldd中,虽然能够检测到这段代码,但是由于没有命名而且在系统中找不到对应链接库文件,所以会有一些显示上的问题。有关这个问题的背景,可以参考下面这个网址: http://sources.redhat.com/ml/libc-alpha/2003-09/msg00263.html。
由用户态经库函数进入内核态
为了配合内核使用新的系统调用方式,glibc中要做一定的修改。新的glibc-2.3.2(及其以后版本中)中已经包含了这个改动,在glibc源代码的sysdeps/unix/sysv/linux/i386/sysdep.h文件中,处理系统调用的宏INTERNAL_SYSCALL在不同的编译选项下有不同的结果。在打开支持sysenter/sysexit指令的选项I386_USE_SYSENTER下,系统调用会有两种方式,在静态链接(编译时加上-static选项)情况下,采用"call *_dl_sysinfo"指令;在动态链接情况下,采用"call *%gs:0x10"指令。这两种情况由glibc库采用哪种方法链接,实际上最终都相当于调用某个固定地址的代码。下面我们通过一个小小的程序,配合 gdb来验证。
首先是一个静态编译的程序,代码很简单:
main()
{
getuid();
}
将代码加上static选项用gcc静态编译,然后用gdb装载并反编译main函数。
[root@test opt]# gcc test.c -o ./static -static
[root@test opt]# gdb ./static
(gdb) disassemble main
0x08048204 <main+0>: push %ebp
0x08048205 <main+1>: mov %esp,%ebp
0x08048207 <main+3>: sub $0x8,%esp
0x0804820a <main+6>: and $0xfffffff0,%esp
0x0804820d <main+9>: mov $0x0,%eax
0x08048212 <main+14>: sub %eax,%esp
0x08048214 <main+16>: call 0x804cb20 <__getuid>
0x08048219 <main+21>: leave
0x0804821a <main+22>: ret
可以看出,main函数中调用了__getuid函数,接着反编译__getuid函数。
(gdb) disassemble 0x804cb20
0x0804cb20 <__getuid+0>: push %ebp
0x0804cb21 <__getuid+1>: mov 0x80aa028,%eax
0x0804cb26 <__getuid+6>: mov %esp,%ebp
0x0804cb28 <__getuid+8>: test %eax,%eax
0x0804cb2a <__getuid+10>: jle 0x804cb40 <__getuid+32>
0x0804cb2c <__getuid+12>: mov $0x18,%eax
0x0804cb31 <__getuid+17>: call *0x80aa054
0x0804cb37 <__getuid+23>: pop %ebp
0x0804cb38 <__getuid+24>: ret
上面只是__getuid函数的一部分。可以看到__getuid将eax寄存器赋值为getuid系统调用的功能号0x18然后调用了另一个函数,这个函数的入口在哪里呢?接着查看位于地址0x80aa054的值。
(gdb) X 0x80aa054
0x80aa054 <_dl_sysinfo>: 0x0804d7f6
看起来不像是指向内核映射页面内的代码,但是,可以确认,__dl_sysinfo指针的指向的地址就是0x80aa054。下面,我们试着启动这个程序,然后停在程序第一条语句,再查看这个地方的值。
(gdb) b main
Breakpoint 1 at 0x804820a
(gdb) r
Starting program: /opt/static
Breakpoint 1, 0x0804820a in main ()
(gdb) X 0x80aa054
0x80aa054 <_dl_sysinfo>: 0xffffe400
可以看到,_dl_sysinfo指针指向的数值已经发生了变化,指向了0xffffe400,如果我们继续运行程序,__getuid函数将会调用地址0xffffe400处的代码。
接下来,我们将上面的代码编译成动态链接的方式,即默认方式,用gdb装载并反编译main函数
[root@test opt]# gcc test.c -o ./dynamic
[root@test opt]# gdb ./dynamic
(gdb) disassemble main
0x08048204 <main+0>: push %ebp
0x08048205 <main+1>: mov %esp,%ebp
0x08048207 <main+3>: sub $0x8,%esp
0x0804820a <main+6>: and $0xfffffff0,%esp
0x0804820d <main+9>: mov $0x0,%eax
0x08048212 <main+14>: sub %eax,%esp
0x08048214 <main+16>: call 0x8048288
0x08048219 <main+21>: leave
0x0804821a <main+22>: ret
由于libc库是在程序初始化时才被装载,所以我们先启动程序,并停在main第一条语句,然后反汇编getuid库函数
。
(gdb) b main
Breakpoint 1 at 0x804820a
(gdb) r
Starting program: /opt/dynamic
Breakpoint 1, 0x0804820a in main ()
(gdb) disassemble getuid
Dump of assembler code for function getuid:
0x40219e50 <__getuid+0>: push %ebp
0x40219e51 <__getuid+1>: mov %esp,%ebp
0x40219e53 <__getuid+3>: push %ebx
0x40219e54 <__getuid+4>: call 0x40219e59 <__getuid+9>
0x40219e59 <__getuid+9>: pop %ebx
0x40219e5a <__getuid+10>: add $0x84b0f,%ebx
0x40219e60 <__getuid+16>: mov 0xffffd87c(%ebx),%eax
0x40219e66 <__getuid+22>: test %eax,%eax
0x40219e68 <__getuid+24>: jle 0x40219e80 <__getuid+48>
0x40219e6a <__getuid+26>: mov $0x18,%eax
0x40219e6f <__getuid+31>: call *%gs:0x10
0x40219e76 <__getuid+38>: pop %ebx
0x40219e77 <__getuid+39>: pop %ebp
0x40219e78 <__getuid+40>: ret
可以看出,库函数getuid将eax寄存器设置为getuid系统调用的调用号0x18,然后调用%gs:0x10所指向的函数。在gdb中,无法查看非DS段的数据内容,所以无法查看%gs:0x10所保存的实际数值,不过我们可以通过编程的办法,内嵌汇编将%gs:0x10的值赋予某个局部变量来得到这个数值,而这个数值也是0xffffe400,具体代码这里就不再赘述。
由此可见,无论是静态还是动态方式,最终我们都来到了0xffffe400这里的一段代码,这里就是内核为我们映射的系统调用入口代码。在gdb中,我们可以直接反汇编来查看这里的代码
(gdb) disassemble 0xffffe400 0xffffe414
Dump of assembler code from 0xffffe400 to 0xffffe414:0xffffe400: push %ecx
0xffffe401: push %edx
0xffffe402: push %ebp
0xffffe403: mov %esp,%ebp
0xffffe405: sysenter
0xffffe407: nop
0xffffe408: nop
0xffffe409: nop
0xffffe40a: nop
0xffffe40b: nop
0xffffe40c: nop
0xffffe40d: nop
0xffffe40e: jmp 0xffffe403
0xffffe410: pop %ebp
0xffffe411: pop %edx
0xffffe412: pop %ecx
0xffffe413: ret
End of assembler mp.
这段代码正是arch/i386/kernel/vsyscall- sysenter.S文件中的代码。其中,在sysenter之前的是入口代码,在0xffffe410开始的是内核返回处理代码(后面提到的 SYSENTER_RETURN即指向这里)。在入口代码中,首先是保存当前的ecx,edx(由于sysexit指令需要使用这两个寄存器)以及 ebp。然后调用sysenter指令,跳转到内核Ring 0代码,也就是sysenter_entry入口处。
内核中的处理和返回
sysenter_entry整个的实现可以参见arch/i386/kernel/entry.S。内核处理SYSENTER的代码和处理INT的代码不太一样。通过sysenter指令进入Ring 0之后,由于当前的ESP并非指向正确的内核栈,而是当前CPU的TSS结构中的一个缓冲区(参见上文),所以首先要解决的是修复ESP,幸运的是,TSS结构中ESP0成员本身就保存有Ring 0状态的ESP值,所以在这里将TSS结构中ESP0的值赋予ESP寄存器。将ESP恢复成指向正确的堆栈之后,由于SYSENTER不是通过调用门进入Ring 0,所以在堆栈中的上下文和使用INT指令的不一样,INT指令进入Ring 0后栈中会保存如下的值。
低地址
返回用户态的EIP
用户态的CS
用户态的EFLAGS
用户态的ESP
用户态的SS(和DS相同)
高地址
因此,为了简化和重用代码,内核会用pushl指令往栈中放入上述各值,值得注意的是,内核在栈中放入的相对应用户态EIP的值,是一个代码标签 SYSENTER_RETURN,在vsyscall-sysenter.S可以看到,它就在sysenter指令的后面(在它们之间,有一段NOP,是内核返回出错时的处理代码)。接下来,处理系统调用的代码就和中断方式的处理代码一模一样了,内核保存所有的寄存器,然后系统调用表找到对应系统调用的入口,完成调用。最后,内核从栈中取出前面存入的用户态的EIP和ESP,存入edx和ecx寄存器,调用SYSEXIT指令返回用户态。返回用户态之后,从栈中取出ESP,edx,ecx,最终返回glibc库。
其它操作系统以及其它硬件平台的支持
值得一提的是,从 Windows XP 开始,Windows 的系统调用方式也从软中断 int 0x2e 转换到采用 sysenter 方式,由于完全不再支持 int 方式,因此 Windows XP 的对 CPU 的最低配置要求是 PentiumII 300MHz。在其它的操作系统例如 *BSD 系列,目前并没有提供对 sysenter 指令的支持。
在 CPU 方面,AMD 的 CPU 支持一套与之对应的指令 SYSCALL/SYSRET。在纯 32 位的 AMD CPU 上,还没有支持 sysenter 指令,而在 AMD 推出的 AMD64 系列 CPU 上,处于某些模式的情况下,CPU 能够支持 sysenter/sysexit 指令。在 Linux 内核针对 AMD64 架构的代码中,采用的还是 SYSCALL/SYSRET 指令。至于这两种指令最终谁将成为标准,目前还无法得出结论。
未来
我们将 Intel 的 sysenter/sysexit 指令,AMD 的 SYSCALL/SYSRET 指令统称为"快速系统调用指令"。"快速系统调用指令"比起中断指令来说,其消耗时间必然会少一些,但是随着 CPU 设计的发展,将来应该不会再出现类似 Intel Pentium4 这样悬殊的差距。而"快速系统调用指令"比起中断方式的系统调用方式,还存在一定局限,例如无法在一个系统调用处理过程中再通过"快速系统调用指令"调用别的系统调用。因此,并不一定每个系统调用都需要通过"快速系统调用指令"来实现。比如,对于复杂的系统调用例如 fork,两种系统调用方式的时间差和系统调用本身运行消耗的时间来比,可以忽略不计,此处采取"快速系统调用指令"方式没有什么必要。而真正应该使用" 快速系统调用指令"方式的,是那些本身运行时间很短,对时间精确性要求高的系统调用,例如 getuid、gettimeofday 等等。因此,采取灵活的手段,针对不同的系统调用采取不同的方式,才能得到最优化的性能和实现最完美的功能。
参考资料
[1] VxWorks Optimized for Intel Architecture, Hdei Nunoe, Wind River, Member of Technical Staff Leo Samson, Wind River, Technical Marketing Engineer David Hillyard, Intel Corporation, Mgr., Platform Architect
[2] Kernel Entry / Kernel Exit , Marcus Voelp & University Karlsruhe
[3] Dave Jones' blog, http://diary.codemonkey.org.uk/index.php?month=12&year=2002
[4] Linux 内核源码 v2.6.0 http://www.kernel.org/ [Linus Torvalds,2004]
[5] GNU C Library glibc 2.3.3 源码 http://www.gnu.org/software/libc/libc.html
Linux Kernel Mailing List 中对系统调用方式的讨论: [5] Linux Kernel Mailing List, "Intel P6 vs P7 system call performance" http://www.ussg.iu.e/hypermail/linux/kernel/0212.1/index.html#1286 http://www.ussg.iu.e/hypermail/linux/kernel/0212.3/index.html#54
Linux 内核首次引入对 sysenter/sysexit 指令的支持: [6] Linux Kernel Mailing List, "Add "sysenter" support on x86, and a "vsyscall" page." http://lwn.net/Articles/18414/
8. linux arm嵌入式开发中的 MSR指令什么意思
在ARM处理器中,只有MSR指令可以对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读-修改-写操作,可以切换处理器模式、或者允许/禁止IRQ/FIQ中断等。
由于xPSR寄存器代表了CPU的状态,其每个位有特殊意义,在执行对xPSR状态寄存器写入时(读取时不存在该用法),为了防止误操作和方便记忆,将xPSR里32位分成四个区域,每个区域用小写字母表示:
c 控制域屏蔽 psr[7..0]
x 扩展域屏蔽 psr[15..8]
s 状态域屏蔽 psr[23..16]
f 标志域屏蔽 psr[31..24]
注意:区域名必须为小写字母
向对应区域进行执行写入时,使用xPSR_x可以指定写入区域,而不影响状态寄存器其它位,如:
使能IRQ中断:
ENABLE_IRQ
MRS R0, CPSR ; 将CPSR寄存器内容读出到R0
BIC R0, R0,#0x80 ; 清掉CPSR中的I控制位
MSR CPSR_c,R0 ; 将修改后的值写回 CPSR寄存器的对应控制域
MOV PC,LR ; 返回上一层函数
禁用IRQ中断:
DISABLE_IRQ
MRS R0 CPSR ; 将CPSR寄存器内容读出到R0
ORR R0, R0,#0x80 ; 设置CPSR中的I控制位
MSR CPSR_c,R0 ; 将修改后的值写回 CPSR寄存器的对应控制域
MOV PC,LR ; 返回上一层函数