- c 程序的入口是 main 函数,签名为
int main(int argc, char *argv[])
,内核在调用 main 之前先调用特殊的启动例程(启动例程从内核获得命令行参数和环境变量) - 进程终止的方式
- 正常终止
- 从 main 返回
- 调用 exit (先进行清理处理,再返回内核)
- 调用 _exit 或 _Exit (立即进入内核)
- 最后一个县城从启动例程返回
- 从最后一个线程调用 pthread_exit
- 异常终止
- 调用 abort
- 接到信号
- 最后一个线程对取消请求作出响应
- 正常终止
- 进程终止时可以执行登记的回调函数
- 函数执行顺序与登记顺序相反
- 一个函数重复登记会被执行多次
- C 程序如何启动和终止
- 命令行参数表:每个进程一张,记录命令行参数,
argv[0]
是可执行文件 - 环境表:每个进程都有一张,是一个字符指针数数组,每个指针包含一个 C 字符串地址,指向环境字符串
- C 程序存储空间布局
- 正文段(text segment):CPU 执行的机器执行
- 只读
- 可共享,在存储器中只有一个副本
- 初始化数据段:包含需要明确赋值的变量
- 未初始化数据段(bss,block started by symbol):在程序开始执行前,内核将此段中数据初始化为 0 或空指针
- 栈:自动变量及函数调用所需的信息
- 函数返回地址
- 调用者的环境信息
- 临时变量
- 堆:动态存储分配
- 示意图
- size 命令报告 text segment, data segment, bss 长度
- 正文段(text segment):CPU 执行的机器执行
- 共享库:可执行文件中不需要包含公用的库函数,只需要在所有进程都可引用的存储区中保存一个副本,减少了每个可执行文件的长度,并且可以在不用重新链接的情况下,升级共享库
- 进程存储空间分配函数,通常使用 sbrk 系统调用实现
- malloc 分配给定大小的内存
- calloc 为指定数量指定长度的对象分配存储空间,分配的每一个 bit 都初始化为 0
- reallac 增加或减少已分配区的长度,长度增长时可能改变内存空间初始值
- free 释放已分配的内存,通常呗放入可用存储区池
- 跨函数的跳转: setjmp & longjmp 在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中
int setjmp(jmp_buf env)
jmp_buf 是某种形式的数组,包含用来恢复栈状态的所以信息,通常声明为全局变量,调用setjmp
的地方通常是设置跳转点的地方void longjmp(jmp_buf env, int val)
jmp_buf 同setjmp
,val 为 setjmp 处的返回值- 自动变量、寄存器变量和易失变量
- volatile 变量、全局变量、静态变量在 longjmp 时会保持不变,不会被 longjmp 回滚
- 本质上是主存中的变量在 longjmp 后会保持 longjmp 时的值,而寄存器变量在某些情况会被回滚
- getrlimit / setrlimit 获取或设置资源限制