什么是asm
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是asm相关的知识,希望对你有一定的参考价值。
哪位大哥能帮我解释一下什么事asm,自动储存管理,我看了百度百科,有解释,可是看不懂啊,那个大哥能给我解释一下啊,就是自动储存这一方面的
假设您要在数据库中使用 10 个磁盘。利用 ASM,您不需要在 OS 端创建任何东西,该特性将把一组物理磁盘集合成一个逻辑实体(称为磁盘组)。
磁盘组类似于一个分段(和可选镜像)文件系统,但具有重要的差异:它不是一个用于存储用户文件的通用文件系统,并且它不进行缓冲。由于后面的原因,磁盘组提供了直接作为原始设备来访问这个空间,并仍提供文件系统的便利性和灵活性的好处。
ASM它提供了以平台无关的文件系统、逻辑卷管理以及软RAID服务。ASM可以支持条带化和磁盘镜像,从而实现了在数据库被加载的情况下添加或移除磁盘以及自动平衡I/O以删除“热点”。它还支持直接和异步的I/O并使用Oracle9i中引入的Oracle数据管理器API(简化的I/O系统调用接口)。
扩展资料:
ASM使用独特的镜像算法:不镜像磁盘,而是镜像盘区。作为结果,为了在产生故障时提供连续的保护,只需要磁盘组中的空间容量,而不需要预备一个热备(hot spare)磁盘。
不建议用户创建不同尺寸的故障组,因为这将会导致在分配辅助盘区时产生问题。ASM将文件的主盘区分配给磁盘组中的一个磁盘时,它会将该盘区的镜像副本分配给磁盘组中的另一个磁盘。给定磁盘上的主盘区将在磁盘组中的某个伙伴磁盘上具有各自的镜像盘区。
ASM确保主盘区和其镜像副本不会驻留在相同的故障组中。磁盘组的冗余可以有如下的形式:双向镜像文件(至少需要两个故障组)的普通冗余(默认冗余)和使用三向镜像(至少需要3个故障组)提供较高保护程度的高冗余。
参考资料:百度百科-ASM
参考技术A 最近没有事情就翻翻自己的系统文件夹,走到C:\WINDOWS\system32\config文件夹下时,发现如下五个奇怪的文件:sam,default,security,software,system.在windows系统环境下无法打开。并且其中sam,security,default均为256k。这几个文件到底是什么用呢?就到网络上查查。SAM最初是跟随第一代NT来到世界的,它在微软总部的特工代号叫做“安全账户管理器”(Security Accounts Manager),可以所sam文件是windows的门卫,在win2k时代这个门卫不太强大,到了NT内核时代,这个家伙的作用就变得强大了。SAM记录的数据很多,包括所有组、账户信息、密码HASH、账户SID等,应该说是一个考虑得比较周全的门卫。
SAM不仅仅是一个文件那么简单,它不但有文件数据,在注册表里面还有一个数据库,位于HKEY_LOCAL_MACHINE\\SAM下,这是一个比较复杂的结构。SAM在系统启动后就处于锁定状态,我们没法擅自更改这个文件内容。
在注册表里我们可以看到一下内容:
1.在HKEY_LOCAL_MACHINE\\SAM\\SAM\\
Domains下就是SAM的内容,其下有两个分支“Account”和“Builtin”。
2.Domains\\Account\\Users下存放的就是各个账号的信息,当然,这里是加密过的二进制数据,每个账号下面有两个子项,F和V。项目V中保存的是账户的基本资料,用户名、所属组、描述、密码、注释、是否可以更改密码、账户启用、密码设置时间等。项目F中保存的是一些登录记录,比如上次登录时间、错误登录次数等。SAM靠这些齐全的备忘录来保存与用户账号相关的各种信息。
3.Domains\\Builtin存放着不同用户分组信息,SAM就是根据这个来划分NT中固有的6个不同的工作组的,它们分别是:管理员(Administrators)、备份操作员(Backup Operators)、客人(Guests)、高权限用户(Power Users)、修复员(Replicator)和普通用户(Users)。
幕后指挥官
在Windows系统中,虽然SAM如此尽力,但是他不听从你的指挥。它只听本地安全认证(Local Security Authority)程序——LSASS.EXE的差遣,就连进门时的审查也是LSASS的指示。如果你把LSASS杀了,你就等着被赶出门吧——当然,对于普通用户来说,如果你试图用普通的进程管理工具或者Windows系统的进程管理杀掉“LSASS.EXE”进程的话,只会得到“该进程为关键系统进程,任务管理器无法结束进程。”的提示,本地安全认证(Local Security Authority)在Windows系统中主要负责以下任务:1.重新找回本地组的SID和用户权限;2.创建用户的访问令牌;3.管理本地安装的服务所使用的服务账号;4. 存储和映射用户权限;5.管理审核的策略和设置;6.管理信任关系。
俗话说,“人无完人”。尽管SAM(萨姆)是这么尽心尽责,可是在这里,我们还是必须用那句话——“萨姆也是人”来形容它。由于一些设计上的失误,在WinNT/2000里,如果你忘记了密码,那么你要做的不是呼天喊地,只需要在非NT环境里把SAM驱逐出硬盘就可以了。但是在XP以后的Windows操作系统里,这个情况得以改善,如果你把萨姆大叔踢了,NT也躲着死活不肯出来了。
特别提醒:不要以为sam文件记录了密码信息你就可以删除该文件使得系统用户密码为空,虽然在早期的win2k时代你可以在dos环境下这样做以求达到置空密码的目的,在xp时代,这样可没有用哦。 参考技术B 假设您要在数据库中使用 10 个磁盘。利用 ASM,您不需要在 OS 端创建任何东西,该特性将把一组物理磁盘集合成一个逻辑实体(称为磁盘组)。磁盘组类似于一个分段(和可选镜像)文件系统,但具有重要的差异:它不是一个用于存储用户文件的通用文件系统,并且它不进行缓冲。由于后面的原因,磁盘组提供了直接作为原始设备来访问这个空间,并仍提供文件系统的便利性和灵活性的好处。
逻辑卷管理器一般使用一个函数(如散列函数)来将块的逻辑地址映射到物理块。计算使用 CPU 周期。此外,当增加一个新的磁盘(或 RAID-5 磁盘组)时,这种典型的分段函数需要重新定位整个数据集中的每一位。
相比而言,ASM 使用一个特殊的 Oracle 例程来解决从文件区到物理磁盘块的映射问题。这种设计除了定位文件区非常快速之外,还在增加或删除磁盘时有所帮助,因为文件区的位置不需要调整。这个特殊的 ASM 例程类似于其它的文件系统,必须运行此例程,ASM 才能工作,并且用户不能进行修改。一个 ASM 例程可以在同一台服务器上支持许多 Oracle 数据库例程。
这个特殊的例程只是一个例程,不是用户可以在其中创建对象的数据库。所有关于磁盘的元数据都存储在磁盘组本身中,使得它们能够尽可能地自我描述。
那么概括地说,ASM 的优点是什么?
● 磁盘增加 — 增加磁盘变得非常容易。无需停机时间,并且文件区域自动重新分配。
● I/O 分配 — I/O 自动分布在所有可用的磁盘上,无需人工干预,从而减少了热点出现的可能性。
● 带区宽度 — 在重做日志文件中分段可以细分(128K,以获得更快的传输速率),对于数据文件,带区则略大一些(1MB,以一次性传输大量的数据块)。
● 缓冲 — ASM 文件系统不进行缓冲,直接进行输入/输出。
● 核心化的异步 I/O — 实现核心化的异步 I/O 无需特殊的设置,并且无需使用原始或第三方的文件系统(如 Veritas Quick I/O)。
● 镜像 — 如果硬件镜像不可用,则可以容易地建立软件镜像。本回答被提问者采纳 参考技术C ASM- 「动态稳定控制器」。同样是藉著控制四个轮子的煞车力道,来抑减转向过度或转向不足等状况。对大马力车种而言,这种装置可以有效地预防转向过度,即使是驾驶风格粗暴的人,也会因为ASM的关系而大幅降低失控偏离赛道的窘况,是一种能使车性稳定温和的机制。
但同时也因ASM的强力介入,会使得车辆性能受到压制,无法达到如驾驶人意志般的随心所欲自由操控,相对会牺牲掉一些速度与灵活度。
'asm','__ asm'和'__asm__'有什么区别?
据我所知,__asm { ... };
和__asm__("...");
之间的唯一区别是,第一个使用mov eax, var
,第二个使用movl %0, %%eax
和:"=r" (var)
。还有什么其他差异?那只是asm
呢?
您使用哪一个取决于您的编译器。这不像C语言那样标准。
MSVC内联asm和GNU C内联asm之间存在巨大差异。 GCC语法设计用于最佳输出而不会浪费指令,用于包装单个指令或其他内容。 MSVC语法设计得相当简单,但是AFAICT如果没有延迟和额外的指令通过内存为您的输入和输出使用它是不可能的。
如果出于性能原因使用内联asm,这使得MSVC内联asm仅在完全在asm中编写完整循环时才可行,而不是用于在内联函数中包装短序列。下面的例子(用函数包装idiv
)是MSVC不好的东西:~8个额外的存储/加载指令。
MSVC内联asm(由MSVC使用,可能是icc,也可能在一些商业编译器中提供):
- 查看你的asm,找出你的代码所处的寄存器。
- 只能通过内存传输数据。例如,存储在寄存器中的数据由编译器存储,以准备您的
mov ecx, shift_count
。因此,使用编译器不会为您生成的单个asm指令,包括在路上和路上的往返内存。 - 更适合初学者,但通常无法避免数据输入/输出。即使除了语法限制之外,当前版本的MSVC中的优化器也不擅长围绕内联asm块进行优化。
GNU C inline asm is not a good way to learn asm。您必须非常了解asm,以便您可以告诉编译器您的代码。你必须了解编译器需要知道什么。该答案还与其他inline-asm指南和Q&A有关。 x86标签维基对于asm一般有很多好东西,但只是链接到GNU内联asm。 (该答案中的内容也适用于非x86平台上的GNU内联asm。)
GNU C inline asm语法由gcc,clang,icc和一些实现GNU C的商业编译器使用:
- 你必须告诉编译器你破坏了什么。如果不这样做,将导致以非显而易见的难以调试的方式破坏周围的代码。
- 功能强大但难以阅读,学习和使用语法来告诉编译器如何提供输入以及在何处查找输出。例如
"c" (shift_count)
将让编译器在你的内联asm运行之前将shift_count
变量放入ecx
。 - 因为asm必须在一个字符串常量内,所以对于大块代码来说是额外的笨重。所以你通常需要
"insn %[inputvar], %%reg " // comment "insn2 %%reg, %[outputvar] "
- 非常无情/更难,但允许更低的开销esp。用于包装单个指令。 (包装单个指令是原始的设计意图,这就是为什么你必须特别告诉编译器有关早期的clobbers,以阻止它使用相同的寄存器输入和输出,如果这是一个问题。)
Example: full-width integer division (div
)
在32位CPU上,将64位整数除以32位整数,或者进行全乘(32x32-> 64),可以从内联asm中受益。 gcc和clang没有利用idiv
来获取(int64_t)a / (int32_t)b
,可能是因为如果结果不适合32位寄存器,则指令会出错。因此,与this Q&A about getting quotient and remainder from one div
不同,这是内联asm的用例。 (除非有办法通知编译器结果是否合适,所以idiv不会出错。)
我们将使用调用约定将一些args放在寄存器中(甚至在正确的寄存器中使用hi
),以显示一个更接近你在内联这样一个小函数时看到的情况。
MSVC
使用inline-asm时要小心register-arg调用约定。显然,内联-asm支持是如此糟糕的设计/实现the compiler might not save/restore arg registers around the inline asm, if those args aren't used in the inline asm。感谢@RossRidge指出这一点。
// MSVC. Be careful with _vectorcall & inline-asm: see above
// we could return a struct, but that would complicate things
int _vectorcall div64(int hi, int lo, int divisor, int *premainder) {
int quotient, tmp;
__asm {
mov edx, hi;
mov eax, lo;
idiv divisor
mov quotient, eax
mov tmp, edx;
// mov ecx, premainder // Or this I guess?
// mov [ecx], edx
}
*premainder = tmp;
return quotient; // or omit the return with a value in eax
}
更新:显然在eax
或edx:eax
留下一个值,然后从无效函数(没有return
)is supported, even when inlining的末尾掉下来。我认为这只有在asm
语句之后没有代码时才有效。这避免了输出的存储/重载(至少对于quotient
),但我们无法对输入做任何事情。在具有堆栈args的非内联函数中,它们已经在内存中,但在这个用例中,我们正在编写一个可以有用内联的小函数。
编译与MSVC 19.00.23026 /O2
on rextester(与main()
找到exe和dumps the compiler's asm output to stdout的目录)。
## My added comments use. ##
; ... define some symbolic constants for stack offsets of parameters
; 48 : int ABI div64(int hi, int lo, int divisor, int *premainder) {
sub esp, 16 ; 00000010H
mov DWORD PTR _lo$[esp+16], edx ## these symbolic constants match up with the names of the stack args and locals
mov DWORD PTR _hi$[esp+16], ecx
## start of __asm {
mov edx, DWORD PTR _hi$[esp+16]
mov eax, DWORD PTR _lo$[esp+16]
idiv DWORD PTR _divisor$[esp+12]
mov DWORD PTR _quotient$[esp+16], eax ## store to a local temporary, not *premainder
mov DWORD PTR _tmp$[esp+16], edx
## end of __asm block
mov ecx, DWORD PTR _premainder$[esp+12]
mov eax, DWORD PTR _tmp$[esp+16]
mov DWORD PTR [ecx], eax ## I guess we should have done this inside the inline asm so this would suck slightly less
mov eax, DWORD PTR _quotient$[esp+16] ## but this one is unavoidable
add esp, 16 ; 00000010H
ret 8
有大量额外的mov指令,编译器甚至没有接近优化任何它。我想也许它会看到并理解内联asm中的mov tmp, edx
,并将它作为premainder
的商店。但是,我想这需要在内联asm块之前将堆栈中的premainder
加载到寄存器中。
_vectorcall
实际上比使用正常的堆栈ABI更糟糕。寄存器中有两个输入,它将它们存储到内存中,因此内联asm可以从命名变量加载它们。如果这是内联的,那么更多的参数可能会出现在regs中,而且必须将它们全部存储起来,所以asm会有内存操作数!因此,与gcc不同,我们从内联中获得的收益并不高。
在asm块中执行*premainder = tmp
意味着在asm中编写更多代码,但确实避免了余数的完全braindead存储/加载/存储路径。这将指令数量减少了2个,减少到11个(不包括ret
)。
我试图从MSVC中获取最好的代码,而不是“使用它错误”并创建一个稻草人的论点。但AFAICT包装非常短的序列非常可怕。据推测,有64/32 - > 32除法的内在函数允许编译器为这种特殊情况生成良好的代码,因此在MSVC上使用内联asm的整个前提可能是一个稻草人的论点。但它确实向您展示内在函数比MSVC的内联函数要好得多。
GNU C(gcc / clang / icc)
在内联div64时,Gcc甚至比这里显示的输出更好,因为它通常可以安排前面的代码首先在edx:eax中生成64位整数。
我无法让gcc编译为32位vectorcall ABI。 Clang可以,但它在"rm"
约束的内联asm中很糟糕(在godbolt链接上尝试它:它通过内存反弹函数arg而不是在约束中使用register选项)。 64位MS调用约定接近32位向量调用,前两个参数在edx,ecx中。不同之处在于,在使用堆栈之前,还有2个参数进入了regs(并且被调用者没有弹出堆栈中的args,这就是ret 8
在MSVC输出中的含义。)
// GNU C
// change everything to int64_t to do 128b/64b -> 64b division
// MSVC doesn't do x86-64 inline asm, so we'll use 32bit to be comparable
int div64(int lo, int hi, int *premainder, int divisor) {
int quotient, rem;
asm ("idivl %[divsrc]"
: "=a" (quotient), "=d" (rem) // a means eax, d means edx
: "d" (hi), "a" (lo),
[divsrc] "rm" (divisor) // Could have just used %0 instead of naming divsrc
// note the "rm" to allow the src to be in a register or not, whatever gcc chooses.
// "rmi" would also allow an immediate, but unlike adc, idiv doesn't have an immediate form
: // no clobbers
);
*premainder = rem;
return quotient;
}