APUE: Process Environment

main函數和進程終止

    當內核執行C程序時,在調用main前先調用一個特殊的啓動例程。可執行程序文件將此啓動例程指定爲程序的起始地址。啓動例程從內核取得命令行參數和環境變量值,而後調用main函數。函數

存在8種方式終止進程:佈局

5種正常終止:spa

1. 從main返回命令行

2. 調用exit線程

3. 調用_exit或者_Exit指針

4. 最後一個線程從啓動例程中返回.code

5. 最後一個線程調用pthread_exit.對象

3種異常終止:進程

1. 調用abort內存

2. 接收信號並終止.

3. 最後一個線程對取消請求作出響應.

Exit函數

#include <stdlib.h>

void exit(int status);

void _Exit(int status);

#include <unistd.h>

void _exit(int status);

_exit和_Exit會立馬返回到內核, 而exit則會清除線程後返回內核.

在main函數中, 若是沒有顯式return/exit, 則默認返回0:

#include <stdio.h>

int main(void)
{
    printf("hello world\n");
}

終端輸出:

leicj@leicj:~/test$ ./a.out
hello world
leicj@leicj:~/test$ echo $?
0

atexit函數

    一個進程能夠登記多達32個函數,這些函數將由exit自動調用。咱們稱這些函數爲終止處理程序,並調用atexit函數來登記這些函數。

終止處理程序:

#include <stdio.h>

static void my_exit1(void);
static void my_exit2(void);

int main(void)
{
    if (atexit( my_exit2 ) != 0)
        printf("can't register my_exit2\n");
    if (atexit( my_exit1 ) != 0)
        printf("can't register my_exit1\n");
    if (atexit( my_exit1 ) != 0)
        printf("can't register my_exit1\n");
    printf("main is done\n");
    return 0;
}

static void my_exit1(void)
{
    printf("first exit handler\n");
}

static void my_exit2(void)
{
    printf("second exit handler\n");
}

程序輸出:

leicj@leicj:~/test$ ./a.out
main is done
first exit handler
first exit handler
second exit handler

 

C程序的存儲空間佈局

1. 正文段:由CPU執行的機器指令部分

2. 初始化數據段:包含了程序中需明確的賦初值的變量

3. 非初始化數據段: 聲明在函數以外的變量存放的地方, 一般會被內核初始化爲0或者null.

4. 棧:自動變量以及每次函數調用時所需保存的信息都存放在此段中

5. 堆:進行動態分配

leicj@leicj:~/test$ size /usr/bin/cc /bin/sh
   text    data     bss     dec     hex filename
 902577    8048    9696  920321   e0b01 /usr/bin/cc
 143301    4792   11312  159405   26ead /bin/sh

內存分配

ISO C定義三個函數用於分配內存, 一個函數用於釋放內存.

#include <stdlib.h>

void *malloc(size_t size);

void *calloc(size_t nobj, size_t size);

void *realloc(void *ptr, size_t newsize);

            returns: 成功返回非空指針, 失敗返回NULL

void free(void *ptr);

malloc: 分配特定字節的內存, 初始值不肯定.

calloc: 分配特定數量的對象, 每一個對象的大小爲size.

realloc: 用於增長或減小內存.

關於環境變量

#include <stdio.h>
#include <stdlib.h>

extern char *environ;
int main( void )
{
    putenv("hello=world");
    setenv("hello1", "world1", 0);

    printf("%s\n", getenv("hello"));
    printf("%s\n", getenv("hello1"));

    unsetenv("hello");
    unsetenv("hello1");

    return 0;
}

程序輸出:

leicj@leicj:~/test$ ./a.out
world
world1

 

setjmp和longjmp

#include <stdio.h>
#include <setjmp.h>
jmp_buf jmpbuffer;
void fun1();
void fun2();
int main( void )
{
    int     bFun1 = 0;
    int     bFun2 = 0;
    bFun1 = setjmp(jmpbuffer);
    bFun2 = setjmp(jmpbuffer);
    printf("the return value is:%d---%d\n", bFun1, bFun2);
    printf("main done\n");
    if ( bFun1 || bFun2 ) {
        exit( 0 );
    }
    fun1();
    fun2();

    return 0;
}

void fun1()
{
    printf("fun1\n");
    longjmp( jmpbuffer, 1 );
}

void fun2()
{
    printf("fun2\n");
    longjmp( jmpbuffer, 2 );
}

程序輸出:

leicj@leicj:~/test$ ./a.out
the return value is:0---0
main done
fun1
the return value is:0---1
main done
相關文章
相關標籤/搜索