当内核执行C程序时,在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址。启动例程从内核取得命令行参数和环境变量值,而后调用main函数。函数
存在8种方式终止进程:布局
5种正常终止:spa
1. 从main返回命令行
2. 调用exit线程
3. 调用_exit或者_Exit指针
4. 最后一个线程从启动例程中返回.code
5. 最后一个线程调用pthread_exit.对象
3种异常终止:进程
1. 调用abort内存
2. 接收信号并终止.
3. 最后一个线程对取消请求作出响应.
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
_exit和_Exit会立马返回到内核, 而exit则会清除线程后返回内核.
在main函数中, 若是没有显式return/exit, 则默认返回0:
#include <stdio.h> int main(void) { printf("hello world\n"); }
终端输出:
leicj@leicj:~/test$ ./a.out hello world leicj@leicj:~/test$ echo $? 0
一个进程能够登记多达32个函数,这些函数将由exit自动调用。咱们称这些函数为终止处理程序,并调用atexit函数来登记这些函数。
终止处理程序:
#include <stdio.h> static void my_exit1(void); static void my_exit2(void); int main(void) { if (atexit( my_exit2 ) != 0) printf("can't register my_exit2\n"); if (atexit( my_exit1 ) != 0) printf("can't register my_exit1\n"); if (atexit( my_exit1 ) != 0) printf("can't register my_exit1\n"); printf("main is done\n"); return 0; } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); }
程序输出:
leicj@leicj:~/test$ ./a.out main is done first exit handler first exit handler second exit handler
1. 正文段:由CPU执行的机器指令部分
2. 初始化数据段:包含了程序中需明确的赋初值的变量
3. 非初始化数据段: 声明在函数以外的变量存放的地方, 一般会被内核初始化为0或者null.
4. 栈:自动变量以及每次函数调用时所需保存的信息都存放在此段中
5. 堆:进行动态分配
leicj@leicj:~/test$ size /usr/bin/cc /bin/sh text data bss dec hex filename 902577 8048 9696 920321 e0b01 /usr/bin/cc 143301 4792 11312 159405 26ead /bin/sh
ISO C定义三个函数用于分配内存, 一个函数用于释放内存.
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
returns: 成功返回非空指针, 失败返回NULL
void free(void *ptr);
malloc: 分配特定字节的内存, 初始值不肯定.
calloc: 分配特定数量的对象, 每一个对象的大小为size.
realloc: 用于增长或减小内存.
#include <stdio.h> #include <stdlib.h> extern char *environ; int main( void ) { putenv("hello=world"); setenv("hello1", "world1", 0); printf("%s\n", getenv("hello")); printf("%s\n", getenv("hello1")); unsetenv("hello"); unsetenv("hello1"); return 0; }
程序输出:
leicj@leicj:~/test$ ./a.out world world1
#include <stdio.h> #include <setjmp.h> jmp_buf jmpbuffer; void fun1(); void fun2(); int main( void ) { int bFun1 = 0; int bFun2 = 0; bFun1 = setjmp(jmpbuffer); bFun2 = setjmp(jmpbuffer); printf("the return value is:%d---%d\n", bFun1, bFun2); printf("main done\n"); if ( bFun1 || bFun2 ) { exit( 0 ); } fun1(); fun2(); return 0; } void fun1() { printf("fun1\n"); longjmp( jmpbuffer, 1 ); } void fun2() { printf("fun2\n"); longjmp( jmpbuffer, 2 ); }
程序输出:
leicj@leicj:~/test$ ./a.out the return value is:0---0 main done fun1 the return value is:0---1 main done