zoukankan      html  css  js  c++  java
  • Linux下main函数启动过程【程序员自我修养笔记】【自用】

    1. 入口函数和程序初始化

    1.1 程序从main开始吗?

    当程序执行到main函数的第一行时,很多事情都已经完成了:

    【证1】如下是一段C语言代码:

    • 代码中可以看到,在程序刚刚执行到main的时候,全局变量的初始化过程已经结束了(a的值已经确定);

    • main函数的两个参数(argc 和 argv)也被正确的传了进来;

    • 此外,堆和栈的初始化 已经完成;

    • 一些 系统I/O 也被初始化了,因此,可以放心的使用printf和malloc。

    【证2】如下是一段C++ 代码,main之前能够执行的代码还会更多,如下:

     

    在这里,对象v的构造函数,以及用于初始化全局变量g的函数foo都会在main之前调用。

    用于初始化全局变量g的函数: 

    #include <iostream>
    using namespace std;
    
    int foo()
    {
        cout << "这个是用来初始化全局变量的函数" << endl;
        return 1;
    }
    
    
    int g = foo();
    
    
    int main()
    {
        cout << "这是main函数中第一条语句" << endl;
            
        cout << "main函数中直接输出g: " << g << endl;
    
        cout << "这是main函数中最后一条语句" << endl;
    
        return 0;
    }

    作为全局变量的对象的构造函数:

    #include <iostream>    
                           
    using namespace std;   
    
    class MyString {       
    private :
        int len;
    public:
        MyString(int t = 0) : len(t) { cout << "默认构造函数" << t << endl; }
      int getLen() {
            return len;
        }
        ~MyString() { cout << "析构函数调用" << len << endl; }
    
    };
    
    MyString t(1);
    
    int main()
    {
        cout << "这是主函数里面的第一行语句
    ";
    
        MyString a(2);
    
        cout << "这是主函数里最后一行语句
    ";
        
        return 0;
    }

     

    【证3】atexit:特殊的函数,接收一个函数指针作为参数,并保证在程序正常退出(指从main里返回或调用exit函数时),这个函数指针指向的函数会被调用。如:

    •  atexit函数注册的函数的调用时机是在 main结束之后
    • 在main返回之后,它会记录main函数的返回值,调用atexit注册的函数,然后结束进程。

    由这些可以看出,首先运行的代码并不是main的第一行,而是某些特别的代码,这些代码负责准备好main函数执行需要的环境。

    由此可知,程序的入口点实际上是一个 程序的初始化和结束部分,它往往是库的的一部分。

     

    1.2 main函数形式

    (1) Linux下常见的main函数形式:

    • int main(int argc, char *argv[])
    • int main(int argc, char **argv) 

    (2)其他形式:

    • int main()
    • int main(int argc, char **argv, char **envp)  

    (3) main函数的参数:

    • argc:命令行参数的个数(包括最开始的可执行文件名称)
    • argv:字符指针的数组,每个元素都是一个指向字符串的字符指针,即命令行中的每一个参数;命令行参数的列表,数组长度对应argc
    • envp:字符指针的数组,每一个元素是 指向一个环境变量的字符指针; 它里面存放了当前系统的所有环境变量,环境变量指的是一大组字符串,代表系统开始运行时加载一些东西

    3. 分析Linux操作系统如何装载链接并执行程序

    尽量描述简单,不讲源码,先看如下的图:

    Linux程序加载过程如图:

     

    4. 总结

    简短的说,整个在shell中键入./test执行应用程序的过程为:

    • 当前shell进程fork出一个子进程(子shell)

    • 子进程使用execve来脱离和父进程的关系,加载test文件(ELF格式)到内存中。

    • 如果test使用了动态链接库,就需要加载动态链接器(或者叫程序解释器),进一步加载test使用到的动态链接库到内存,并重定位以供test调用。

    • 最后从test的入口地址开始执行test。

     

  • 相关阅读:
    将博客搬至CSDN
    JAVA代码备注
    清空数据库SQL
    实战ASP.NET访问共享文件夹(含详细操作步骤)
    我希望我知道的七个JavaScript技巧 译(转)
    ASP.NET获取客户端网卡使用的MAC地址信息
    JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
    JS屏幕距离参数
    jQuery插件开发精品教程,让你的jQuery提升一个台阶
    jQuery编程的最佳实践
  • 原文地址:https://www.cnblogs.com/douzujun/p/10611834.html
Copyright © 2011-2022 走看看