程序如何执行?操作系统在哪里发挥作用?

时间:2009-10-21 08:24:09

标签: platform-independence

程序从某种语言汇编到ASM - >机器代码(可直接执行)。当人们说这是依赖于平台时,二进制文件形成的意思将仅在具有相同指令集架构的CPU(如x86,x86-64)上运行(正确)。由于ISA的不同,它可能(不正确)/可能不会(根本没有)在其他进程上运行。正确?

现在,二进制文件的概念令我感到困惑。一切都是关于“机器语言代码”& “中央处理器”。操作系统在哪里发挥作用?我的意思是编译后的二进制文件在加载到内存时有CPU的直接指令。 &安培; CPU一次执行一条指令。除了流程管理link text之外,我无法看到操作系统的任何角色。无论操作系统如何,它都应该在同一个ISA的CPU上运行。对?

但事实并非如此。如果我在Windows机器上为x86构建代码。它不能在Mac x86机器或Linux x86机器上运行。

我在这里遗漏了一些东西。请清除我的困惑。

9 个答案:

答案 0 :(得分:14)

对于初学者来说,现代CPU具有(至少)两种模式,一种是运行操作系统核心的模式(“内核模式”),另一种是运行程序的模式(“用户模式”) 。在用户模式下,CPU无法做很多事情。

例如,通常会在内核中注意鼠标单击,而不是用户模式。但是,操作系统将事件调度到用户模式并从那里调度到正确的程序。反过来也需要合作:一个程序不能自由地绘制到屏幕上,但需要通过操作系统和内核模式来绘制它。

同样,启动计划的行为通常是合作。 OS的shell部分也是用户模式程序。它会让您点击鼠标,并确定它是用于启动进程的鼠标单击。然后shell告诉操作系统的内核模式部分为该程序启动一个新进程。

当内核模式需要启动新进程时,它首先为记账分配内存,然后继续加载程序。这涉及从二进制文件中检索指令,但也将程序连接到OS。这通常需要找到二进制文件的入口点(经典int main(int argc, char** argv)),以及程序想要调用操作系统的所有点。

不同的操作系统使用不同的方法将程序与操作系统连接起来。因此,加载过程不同,二进制文件的文件格式也可能不同。这不是绝对的;二进制文件的ELF格式用于许多操作系统,Microsoft在其所有当前操作系统上使用其PE格式。在这两种情况下,格式都描述了二进制文件的精确格式,因此操作系统可以决定程序是否可以连接到操作系统。例如,如果它是Win32二进制文件,它将采用PE格式,因此Linux不会加载,Windows 2000将会加载,Windows 7-64也是如此。另一方面,Win64二进制文件也是PE格式,但Windows 2000将拒绝它。

答案 1 :(得分:10)

它不会在其他处理器上运行,因为01010110011意味着x86上的东西和ARM上的其他内容。 x86-64恰好与x86向后兼容,因此它可以运行x86程序。

二进制文件是您的操作系统理解的特定格式(windows = PE,mac / linux = ELF)

对于任何普通二进制文件,您的操作系统会将其加载到内存中并使用特定值填充许多字段。这些“特定值”是存在于共享库(dll,so)中的api函数的地址,例如kernel32或libc。 需要API地址,因为二进制文件本身不知道如何访问硬盘驱动器,网卡,游戏手柄等。程序使用这些地址来调用操作系统或其他库中存在的某些功能。

从本质上讲,二进制文件缺少一些需要由操作系统填充以使一切正常工作的重要部分。如果操作系统填写错误的部分,二进制文件将无法工作,因为它们无法相互通信。如果您将user32.dll替换为另一个文件,或者如果您尝试在mac osx上运行linux可执行文件,那会发生什么。

那么libc如何知道如何打开文件?

libc使用syscalls,它是对OS核心功能的低级访问。它有点像函数调用,除非你通过填充某些CPU寄存器然后触发中断(特殊CPU指令)来实现它。

那么操作系统如何知道如何打开文件呢?

这是操作系统所做的事情之一。但它如何知道如何与硬盘通信? 我不确切知道这些东西是如何工作的,但我想操作系统是通过编写/读取碰巧映射到BIOS功能的某些内存位置来实现的。

那么BIOS如何知道如何与硬盘驱动器通信?

我也不知道,我从未在那个级别做任何编程。我想BIOS是硬连线到硬盘驱动器连接器,并能够发送正确的1和0序列与硬盘驱动器“SATA”。它可能只会说简单的事情,比如“读这个部门”

那么硬盘驱动器如何知道如何读取扇区?

我真的根本不知道这一点,所以我会让一些硬件继续。

答案 2 :(得分:7)

两种方式:

首先,答案是“系统调用”。无论何时调用需要执行任何I / O的函数,与设备交互,分配内存,fork进程等,该函数都需要执行“系统调用”。虽然系统调用指令本身是X86的一部分,但可用的系统调用和参数是特定于操作系统的。

