U N I X进程的环境

main函数
C程序总是从m a i n函数开始执行。m a i n函数的原型是:
int main(int  a rg c, char * a rg v[ ] ) ;
其中,a rg c是命令行参数的数目,a rg v是指向参数的各个指针所构成的数组。

当内核起动C程序时(使用一个e x e c函数),在调用m a i n前先调用一个特殊的起动例程。可执行程序文件将此起动例程指定为程序的起始地址——这是由连接编辑程序设置的,而连接编辑程序则由 C编译程序(通常是c c )调用。起动例程从内核取得命令行参数和环境变量值,然后为调用m a i n函数作好安排。


进程终止
有五种方式使进程终止:
(1) 正常终止:
(a) 从m a i n返回。
(b) 调用e x i t。
(c) 调用_ e x i t。
(2) 异常终止:
(a) 调用a b o r t (见第1 0章)。
(b) 由一个信号终止


exit和_ e x i t函数
e x i t和_ e x i t函数用于正常终止一个程序: _ e x i t立即进入内核,e x i t则先执行一些清除处理
(包括调用执行各终止处理程序,关闭所有标准I / O流等),然后进入内核。
#include <stdlib.h>
void exit(int  s t a t u s) ;
#include <unistd.h>
void _exit (int  s t a t u s) ;


环境表
每个程序都接收到一张环境表。与参数表一样,环境表也是一个字符指针数组,其中每个
指针包含一个以n u l l结束的字符串的地址。全局变量e n v i r o n则包含了该指针数组的地址。
extern char **environ;
例如:如果该环境包含五个字符串,那么它看起来可能如图 7 - 2中所示。


图7-2 由五个字符串组成的环境
其中,每个字符串的结束处都有一个n u l l字符。我们称e n v i r o n为环境指针,指针数组为环境表,
其中各指针指向的字符串为环境字符串。


虚拟地址



C程序的存储空间布局
由于历史原因,C程序一直由下列几部分组成:
• 正文段。这是由C P U执行的机器指令部分。通常,正文段是可共享的,所以即使是经常
执行的程序(如文本编辑程序、C编译程序、s h e l l等)在存储器中也只需有一个副本,另外,正
文段常常是只读的,以防止程序由于意外事故而修改其自身的指令。
• 初始化数据段。通常将此段称为数据段,它包含了程序中需赋初值的变量。例如, C程
序中任何函数之外的说明:
int maxcount = 99;
使此变量以初值存放在初始化数据段中。
• 非初始化数据段。通常将此段称为 b s s段,这一名称来源于早期汇编程序的一个操作符,
意思是“block started by symbol(由符号开始的块)”,在程序开始执行之前,内核将此段初始
化为0。函数外的说明:
long sum[1000] ;
使此变量存放在非初始化数据段中。
• 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次函数调用时,
其返回地址、以及调用者的环境信息(例如某些机器寄存器)都存放在栈中。然后,新被调
用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈, C函数可以递归
调用。
• 堆。通常在堆中进行动态存储分配。由于历史上形成的惯例,堆位于非初始化数据段顶
和栈底之间。
图7 - 3显示了这些段的一种典型安排方式。
这是程序的逻辑布局 — 虽然并不要求一个具体
实现一定以这种方式安排其存储空间。尽管如
此,这给出了一个我们便于作有关说明的一种
典型安排。
对于VA X上的4 . 3 + B S D,正文段从 0位置开
始,栈顶则在0 x 7 fffffff之下开始。在VA X机器上,
堆顶和栈底之间未用的虚地址空间很大。
从图7 - 3还可注意到末初始化数据段的内容
并不存放在磁盘程序文件中。需要存放在磁盘程
序文件中的段只有正文段和初始化数据段。
s i z e ( 1 )命令报告正文段、数据段和b s s段的长
度(单位:字节)。例如:
$ size /bin/cc /bin/sh
text data bss dec hex
81920 16384 664 98968 18298 /bin/cc

90112 16384 0 106496 1a000 /bin/sh第4和第5列是分别以十进制和十六进制表示的总长度。



