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 ;
} 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函数启动过程【程序员自我修养笔记】【自用】的更多相关文章
- [oracle] oracle的三种密码验证机制以及在windows和linux下的不同启动过程
oracle数据库的密码验证机制: ① 操作系统验证 拥有SYSDBA和SYSOPER的用户用该方式验证此时数据库无需启动,也无需开启监听和实例服务. 要求:本地组ora_dba中有该操作系统的登录用 ...
- linux编程之main()函数启动过程【转】
转自:http://blog.csdn.net/gary_ygl/article/details/8506007 1 最简单的程序 1)编辑helloworld程序,$vim helloworld. ...
- pwn学习日记Day10 《程序员自我修养》读书笔记
第一章 从 Hello world 说起 抛出问题: 1.程序为什么要被编译器编译后才能执行? 2.编译器在把C语言程序转换成可以执行的机器码的过程中做了什么,怎么做的? 3.最后编译出来的可执行文件 ...
- ***IT程序员自我修养和情商提升文章
低情商的13个表现 --------------------------------------------------------------------- — THE END —
- Linux移植之内核启动过程start_kernel函数简析
在Linux移植之内核启动过程引导阶段分析中从arch/arm/kernel/head.S开始分析,最后分析到课start_kernel这个C函数,下面就简单分析下这个函数,因为涉及到Linux的内容 ...
- 对于linux下system()函数的深度理解(整理)
原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...
- 转:对于linux下system()函数的深度理解(整理)
这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...
- (笔记)Linux下system()函数的深度理解(整理)
注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...
- Linux下使用vim编辑C程序
这几天在系统能力班自学linux,加上最近大数据课上开始使用linux,我在这里总结一下,linux下使用vim编辑c程序的一些问题. 大数据课上是直接使用micro来编辑的,我这里只是简单的说明一下 ...
随机推荐
- 【BZOJ2333】【SCOI2011】棘手的操作 treap合并
题目大意 有\(n\)个节点,标号从1到\(n\),这\(n\)个节点一开始相互不连通.第\(i\)个节点的初始权值为\(a_i\),接下来有如下一些操作: \(U~x~y\):加一条边,连接第\(x ...
- mysql Navicat 连接MySQL 8.0.11 出现2059错误
https://www.cnblogs.com/lifan1998/p/9177731.html 原因 mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8 ...
- [国家集训队]整数的lqp拆分
我们的目标是求$\sum\prod_{i=1}^m F_{a_i}$ 设$f(i) = \sum\prod_{j=1}^i F_{a_j}$那么$f(i - 1) = \sum\prod_{j=1}^ ...
- BZOJ 4242: 水壶(Kruskal重构树 + Bfs)
题意 一块 \(h ∗ w\) 的区域,存在障碍.空地.\(n\) 个建筑,从一个建筑到另一个建筑的花费为:路径上最长的连续空地的长度. \(q\) 次询问:从建筑 \(s_i\) 到 \(t_i\) ...
- python3 hashlib模块
hashlib是一个加密模块,可以将明文加密为密文: md5,sha加密:过程不可逆转.
- Double.valueOf(0.0D) 分析
private Double price = Double.valueOf(0.0D); 查看Java API 文档如下: doubleValue public double doubleValue( ...
- 【BZOJ4784】[ZJOI2017]仙人掌(Tarjan,动态规划)
[BZOJ4784][ZJOI2017]仙人掌(Tarjan,动态规划) 题面 BZOJ 洛谷 题解 显然如果原图不是仙人掌就无解. 如果原图是仙人掌,显然就是把环上的边给去掉,变成若干森林连边成为仙 ...
- nodejs的某些api~(三)net模块
net模块和http模块是node最重要的两个模块,前者是基于TCP的封装,后者的本质也是TCP.他们通过 tcp通信,建立一个可以收发消息的web服务器.我在写的作品里面用的express也是封装的 ...
- Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2) C D
C - Maximum Subrectangle 因为是两个数组相乘的到的 矩阵所以 a(i ->j)*b(x->y) 的面积 就是 a(i ->j) 的和乘与b(x-> ...
- 工厂方法模式(Factory Method)和抽象工厂模式(Abstact Factory)
分类 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的.工厂模式在<Java 与模式>中分为三类:1)简单工厂模式(Simple Facto ...