进程环境

进程终止的8种方式,其中前5种为正常终止,他们是:
(1)从main返回
(2)调用exit
(3)调用_exit或_Exit
(4)最后一个线程从其启动例程返回
(5)从最后一个线程调用pthread_exit
异常终止方式有3种,它们是:
(6)调用abort
(7)接到一个信号
(8)最后一个线程对取消请求做出响应
1、退出函数

三个函数用于正常终止一个程序:_exit和_Exit立即进入内核,exit先执行一些清理处理,然后返回内核。

#include<stdlib.h>//由ISO C说明的
void exit(int status);
void _exit(int status);
#include<unistd.h>//由POSIX.1说明的
void _exit(int status);
3个退出函数都有一个整形参数,称为终止状态。

如果:调用这些函数时不带终止状态、main执行了一个无返回值的return语句、main没有声明返回类型为整形。则该进程的终止状态是未定义的。

如果:main返回类型是整形,并且执行到最后一条语句返回,则终止状态为0。(exit(0)等价于return (0))

#include<iostream>
main()
{
    cout<<"hello world"<<endl;
}
编译完成echo $? 打印终止状态

2、函数atexit

按照ISO C规定,一个进程可以登记至多32个函数,这些函数由exit自动调用,这些函数称为终止处理函数。将在主程序退出后进行一些处理操作。需要用atexit函数登记,调用顺序与登记顺序相反,登记多次会被调用多次。

#include<iostram>
static void my_exit1();
static void my_exit2();
int main(){
    atexit(my_exit2);
    atexit(my_exit1);
    atexit(my_exit1);
    cout<<"main is done"<<endl;
    return 0;
}
static void my_exit1(){
    cout<<"first"<<endl;
}
static void my_exit2(){
    cout<<"second"<<endl;
}
3、命令行参数

当执行一个程序时,调用exec的进程将命令行参数传递给该新程序。

#include<iostream>
using namespace std;
int main(int argc,char *argv[]){
    for(int i = 0; i < argc; i++){
        cout<<argv[i]<<" ";
    }
    return 0;
}
编译执行:./a.out 123 abc ABC,输出:123 abc ABC

4、环境表

每个程序都接收一个环境表,与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的C字符串的地址。全局变量environ则包含该指针数组的地址:extern char **environ;每个字符串为name=value的格式。

5、C程序的存储空间布局

由地地址到高地址依次为:正文段-->初始化数据段-->未初始化数据段-->堆-->栈。

6、存储空间分配

3种用于存储空间动态分配的函数。

(1)malloc,分配指定字节数的存储区。不进行初始化。

(2)calloc,为指定数量指定长度的对象分配存储空间。空间中每一位都初始化为0.

(3)realloc,增加或减少以前分配区的长度。 

#include<stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
void free(void *ptr);
7、环境变量

getenv获得某环境变量

putenv将name=value放到环境表中,如果name存在,则先删除原定义。

setenv将name设置为value,name如果存在,rewrite非0则先删除,rewrite=0,不删除不操作

unsetenv删除name定义,不存在也不会报错。

#include<stdlib.h>
char *getenv(const char *name);
int putenv(char *str);
int setenv(const char *name,const char *value,int rewrite);
int unsetenv(const char *name);


8、函数setjmp和longjmp

goto语句不能跨越函数,在深层次调用跳转用setjmp和lonjmp

#include<iostream>
#include<setjmp.h>
using namespace std;
int fun1(int i);
int fun2(int i);
jmp_buf jmpbuffer;
int main(){
    setjmp(jmpbuffer);
    for(int i=0;i<10;i++){
        fun1(i);
    }
    return 0;
}
int fun1(int i){
    if(i>7)
        longjmp(jmpbuffer,1);
    fun2(i);
    return 0;
}
int fun2(int i){
    if(i>5)
        longjmp(jmpbuffer,2);
    return 0;
}
main将所需信息存入jmpbuffer里,并返回1,调用fun1,又调用fun2,假设fun2处出现错误,将返回到setjmp记录的栈位置,将下面的栈帧抛弃,setjmp返回的是2(longjmp的 第二个参数)。

然而在执行longjmp后,main中的自动变量和寄存器变量状态不好确定,如果不想回滚到调用fun1之前的状态,则自动变量使用volatile,全局变量或者静态变量在执行longjmp时保持不变。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值