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. tp5命令行基础介绍

    查看指令 生成模块 生成文件 生成类库映射文件 生成路由缓存文件 生成数据表字段缓存文件 指令扩展示例 命令行调试 命令行颜色支持 调用命令 查看指令 命令行工具需要在命令行下面执行,请先确保你的ph ...

  2. 【bfs】拯救少林神棍(poj1011)

    Description 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位.然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度.请你 ...

  3. Apache rewrite地址重写

    Apache-rewrite+13个经典案例Apache 重写规则的常见应用(rewrite)一:目的 如何用Apache重写规则来解决一些常见的URL重写方法的问题,通过常见的 实例给用户一些使用重 ...

  4. Python数据结构之栈的实现

    一图胜千言,看图! 代码code: #coding:utf-8 #常见数据结构之栈的实现 class Stack(): #创建Stack类 def __init__(st,size): st.stac ...

  5. 51Nod--1117 聪明的木匠(排序)

    我们可以反过来想,如何将这几个线段组成一根 并且每次花费是组成的两段的和 #include<bits/stdc++.h> using namespace std; #define maxn ...

  6. Linux下使用pv监控进度

    使用pv移动文件 pv example.mkv > /tmp/example.mkv 使用pv监控dd pv -cN source < example.iso | dd of=/dev/s ...

  7. WebClient请求接口,get和post方法

    1,get方式 string URI = "url"; //实例化 WebClient client = new WebClient(); // client.UseDefault ...

  8. 认识Jmeter工具

    1.Apache jmeter 是一个100%的纯java桌面应用,是Apache组织开发的基于java的压力测试工具.它最初被设计用于Web应用测试但后来扩展到其他测试领域,可以用于对静态的和动态的 ...

  9. Ubuntu下安装Goldendict(翻译软件)

    Ubuntu直接安装 sudo apt-get install goldendict 通过源码安装 失败 下载词典 http://blog.sina.com.cn/s/blog_c58823b3010 ...

  10. C++基础知识--DAY4

    今天主要讲的是类中除了构造器析构器以外的拷贝构造器,运算符重载等问题 首先是拷贝构造器 1. copy constructor(拷贝构造) 其也是构造器,其地位和constructor的地位是一样的 ...