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 ;
} int g = foo(); int main()
{
cout << "这是main函数中第一条语句" << endl; cout << "main函数中直接输出g: " << g << endl; cout << "这是main函数中最后一条语句" << endl; return ;
}

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

#include <iostream>    

using namespace std;   

class MyString {
private :
int len;
public:
MyString(int t = ) : len(t) { cout << "默认构造函数" << t << endl; }
int getLen() {
return len;
}
~MyString() { cout << "析构函数调用" << len << endl; } }; MyString t(); int main()
{
cout << "这是主函数里面的第一行语句\n"; MyString a(); cout << "这是主函数里最后一行语句\n"; return ;
}

【证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。

Linux下main函数启动过程【程序员自我修养笔记】【自用】的更多相关文章

  1. [oracle] oracle的三种密码验证机制以及在windows和linux下的不同启动过程

    oracle数据库的密码验证机制: ① 操作系统验证 拥有SYSDBA和SYSOPER的用户用该方式验证此时数据库无需启动,也无需开启监听和实例服务. 要求:本地组ora_dba中有该操作系统的登录用 ...

  2. linux编程之main()函数启动过程【转】

    转自:http://blog.csdn.net/gary_ygl/article/details/8506007 1 最简单的程序  1)编辑helloworld程序,$vim helloworld. ...

  3. pwn学习日记Day10 《程序员自我修养》读书笔记

    第一章 从 Hello world 说起 抛出问题: 1.程序为什么要被编译器编译后才能执行? 2.编译器在把C语言程序转换成可以执行的机器码的过程中做了什么,怎么做的? 3.最后编译出来的可执行文件 ...

  4. ***IT程序员自我修养和情商提升文章

    低情商的13个表现 --------------------------------------------------------------------- — THE END —

  5. Linux移植之内核启动过程start_kernel函数简析

    在Linux移植之内核启动过程引导阶段分析中从arch/arm/kernel/head.S开始分析,最后分析到课start_kernel这个C函数,下面就简单分析下这个函数,因为涉及到Linux的内容 ...

  6. 对于linux下system()函数的深度理解(整理)

    原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...

  7. 转:对于linux下system()函数的深度理解(整理)

    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...

  8. (笔记)Linux下system()函数的深度理解(整理)

    注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...

  9. Linux下使用vim编辑C程序

    这几天在系统能力班自学linux,加上最近大数据课上开始使用linux,我在这里总结一下,linux下使用vim编辑c程序的一些问题. 大数据课上是直接使用micro来编辑的,我这里只是简单的说明一下 ...

随机推荐

  1. 【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆

    题目大意 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots ,c_n\).如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合\(\{c_1,c_2,\ldots ,c_n\ ...

  2. 【BZOJ3132】【TYVJ1716】上帝造题的七分钟 二维树状数组

    题目大意 维护一个\(n\times m\)的矩阵,有两种操作: \(1~x_1~y_1~x_2~y_2~v\):把\((a,b),(c,d)\)为顶点的矩形区域内的所有数字加上\(v\). \(2~ ...

  3. 如何将Drawable转为Bitmap?

    本文选自StackOverflow(简称:SOF)精选问答汇总系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术.本文将讲解如何将Drawable转为Bitmap ...

  4. bzoj3427小P的牧场(斜率优化dp)

    小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧 ...

  5. Hyper-V

    docker与vm同时安装,会导致虚拟机无法启动及网络不通等问题,解决方法分为两步. 1.在网络连接中禁用vEthernet连接. 2.控制面板>程序>程序和功能中 >启用或关闭wi ...

  6. Jupyter-Notebook服务器自定义密码

    往期回顾 Anaconda安装:https://www.cnblogs.com/dotnetcrazy/p/9158715.html 基本知识导航篇:https://www.cnblogs.com/d ...

  7. 分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】

    原创: dqqzj SpringForAll社区 今天 Spring Cloud Sleuth Span是基本的工作单位. 例如,发送 RPC是一个新的跨度,就像向RPC发送响应一样. 跨度由跨度唯一 ...

  8. wildfly 10上使用最新的 Hibernate ORM OGM

    ORM是关系型数据库连接:ogm是No sql数据库连接,Mongo, redis等. 1,下载ogm zip包,解压到wildfly_home\modules\system\layers\base, ...

  9. Qt5应用改变窗口大小时出现黑影

    解决方法 在启动程序时,添加-platform wayland参数 添加QT_QPA_PLATFORM=wayland-egl到系统环境变量 注意:改完后虽然没有黑影,但软件图标显示不正常,也不能正常 ...

  10. 省选前的JOI

    RT,发现找不到题,于是又开了新坑 JOI特色:重思考,代码难度(相比NOI系列)基本没有 (省选前到处挖坑2333) JOI 2017 Final 焚风现象 差分,莫得了 (不是看到200ms就tm ...