即使您的程序没有进行任何系统调用(我不确定是否可行,当然也不会非常有用),包含机器代码的格式对于不同的操作系统是不同的。因此exe(PE)和linux可执行文件(通常是ELF)的文件格式不同,这就是exe文件无法在Linux上执行的原因。

编辑:这些是低级细节。更高层次的答案是,任何需要访问文件,控制台/ GUI,分配内存等的都是特定于操作系统的。

答案 3 :(得分:3)

当您尝试访问在硬件级别为您提取的“服务”时,操作系统会发挥作用,例如:在名为filesystem的“数据库”中打开一个文件,生成一个随机数(每个现代操作系统都有此功能)。

例如,在GNU / Linux下,你必须填写寄存器并调用int 80h来访问“服务”(实际上称为“syscall”)。

您的程序也不会在另一个操作系统上运行,因为可执行文件的文件格式不同,例如Win有COFF / PE,Linux有ELF文件格式(就像任何其他文件格式一样,这也包含“元数据”) “,例如HTML(或SGML)文件格式。)

答案 4 :(得分:1)

操作系统提供(a)运行机器代码的环境,以及(b)标准服务。如果没有(a),你的代码将永远不会在第一时间执行,如果没有(b),你必须自己实现所有内容并直接命中硬件。

答案 5 :(得分:1)

由高级语言生成的机器指令适用于提供您所做调用的库的调用约定,包括任何系统调用(尽管这些调用通常包含在某个用户空间库中,因此具体说明如何制作可能没有必要进行系统调用。)

此外,它适用于目标指令集架构,但有一些例外(例如,必须注意关于指针大小,基本类型,结构布局,C ++中的类实现等的假设)。

文件格式将指示必要的钩子/公开可见的函数和数据,以使操作系统能够将代码作为进程执行,并将进程引导到所需的状态。如果您熟悉Windows下的C / C ++开发,子系统的概念决定了引导级别,提供的资源和入口点签名(在大多数系统上通常为main(int, char **))。

有一些很好的例子说明高级语言,指令集架构和可执行文件格式的选择如何影响在任何给定系统上运行二进制文件的能力:

汇编语言必须为特定ISA编码。它们使用特定于一系列CPU类型的指令。这些指令可能适用于其他CPU系列,如果那些CPU支持给定的指令集。例如,x86代码在某种程度上可以在amd64操作系统上运行,并且肯定适用于运行x86操作系统的amd64 CPU。

C抽象了ISA的许多细节。一些明显的例外包括指针大小和字节序。各种众所周知的接口将通过libc提供给预期的级别,例如printfmainfopen等。这些包括预期的寄存器和堆栈状态,以便进行这些调用,使C代码能够在不改变的情况下在不同的操作系统和体系结构上工作。可以直接提供其他接口,也可以通过将特定于平台的特性包装到预期的接口中来增加C代码的可移植性。

Python和其他类似的“虚拟化”语言在另一个抽象层次上运行,并且除了少数例外,例如特定平台上不存在的特征或字符编码差异,可以无需修改即可运行系统。这是通过为许多不同的ISA和操作系统组合提供统一的接口来实现的,但代价是性能和可执行的大小。

答案 6 :(得分:0)

操作系统提供了访问某些功能和硬件的工具和API。

例如,要在Microsoft Windows上创建窗口,您需要操作系统的DLL来创建窗口。

除非您希望自己编写API,否则您将使用操作系统提供的API。这就是操作系统发挥作用的地方。

答案 7 :(得分:0)

此外,我想添加操作系统处理程序的启动。 它准备进程空间并对其进行初始化,以便程序可以开始,加载程序指令并控制程序。

答案 8 :(得分:0)

类比:

假设您从其他国家雇用管家。他不明白你说的一句话,所以你得到一个类似星际跋涉的翻译设备。现在他可以理解你的高级语言,因为当你说话时,他会听到他自己的(相当粗略的)语言。

现在假设你想要他从A走到B.你不会直接跟他的腿或脚说话,你会问他的脸!他控制着自己的身体。如果1)您正确地传达了您的请求,2)他决定将其纳入其工作职责,他将从A移至B.

现在你得到一个新的仆人,来自同一个国家(因为你宁愿不买一个新的星际跋涉翻译)。你也希望他从A走到B。但是这个仆人要求你大声说话,并在询问时说。你忍受了这个,因为他更灵活:如果你愿意的话,你可以让他通过C从A到B去 - 以前的管家可以做到这一点,但拖了他的脚并抱怨。

另一个幸运的突破是你可以调整你的翻译设置来处理这个问题,因此,从你的语言角度来看,没有任何改变。但是,如果你要用新设置与老管家谈话,即使你说的是他的语言,他也会感到困惑甚至不理解。

如果不清楚,管家是具有相同ISA但操作系统不同的计算机。翻译器是针对其ISA的交叉编译工具链。