编译和链接程序后,可以按照以下步骤在Windows命令提示符中运行可执行文件:
打开Windows命令提示符。您可以按下Windows + R键,然后输入“cmd”并按回车键来打开它。
进入可执行文件所在的目录。罩皮族假设可执行文件名为“T1-1.exe”,则可以使用cd命令进入该文件所在的目录,例如:
cd C:\
运行可执行文件。在命令提示符中输入可执握高行文件的名称(包括扩展名),并按回车键。例如:
T1-1.exe
这物弊将启动可执行文件并运行它。请注意,在运行可执行文件之前,您需要确保已经正确设置了环境变量和依赖项,并且已经正确生成了可执行文件。否则,程序可能无法正常运行。
当双击某个图标时,Explorer.exe进程的一个线程会侦测到这个 *** 作,它根据注册表中的信息取得文件名,然后Explorer.exe 以这个文件名调用 CreateProcess 函数。注册表中有相关的项保存着双击 *** 作的信息,如 exe 文件关联、启动 exe 的 Shell 是哪个。PC中的大多其它的进程都是 Explorer.exe 的子进程,因为它们都是由Explorer.exe 进程创建的。CreateProcess 实际上是通过 NtCreateProcess 函数实现的, 此时,系统会创建一个进程内核对象。进程内核对象可以看作是 *** 作系统用来管理进程的小的数据结构,它是在内核堆区分配的一个结构体,是系统用来存放关于进程统计信息的地方。进程内核对象维护了一个句柄表的结构,当进程被初始化之后,其句柄表是空的。当进程内的一个线程通过指定的函数创建了一个内核对象时,内核会为对象分配一块内存区域并初始化这块区域,然后内核会在进程的句柄表中查找一个空的入口,找到之后会初始化句柄表的以索引定位的区域。初始化的主要过程就是填充句柄表的一个单元,包括指定内核对象地址,指定访问码,指定标记等。
进程内核对象创建后,它的引用计数被置为1。然后系统为刚刚创建的进程分配的进程虚拟地址空间。要注意了,之所以称为虚拟地址空间,就是因为这块地址空间并不在内存之中,它只是在硬盘上划分的被称为“页”的文件。每个进程都有自己的虚拟地棚蔽碰址空间,在进程初始化的时候,其所有的程序和数据会被加载到这个地址空间中。等到真正运行的时候,系统为每个进程配置的页表会把虚拟地址映射为真正的物理地址(这个过程,链谈我会在后面的博客中详细介绍如何映射)。
初始化虚拟地址空间。进程地址空间创建后,Windows的装载器(loader,也称为PE装载器)开始工作,Loader会读取EXE文件的信息(PE文件)。此时 loader 会检查PE文件的有效性,如果PE文件有错误,进程也就无法启动了。如果PE文件没有错误,装载器就把PE文件的内容(二进制代码)映射到进程的地址空间中,然后读取 PE文件的导入地址表(Import Table),这里存放有exe文件需要导入的模块文件(DLL),系统会一一加载这些DLL到进程的地址空间中,具体做法是调用 LoadLibrary 函数加载程序代码到某个地址,然后系统会映射这些代码到进程的地址空间中,要知道DLL只需加载一次就可映射到所有进程的地址空间(映射过程我会在后面详细阐述)中,并为每个DLL维护一个引用计数,当引用计数为 0 时,DLL就从内存中卸载,释放占用的内存。DLL里面可能又引用了其它的DLL,因此加载DLL时是递归形式的,直到加载完Import Table 里描述的所有DLL模块,此时进程初始化部分完成。
创建进程的主线程。当进程的初始化完成后,开始创建进程的主线程,一个进程至少要有一个主线程才能运行,可以说进程只是充当一个容器的作用,而线程才是执行代码的载体。线程是用 CreateThread 这个函数创建的。创建线程时,也和进程相似,系统会创建线程内核对象,初始化线程堆栈。线程堆栈有两个,一个是核心堆栈,由核心态维护;另一个是用户堆栈,运行在用户态下。同样的,线程的引用计数也置为1。
C/C++运行期库初始化。当进程的主线程初始化完成后,并且线程得到了CPU时间片,CPU把CS:IP指向程序入口(OEP),这并档个地址相当重要,因为这是程序运行时第一条指令所在的地址(我们可以使用一些PE辅助工具来查看PE文件的地址信息,注意真实地址==偏移地址 + 基址)。其实,CS:IP指向的地址处是一条JMP指令,它跳转到程序真正的入口函数,入口函数有以下4种形式:
···
mainCRTStartup (用于 ANSI 版本的控制台应用程序 )
wmainCRTStartup ( 用于 Unicode 版本的控制台应用程序 )
WinMainCRTStartup ( 用于 ANSI 版本的窗口应用程序 )
wWinMainCRTStartup ( 用于 Unicode 版本的窗口应用程序)
···
下面再看看入口函数的源码:
···
int XXXCRTStartup(void) //XXX表示不同Windows版本
{ __security_init_cookie() // 完成安全方面的初始化
return__tmainCRTStartup()
}
···
在__tmainCRTStartup中首先调用了GetStartupInfoW函数取得父进程创建本进程时的启动信息, 然后又是一系列的初始化,其中包括C++构造函数的调用,还有静态变量,全局变量的初始化,这些 *** 作是在_initterm这个函数中完成的。接着,我们的 (w)WinMain / (w)main 函数会被调用,到这时,用户程序代码才开始被执行。
具体 *** 作步骤如下:
步骤一:运行能够在Mac上运行Windows的CrossOver,点击【容器】中的【运行命令】;
图1:运行命令
步骤二:在运行命令中,选择你运行的Windows应用程序所在的容器,然后在命令中点击【浏览】找到并选择终端,然后单击【运行】;
图2:运行
步骤三:空宴戚在出现的Wine资源管理器中按照以下路斗陵祥滑径找到【MathType.exe】,双击运行即可。
路径:我的电脑→drive_c(C:)→Program Files→MathType
图3:Wine资源管理器
图4:运行的Windows程序
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)