1、内核执行C程序(用exec)
在调用main函数之前会调用一个特殊的启动程序
它从内核中获取 命令行参数和环境变量 供main函数使用
可执行程序以它作为程序的开始地址
2、C程序的开始和结束
Fig.1 How a C program is started and how it terminate
注1:#include
void exit(int statues);
void _Exit(int statues);
#include
void _exit(int status);
后2个函数立即返回内核
第1个函数首先执行exit handlers,执行flush buffer(all buffered datas be flushed),关掉标准IO库,用fclose关掉所有打开的streams
注2:exit(0) 等同于 return(0)
注3: #include
int atexit(void (*func)(void));
(用于注册exit handlers)
注4:除了exit系列函数,还有信号可以终止进程
3、命令行参数 和 环境变量
for(i = 0; i
ISO C和POSIX.1都确保argv[argc]是NULL,所以
for(i = 0; argv[i] != NULL; i++)
extern char **environ;(字符串数组)
i.e: HOME=/home/sar\0
PATH=:/bin:/usr/bin\0
SHELL=/bin/bash\0
USER=sar\0
LOGNAME=sar\0
最早的时候写成
int main(int argc, char *argv[], char *envp[])
但POSIX.1规定最后一个变量用getenv系列函数来操作
#include
int putenv(char *str);
int setenv(const char *name, const *value, int
rewrite);
int unsetenv(const char *name);
4、C程序内存布局
Fig.2 Typical memory arrangement
注1:.text----CPU执行的机器指令,只读,共享(任何C程序可用)
.data----初始化的数据
.bss----"block started by symbol"(古老的汇编运算符)C declaration
注2:LINUX intel x86下,.text起始于0x08048000,stack底低于
0xC0000000
注3:只有.text 和.data 需要存储,而.bss在程序开始运行之前全部被设置为
0或者NULL
注4:可以用size命令查看各部分大小
$size /usr/sh
注5:一般以静态方式进行编译的可执行文件通常会很大,那是因为以普通方
式(共享库模式)编译,共享库从可执行文件移出了通用库routines,而
通过在内存中为所有程序维持一份拷贝作为参考
5、内存分配
#include
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
// a specified number of objects of a specified size,i
// initialzied to all 0 bits
void *realloc(void *ptr, size_t newsize);
// increases or decreases the size of a previously allocated area
void free(void *ptr);
注1: 分配的内存都被确保很好的aligned
注2: 它们一般都是通过sbrk()系统调用来实现
注3: 通常分配的内存比程序的指定要大点,因为需要一些附加的空间来记录
分配块的打消,下一个分配块的指针等等。所以写这一部分是件不允许
的事情
注4: 忘记free,那么只要程序在运行,进程内存的使用就会持续增加直到
无内存可用,这叫leakage
6、setjmp和longjmp(跨越函数的跳跃)
#include
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
注1:jmp_buf----数组形式,保存所有需要的信息存储到stack直到调用
longjmp
val----非0,作为从setjmp的返回值
if (setjmp(jmbbuffer) != 0)
...
longjmp(jmpbuffer, 1);
注2:这两个函数在编译优化的时候并不影响globlal,static和volatile变量
但是影响automatic和register变量。因为在CPU里的变量和浮点寄存器
在setjmp调用时就已经存储好了,其他存储在内存的变量与longjmp时的
值一样
7、getrlimit和setrlimit(获取和设置系统资源限制)
#include
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
(0 if OK, nonzero on error)
注1:系统资源----比如data段的大小,程序使用的最大空间等等
注2:resource limits影响调用进程和子进程
resource limits可以设置到shell影响所有进程(ulimit命令)
阅读(1938) | 评论(0) | 转发(0) |