创意电子

标题: Mono源码学习-1 [打印本页]

作者: 秋风技术    时间: 2021-10-18 06:30
标题: Mono源码学习-1
因由

结束了一年多的出差,回到了公司上班,最近一直在想着博客的改版,连博客也没怎么写了,正好这两天不怎么忙,便想起看看mono的源码,至于为什么看mono源码而不是选择.Net Core源码,Mono源码是纯c的,看起来更容易一些,不需要c++的知识.实在.Net Core源码直接用VS调试还是很方便的.不过source insight对c++支持的不是很好.阅读Mono源码使用source insight还是很方便的.
在Github看Mono已经把zlib源码加入到Mono源码,在编译源码的时候,不用手动链接zlib静态库了
阅读源码从mini/main.c开始.
函数名以g_开头的,是eglib封装的工具函数.重要用于简化操作.如g_new0/g_free
屏蔽系统API差别

这里以mono_pagesize为例.先认识Windows的源码.
//获取系统页巨细int mono_pagesize(void){        SYSTEM_INFO info;        static int saved_pagesize = 0;            //saved_pagesize 使用static声明        if (saved_pagesize)                return saved_pagesize;            //第二次调用mono_pagesize函数,直接返回saved_pagesize        GetSystemInfo(&info);                     //第一次调用mono_pagesize函数,调用GetSystemInfo系统函数        saved_pagesize = info.dwPageSize;   //将获取到系统页巨细赋值给saved_pagesize         return saved_pagesize;}Linux源码:
int mono_pagesize (void){        static int saved_pagesize = 0;        if (saved_pagesize)                return saved_pagesize;        // Prefer sysconf () as it's signal safe.#if defined (HAVE_SYSCONF) && defined (_SC_PAGESIZE)  //判定是否有sysconf系统函数        saved_pagesize = sysconf (_SC_PAGESIZE); #else        saved_pagesize = getpagesize ();   //不支持sysconf系统函数#endif        return saved_pagesize;}根据宏判定是否支持sysconf系统调用.

                               
登录/注册后可看大图
Windows和Linux 系统页巨细默以为4096
实在Windows默认的页巨细也是4096,这里没有截取Windows系统页巨细.
mono_main 主函数


                               
登录/注册后可看大图
初学mono源码,mono加载过程
main.c        int main(void)                                                           //Windows 通过CommandLineToArgvW获取参数        int main(int argc, char* argv[])               //Linux或Unix及Mac                int mono_main_with_options(argc, argv)driver.c      //主函数                        int mono_main(argc, argv)      coree.c                           //加载mscoree.dll,Windows独有的, c# exe(Windows下)实验的时候通过ntdll->mscoree.dll->mscorlib.dll                                void mono_load_coree(const char* exe_file_name)  mono-config.c                                        //设置lib和etc,具体可以看 https://www.qiufengblog.com/articles/mono-config.html                                void mono_config_parse (const char *filename)    mini-runtime.c         //mono CLR运行时初始化,返回MonoDomain                                MonoDomain* mini_init(const char* filename, const char* runtime_version) dirver.c                                        static void main_thread_handler (gpointer user_data)domain.c                                                //根据domain,加载程序集(并没有实验)                                                MonoAssembly* mono_domain_assembly_open(MonoDomain* domain, const char* name)driver.c                                                //根据domain,实验程序集                                                int mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])mini-runtime.c                                                //清理domain,释放资源                                                void mini_cleanup(MonoDomain* domain)简化之后的代码:
//函数原型MonoDomain* mini_init(const char* filename, const char* runtime_version);//mono 主函数//函数去除很多代码int mono_main(int argc, char* argv[]){        //        //去除剖析参数处理,背面用到单独阐明        //        MonoThreadArgs main_args;        int i;        int mixed_mode = FALSE;        if (mixed_mode)        {                mono_load_coree(argv);        }        mono_config_parse(config_file);        mono_set_defaults(mini_verbose_level, opt);        MonoDomain* domain = mini_init(argv, forced_version);        main_args.domain = domain;        main_args.file = aname;        main_args.argc = argc - i;        main_args.argv = argv + i;        main_args.opts = opt;        main_args.aot_options = aot_options;        main_thread_handler(&main_args);        mono_thread_manage();        mini_cleanup(domain);        i = mono_environment_exitcode_get();        return i;}MonoDomain* mini_init(const char* filename, const char* runtime_version){        //1.初始化很多东西        //2.注册回调函数        MonoDomain* domain;        //通过mono program.exe 没有指定--runtime=v4.0.30319 ,runtime_version不为真的        if (runtime_version)                          {                domain = mono_init_version(filename, runtime_version);        }        else        {                domain = mono_init_from_assembly(filename, filename);        }        //还要处理很多东西        //xxx        //xxx        return domain;}在fixed模式下,mono如何加载mscoree.dll

基于mono_load_coree函数源码,改动而来,重要是动手练习一下.也顺便一些系统函数的调用.
typedef unsigned __int16 gunichar;//1. 根据GetSystemDirectory系统函数,获取系统目次//2. 将获取到系统目次和mscoree.dll进行拼接//3. 通过LoadLibrary加载到内存HMODULE load_coree(){        UINT len = GetSystemDirectory(NULL, 0);        printf("%d\n", len);        printf("unsigned __int16 size:%d\n", sizeof(gunichar));        gunichar* dir = calloc(1, (len + 12) * sizeof(gunichar));        GetSystemDirectory(dir, len);        //打印系统路径        printf("system dir:%ls\n", dir);        if (dir[len - 1] != L'\\')        {                dir[len - 1] = L'\\';        }        //拼接dll路径          memcpy(&dir[len], L"mscoree.dll", 12 * sizeof(gunichar));        printf("dir :%ls\n", dir);        //LoadLibrary (将dll加载内存中,将文件的起始位置返回)         //LoadLibrary和FreeLibrary 配对使用,        HMODULE module = LoadLibraryW(dir);        return module;}//验证该句柄是否位pe文件的起始位置int validate_pe(HMODULE hModule){        PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)hModule;        DWORD magic = dos_header->e_magic;        char* a = (char*)&magic;        printf("%s\n", a);        if (magic == IMAGE_DOS_SIGNATURE)        {                printf("pe dos header Signature:MZ\n");        }        PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)((char*)dos_header + dos_header->e_lfanew);        if (nt_header->Signature == IMAGE_NT_SIGNATURE)        {                printf("pe dos header Signature:PE\n");        }        return 0;}要不是看了源码,怎么也没想到LoadLibrary返回的HMODULE,竟然是文件在内存中的起始地址.
这是2019年所写,不是学Mono写的第一篇,只是Mono代码一直改进,如今Mono源码已经和.Net源码放在一起了,今天本想在本地用VS编译Mono的,编译失败了,如今编译Mono源码需要使用CMake天生VS解决方案.
在2021年,Mono侧重于移动端和Blazor(WebAssmebly), .Net Core侧重于服务端(说Web也不符合,由于Blazor客户端是用Mono)




欢迎光临 创意电子 (https://wxcydz.cc/) Powered by Discuz! X3.4