本文章介绍进程的环境
1.main函数
c程序总是从main函数开始执行的,其原型是
int main(int argc, char **argv);
//argc是命令行参数的个数
//argv是指向参数的各个指针所构成的数组
2.进程终止
有8种方式可以让进程终止,其中前5种为正常终止
1.从main返回
2.调用exit
3.调用_exit或_Exit
4.最后一个线程从其启动例程返回
5.最后一个线程调用pthread_exit
6.调用abort
7.接到一个信号并终止
8.最后一个线程对取消请求做出响应
3.exit函数
#include
void exit(int status);
void _Exit(int status);
#include
void _exit(int status);
//_exit和_Exit立即进入内核,exit则进行一些清理处理在进入内核
由于历史原因,exit函数总是要执行一个标准I/O库的清理关闭操作fclose(),这将造成所有的缓冲区数据都被冲洗
unix shell:#echo $? 可以显示程序的返回值
4.atexit函数
按照ISO C规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。
我们称这些函数为终止处理函数,用下面的函数来登记这些函数:
#include
int atexit(void (*func)(void));
//成功返回0,出错返回非零值
在程序即将结束的时候,调用登记过的函数,但是函数的执行顺序和登记的顺序是相反的
根据ISO C和POSIX.2,exit函数首先调用各个终止处理函数,然后按需多次调用fclose函数,关闭所有打开的流。
POSIX.1扩展了ISO C的标准,它指定如若程序调用exec函数族的任一函数,则将清除所有已安装的终止处理函数。
5.命令行参数
当执行一个程序的时候,调用exec的进程可将命令行参数传递给新程序。
程序如下:
- #include <stdio.h>
- #include <stdlib.h>
- int main(int argc, char **argv)
- {
- int i;
- for (i = 0; i < argc; i++) {
- printf("argv[%d] = %s.\n", i, argv[i]);
- }
- exit(EXIT_SUCCESS);
- }
6.环境表
每个程序都会接受一张环境表,这个表和参数表一样是一个字符指针数组,每个指针包含以NULL介绍给有的c字符串的地址
在程序中声明
extern char **environ;
在程序中输出环境表
for (i = 0; environ[i] != NULL; i++) {
printf("environ[%d]: %s.\n", i, environ[i]);
}
环境表的每个字段的格式都是name=value
7.c语言的存储空间布局
从历史上将c语言一直由以下几部分组成
正文段:这是由CPU执行的机器指令部分。正文段是共享的,在存储器中只有一个副本。另外正文段通常是只读的
初始化数据段: 通常将此段称为数据段,它包含了程序中需明确的赋初值的变量。如:
c语言中:
int i = 0;
此变量存在初始化数据段中
非初始化数据段:通常将此段称为bss段。在程序开始执行之前,内核将此段中的数据初始化为0或空指针。
栈:自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次调用函数时,其返回地址以及调用者的环
境信息都存放到栈中。然后,最近被调用的函数在栈上为其自动和临时变量分配存储空间。通过这种方式使用栈,
可以递归调用c函数。递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的环境变量不会
影响到另一个函数调用实例中的变量。
堆:通常在堆中进行动态存储分配。堆位于非初始化数据段和栈之间。
size命令则报告正文段,数据段和bss段的长度
8.存储器分配
ISO C说明了三种用于存储器空间分配的函数
#include
void *malloc(size_t size);
//分配指定字节数的存储区。此存储区中的初始值不确定。
void *calloc(size_t nobj, size_t size);
//在内存的动态存储区中分配nobj个长度为size的连续空间,存储区中初始值均为0。
void *realloc(void *ptr, size_t newsize);
//将ptr所指向的存储区重新分配,当增加长度的时候新增的存取区中的初始值不确定。
//这三个函数若成功返回非空指针,失败返回NULL
void free(void *ptr);
//释放存储区空间
9.setjmp和longjmp
在c语言中,goto语句是不能跨越函数的,最稳妥安全的跨越函数跳转的函数是setjmp和longjmp
#include
int setjmp(jmp_buf env);
//若直接调用返回0,若从longjmp调用返回非0值
void longjmp(jmp_buf env, int val);
//setjmp设置返回的位置,longjmp中的val是跳转后的返回值
阅读(1696) | 评论(0) | 转发(0) |