UNIX进程的环境
来源:互联网 发布:java 置顶 编辑:程序博客网 时间:2024/06/05 18:16
在学习进程之前,先来了解下进程的执行环境。
main函数
进程总是从main函数开始执行的,我们编程时,程序运行也是从main函数运行的,它的原型如下:
int main(int argc, char *[]argv);
argc是命令行参数的数目,argv是指镇数组,即指向指针的指针,可以写代码测试一下:
#include<stdio.h>
int main(int argc, char *argv[])
{
int i;
for(i=0; i<argc; i++)
printf("argv[%d]:%s\n",i,argv[i]);
exit(0);
}
输出:
linux:/home # ./test this is a test program
argv[0]:./test
argv[1]:this
argv[2]:is
argv[3]:a
argv[4]:test
argv[5]:program
在调用main函数之前,内核先调用一个特殊的启动例程,它从内核取得命令行参数和环境变量的值,可执行程序文件将此启动例程指定为程序的起始地址。内核使用exec函数来启动C程序。
进程终止
有5种方式可以终止进程
(1)正常终止
(a)从main函数返回
(b)调用exit
(c)调用_exit
(2)异常终止
(a)调用abort
(b)由一个信号终止
在上面的正常终止中有exit和_exit,区别在于:_exit调用后立即进入内核;而exit则会先执行一些清除工作(包括调用执行各种终止处理程序,关闭所有标准I/O流等),然后在进入内核。它们定义如下:
#include<stdlib.h>
void exit(int status);
#include<unistd.h>
void _exit(int status);
使用了不同的头文件,因为exit是右ANSI C说明的,而_exit是由POSIX.1说明的。
atexit函数
我们可以在进程中登记一些函数(最多32个),这些函数由exit调用。这样的函数叫做终止处理程序(exit handler),有atexit函数来登记。这点看起来有点像类的析构函数。
#include<stdlib.h>
int atexit(void (*func)(void));
其参数是一个函数地址。exit调用顺序与登记顺序相反,先登记后调用(像栈),同一个函数可以被登记多次。
环境表
进程的运行都有一个环境,环境的信息存储在环境表里面。环境表是一个字符指针数组,其中每个指针包含一个以NULL结束的字符串的地址。全局变量environ包含了该指针数组的地址:
extern char **environ;
程序的存储空间布局
C程序由以下几部分组成:
正文段:也叫代码段,是CPU执行的机器指令。正文段一般可以共享的,且是只读的。
初始化数据段:也叫做数据段,包含程序中已经初始化的全局变量和静态变量。
非初始化数据段:也叫做bss段,包含未初始化的全局变量和静态变量,在程序执行之前有内核初始化为0。不在代码中存储器初始值,可以减小代码的大小。
栈:自动存储变量以及每次函数调用时所需保存的信息都放在此段中。每次函数调用时,其返回地址、以及寄存器中的变量都放在栈中。新被调的函数在栈上为其自动和临时变量分配存储空间。
堆:进行动态分配的变量。需要手动释放。堆位于未初始化数据段的顶和栈底之间。
存储器的分配:
可以参考这里
setjmp和longjmp
在C语言中,可以使用goto语言(虽然不建议使用),但是goto语句不能跳跃函数。执行这个跳转功能的函数时setjmp和longjmp。这两个函数对于处理发生在很深的嵌套调用中的出错情况非常好用。递归调用返回时只能返回到上一层函数,这两个函数可以使其跳出递归调用。
main函数
进程总是从main函数开始执行的,我们编程时,程序运行也是从main函数运行的,它的原型如下:
int main(int argc, char *[]argv);
argc是命令行参数的数目,argv是指镇数组,即指向指针的指针,可以写代码测试一下:
#include<stdio.h>
int main(int argc, char *argv[])
{
int i;
for(i=0; i<argc; i++)
printf("argv[%d]:%s\n",i,argv[i]);
exit(0);
}
输出:
linux:/home # ./test this is a test program
argv[0]:./test
argv[1]:this
argv[2]:is
argv[3]:a
argv[4]:test
argv[5]:program
在调用main函数之前,内核先调用一个特殊的启动例程,它从内核取得命令行参数和环境变量的值,可执行程序文件将此启动例程指定为程序的起始地址。内核使用exec函数来启动C程序。
进程终止
有5种方式可以终止进程
(1)正常终止
(a)从main函数返回
(b)调用exit
(c)调用_exit
(2)异常终止
(a)调用abort
(b)由一个信号终止
在上面的正常终止中有exit和_exit,区别在于:_exit调用后立即进入内核;而exit则会先执行一些清除工作(包括调用执行各种终止处理程序,关闭所有标准I/O流等),然后在进入内核。它们定义如下:
#include<stdlib.h>
void exit(int status);
#include<unistd.h>
void _exit(int status);
使用了不同的头文件,因为exit是右ANSI C说明的,而_exit是由POSIX.1说明的。
atexit函数
我们可以在进程中登记一些函数(最多32个),这些函数由exit调用。这样的函数叫做终止处理程序(exit handler),有atexit函数来登记。这点看起来有点像类的析构函数。
#include<stdlib.h>
int atexit(void (*func)(void));
其参数是一个函数地址。exit调用顺序与登记顺序相反,先登记后调用(像栈),同一个函数可以被登记多次。
环境表
进程的运行都有一个环境,环境的信息存储在环境表里面。环境表是一个字符指针数组,其中每个指针包含一个以NULL结束的字符串的地址。全局变量environ包含了该指针数组的地址:
extern char **environ;
程序的存储空间布局
C程序由以下几部分组成:
正文段:也叫代码段,是CPU执行的机器指令。正文段一般可以共享的,且是只读的。
初始化数据段:也叫做数据段,包含程序中已经初始化的全局变量和静态变量。
非初始化数据段:也叫做bss段,包含未初始化的全局变量和静态变量,在程序执行之前有内核初始化为0。不在代码中存储器初始值,可以减小代码的大小。
栈:自动存储变量以及每次函数调用时所需保存的信息都放在此段中。每次函数调用时,其返回地址、以及寄存器中的变量都放在栈中。新被调的函数在栈上为其自动和临时变量分配存储空间。
堆:进行动态分配的变量。需要手动释放。堆位于未初始化数据段的顶和栈底之间。
存储器的分配:
可以参考这里
setjmp和longjmp
在C语言中,可以使用goto语言(虽然不建议使用),但是goto语句不能跳跃函数。执行这个跳转功能的函数时setjmp和longjmp。这两个函数对于处理发生在很深的嵌套调用中的出错情况非常好用。递归调用返回时只能返回到上一层函数,这两个函数可以使其跳出递归调用。
0 0
- UNIX进程的环境
- apue:UNIX进程的环境
- unix进程的环境--unix环境高级编程读书笔记
- unix环境高级编程-unix的进程环境
- 第七章 UNIX进程的环境
- chapter 7 UNIX进程的环境
- UNIX进程环境小结
- Unix进程环境
- UNIX进程环境
- Unix环境编程-进程环境
- Unix环境进程间通信
- Unix环境程序之进程
- UNIX环境高级编程---- 进程
- Linux/UNIX之进程环境
- Unix 环境编程: 进程控制
- UNIX进程环境及关系
- UNIX再学习 -- 进程环境
- 《Unix环境高级编程》:单实例守护进程的实现
- RDF与SPARQL的学习资料
- struts2 03 action
- Oracle DataGuard ora-16198
- MongoDB基本用法(增删改高级查询、mapreduce)
- hdu4968(选n个物品恰好装满的背包)
- UNIX进程的环境
- 【UVA】230 - Borrowers(map模拟)
- jsonobject 遍历取值
- 美国家长如何培养孩子的财富管理意识
- nginx反向代理,动静态分离,缓存
- win7 的64位操作系统安装oracle11g之后navicat链接不上oracle服务器的解决办法
- 句柄和指针【英国某著名计算及图形面试题】
- Cookie和Session专题
- 一个和美很动人的人生 你有这样回想过你的人生吗?发现它曾带给你的美丽