在main前调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址,启动例程会从内核取得命令行参数和环境变量值,然后为调用mian做好准备。
4.1 进程终止
有8种啊方式使进程终止,前5种为正常终止,如下
(1)从main返回,等效于调用exit()
(2)调用exit函数
(3)调用_exit和 _Exit
(4)最后一个线程从启动例程返回
(5)从最后一个线程调用pthread_exit
后面3种如下,为异常终止方式
(1)调用abort
(2)接到一个信号
(3)最后一个线程对取消请求做出相应破
一般从main返回后立即调用exit函数
exit(main(argc,argv));
退出函数
void exit(int stat)
先执行一些自定义的或者内核定义的函数,再必须执行一个标准IO库的清理关闭操作,将所有的打开流调用fclose函数
注意,直接return main函数也是会调用exit函数的
return 0 == exit(0)
void _Exit(int stat)
void _exit(int stat)
立即进入内核,不做处理
一个进程可以登记多到32个函数,这下函数将在exit自动调用,可以通过atexit函数来登记这些函数
int atexit(void (*func)(void))
成功则返回0.否则返回非0
参数是一个函数地址,调用这些函数的顺序与登记的时候相反
一般函数地址直接函数名就可。
4.2 命令行参数和环境参数
int main(int argc,char* argv[])
argc从0开始,argv[argc]==NULL
argv[0]=调用的命令,后面的才是参数
可以写作
for(i=0;argv[i]!=NULL;i++)
同样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的c字符串的地址,全局变量environ则包含了该指针数组的地址
extern char** environ;
每个环境字符串类型于"PATH=:abcd\0"
char* getenv(const char* name)
返回与name关联的value指针,未找到则返回NULL
int putenv(char* str)
成功则返回0,否则返回非0
取形式为"name=value\0"格式的字符串放入环境表中,若name已经存在则删除原来的定义
int setenv(const char* name,const char *value,int rewrite)
将name设置为value,如果环境表中name已经存在,则
rewrite=0 不删除现有定义
rewrite=1 删除现有的定义
int unsetenv(const char* name)
删除name的定义,即使未定义也不会出错