Chinaunix首页 | 论坛 | 博客
  • 博客访问: 71893
  • 博文数量: 17
  • 博客积分: 322
  • 博客等级: 二等列兵
  • 技术积分: 305
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-15 17:43
个人简介

linux code Engineer

文章分类
文章存档

2013年(3)

2012年(14)

我的朋友

分类: 系统运维

2012-05-29 20:18:14

本文章介绍进程的环境

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的进程可将命令行参数传递给新程序。
    程序如下:

   
  1. #include <stdio.h>
  2.     #include <stdlib.h>
  3.     int main(int argc, char **argv)
  4.     {
  5.         int i;
  6.         for (i = 0; i < argc; i++) {
  7.             printf("argv[%d] = %s.\n", i, argv[i]);
  8.         }
  9.         exit(EXIT_SUCCESS);
  10.     }


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是跳转后的返回值

阅读(1284) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~