Linux 进程环境
关于main函数
内核执行C代码时会使用一个exec函数,在调用main之前会调用一个特殊的启动例程。可执行程序文件会把这个启动例程指定为程序的起始位置(链接的时候设置)。启动例程会先从kernel获取命令行参数和环境变量值,再执行main
关于退出函数从用户态返回内核态
- 3个函数,_exit和_Exit立即进入kernel,exit会先执行一些清理处理(标准I/O的清理关闭操作,对所有打开流执行fclose),再返回kernel。所以对于main来说return(0) 和 exit(0)等价
- 一个进程可以登记至多32个函数,在进程结束时exit()会自动调用之前登记的函数。用atexit()来登记需要登记的函数,main()结束后exit()按照先进后出顺序执行登记函数
- 程序启动/终止图:
- kernel执行程序的唯一方法是调用exec(),进程自愿终止的唯一方法是exit()/_exit()/_Exit(),或者由signal非自愿终止
关于环境表
每个程序会接收一张环境表(字符指针数组),全局变量environ会包含该指针数组的地址:
关于存储空间布局
- text段:只读,可共享,就是存储程序逻辑相关代码的内存
- data段:包含程序中需明确赋初值的变量,比如赋初值的全局变量
- bss段:存储未初始化变量,程序执行前置为0或null,比如未初始化的全局变量
- stack:存函数中的局部变量,返回地址,调用者环境信息等
- heap:malloc()/new()等动态申请的内存
关于共享库
共享库可以时可执行文件不需要包含公共库函数,只需要动态链接就可以了。好处是减小文件大小,更新库函数不需要重新编译,缺点是第一次调用共享库函数时时间开销大一点