存储器分配
ANSI C说明了三个用于存储空间动态分配的函数。
(1) malloc。分配指定字节数的存储区。此存储区中的初始值不确定。
(2) calloc。为指定长度的对象,分配能容纳其指定个数的存储空间。该空间中的每一位
( b i t )都初始化为0。
(3) realloc。更改以前分配区的长度(增加或减少)。当增加长度时,可能需将以前分配区的
内容移到另一个足够大的区域,而新增区域内的初始值则不确定。
#include <stdlib.h>
void *malloc(size_ts i z e) ;
void *calloc(size_tn o b j, size_t s i z e) ;
void *realloc(void * p t r, size_t n e w s i z e) ;
三个函数返回:若成功则为非空指针,若出错则为 N U L L
void free(void * p t r)


环境变量

#include <stdlib.h>
char *getenv(const char * n a m e) ;
返回:指向与n a m e关联的v a l u e的指针,若未找到则为N U L L

注意,此函数返回一个指针,它指向n a m e = v a l u e字符串中的v a l u e。我们应当使用g e t e n v从环境
中取一个环境变量的值,而不是直接存取e n v i r o n。


#include <stdlib.h>
int putenv(const char * s t r) ;
int setenv(const char * n a m e, const char * v a l u e, int re w r i t e) ;
两个函数返回:若成功则为0,若出错则为非0
void unsetenv(const char * n a m e) ;
这三个函数的操作是:
• putenv取形式为n a m e = v a l u e的字符串,将其放到环境表中。如果 n a m e已经存在,则先删
除其原来的定义。
• setenv将n a m e设置为v a l u e。如果在环境中n a m e已经存在,那么( a )若re w r i t e非0,则首先
删除其现存的定义;( b )若re w r i t e为0,则不删除其现存定义(n a m e不设置为新的v a l u e,而且也
不出错)。
• unsetenv删除n a m e的定义。即使不存在这种定义也不算出错。



getrlimit和s e t r l i m i t函数
每个进程都有一组资源限制,其中某一些可以用g e t r l i m i t和s e t r l i m i t函数查询和更改。
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit(int  re s o u rc e, struct rlimit * r l p t r) ;
int setrlimit(int  re s o u rc e, const struct rlimit * r l p t r) ;
两个函数返回:若成功则为0,若出错则为非0

struct rlimit {
rlim_t rlim_cur; /* soft limit: current limit */
rlim_t rlim_max; /* hard limit: maximum value for rlim_cur */
} ;


这两个函数的re s o u rc e参数取下列值之一。注意并非所有资源限制都受到 S V R 4和4 . 3 + B S D
的支持。
• RLIMIT_CORE (S V R 4及4 . 3 + B S D)c o r e文件的最大字节数,若其值为 0则阻止创建
c o r e文件。
• RLIMIT_CPU (S V R 4及4 . 3 + B S D)C P U时间的最大量值(秒),当超过此软限制时,向
该进程发送S I G X C P U信号。
• RLIMIT_DATA (S V R 4及4 . 3 + B S D)数据段的最大字节长度。这是图7 - 3中初始化数据、
非初始化数据以及堆的总和。
• RLIMIT_FSIZE (S V R 4及4 . 3 + B S D)可以创建的文件的最大字节长度。当超过此软限
制时,则向该进程发送S I G X F S Z信号。
• RLIMIT_MEMLOCK (4 . 3 + B S D)锁定在存储器地址空间(尚未实现)。
• RLIMIT_NOFILE (S V R 4)每个进程能打开的最多文件数。更改此限制将影响到
s y s c o n f函数在参数_ S C _ O P E N _ M A X中返回的值(见2 . 5 . 4节)。见程序2 - 3。
• RLIMIT_NPROC (4 . 3 + B S D)每个实际用户I D所拥有的最大子进程数。更改此限制将
影响到s y s c o n f函数在参数_ S C _ C H I L D _ M A X中返回的值(见2 . 5 . 4节)。
• RLIMIT_OFILE (4 . 3 + B S D)与S V R 4的R L I M I T _ N O F I L E相同。
• RLIMIT_RSS (4 . 3 + B S D)最大驻内存集字节长度(R S S)。如果物理存储器供不应求,
则内核将从进程处取回超过R S S的部分。
• RLIMIT_STACK (S V R 4及4 . 3 + B S D)栈的最大字节长度。见图7 - 3。
• RLIMIT_VMEM (S V R 4)可映照地址空间的最大字节长度。这影响到 m m a p函数(见
1 2 . 9节)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值