《unix环境高级编程》--- 进程环境

终止码
main中返回一个整型值与用该值调用exit是等价的

#include <stdio.h>

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

得到的终止码是随机的,取决于main函数返回时栈和寄存器的内容

yjp@yjp-VirtualBox:~/apue/7environ$ cc hello1.c
hello1.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main()
 ^
yjp@yjp-VirtualBox:~/apue/7environ$ ./a.out
hello world
yjp@yjp-VirtualBox:~/apue/7environ$ echo $?    打印终止状态
0
yjp@yjp-VirtualBox:~/apue/7environ$ cc -std=c99 hello1.c  启用gcc's 1999 ISO C扩展
hello1.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main()
 ^
yjp@yjp-VirtualBox:~/apue/7environ$ ./a.out
hello world
yjp@yjp-VirtualBox:~/apue/7environ$ echo $?
0

终止处理程序实例

#include "apue.h"

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

int main(void)
{
    /*
      int atexit(void (*func)(void);
      登记终止处理函数,成功返回0
      调用函数的顺序与登记的顺序相反
      同一函数如若登记多次,也会被调用多次
    */
    if(atexit(my_exit2) != 0)
        err_sys("can't register my_exit2");
    if(atexit(my_exit1) != 0)
        err_sys("can't register my_exit1");
    if(atexit(my_exit1) != 0)
        err_sys("can't register my_exit1");

    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");
}

这里写图片描述

将所有命令行参数送回到标准输出
当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序

#include "apue.h"

int main(int argc, char *argv[])
{
    int i;
    for(i=0; i<argc; i++)
        printf("argv[%d]: %s\n", i, argv[i]);
    exit(0);
}

这里写图片描述

C程序的存储布局空间
正文段。CPU执行的机器指令部分,只读。
初始化数据段。
非初始化数据段。bss段。
栈。
堆。
这里写图片描述
未初始化的数据段的内容不存放在磁盘上的程序文件中。

size报告正文段、数据段、bss段长度
这里写图片描述
第4列和第5列分别以十进制和十六进制表示三个段的总长度

共享库
程序第一次执行或第一次第哦也某个库函数时,用动态链接方法将程序与共享库函数相链接
使用共享库可减少可执行文件的长度,但会增加运行时间开销

yjp@yjp-VirtualBox:~/apue/7environ$ cc -static hello1.c  阻止gcc使用共享库
yjp@yjp-VirtualBox:~/apue/7environ$ ls -l a.out
-rwxrwxr-x 1 yjp yjp 912664 520 09:09 a.out
yjp@yjp-VirtualBox:~/apue/7environ$ size a.out
   text    data     bss     dec     hex filename
 823726    7284    6360  837370   cc6fa a.out
yjp@yjp-VirtualBox:~/apue/7environ$ cc hello1.c    gcc默认使用共享库
yjp@yjp-VirtualBox:~/apue/7environ$ ls -l a.out
-rwxrwxr-x 1 yjp yjp 8608 520 09:10 a.out
yjp@yjp-VirtualBox:~/apue/7environ$ size a.out
   text    data     bss     dec     hex filename
   1182     552       8    1742     6ce a.out

setjmp和longjmp实例
goto只能在一个函数内部跳转,setjmp和longjmp可在栈上跳过若干调用帧,返回到当前函数调用路径的某一个函数中。
通过此程序说明在调用longjmp后各变量情况。

#include "apue.h"
#include <setjmp.h>

static void f1(int, int, int, int);
static void f2(void);
static jmp_buf jmpbuffer;
static int globval;

int main(void)
{
    int autoval;          /* 自动变量, 执行longjmp时可能变 */
    register int regival; /* 寄存器变量, 执行longjmp时可能变 */
    volatile int volaval; /* 执行longjmp时保持不变*/
    static int statval;   /* 全局或静态变量的值在执行longjmp时保持不变 */

    globval = 1;
    autoval = 2;
    regival = 3;
    volaval = 4;
    statval = 5;

    /*
       int setjmp(jmp_buf env);
       希望返回到的位置调用setjmp
       返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
       env: 存放调用longjmp时能用来恢复栈状态的所有信息,全局变量
    */
    if(setjmp(jmpbuffer) != 0)
    {
        printf("after longjmp:\n");
        printf("globval = %d, autoval = %d, regival = %d, "
            "volaval = %d, statval = %d\n", 
                 globval, autoval, regival, volaval, statval);
        exit(0);
    }
    /* Change variables after setjmp, but before longjmp */
    globval = 95;
    autoval = 96;
    regival = 97;
    volaval = 98;
    statval = 99;

    f1(autoval, regival, volaval, statval);  /* never returns */
    exit(0);
}

static void f1(int i, int j, int k, int l)
{
    printf("in f1():\n");
    printf("globval = %d, autoval = %d, regival = %d, "
        "volaval = %d, statval = %d\n",
        globval, i, j, k, l);
    f2();
}

static void f2(void)
{
    /*
       void longjmp(jmp_buf env, int val);
       env: 在调用setjmp时所用的env
       val: 作为从setjmp处返回的值。setjmp可根据此值,判断造成返回的longjmp在哪里调用
    */
    longjmp(jmpbuffer, 1);
}

不带任何优化的编译:

这里写图片描述

打印当前资源限制

#include "apue.h"
#if defined(BSD) || defined(MACOS)
#include <sys/time.h>
#define FMT "%10lld  "
#else
#define FMT "%10ld  "
#endif      
#include <sys/resource.h>

/* 
ISO C的字符串创建运算符#,可为每个资源名产生字符串值。
如 doit(RLIMIT_CORE); 将由C预处理程序扩展为:
pr_limits("RLIMIT_CORE", RLIMIT_CORE);
*/
#define doit(name) pr_limits(#name, name)

static void pr_limits(char *, int);

int main(void)
{
#ifdef RLIMIT_AS
    doit(RLIMIT_AS);      
#endif
    doit(RLIMIT_CORE);    
    doit(RLIMIT_CPU);
    doit(RLIMIT_DATA);
    doit(RLIMIT_FSIZE);
#ifdef RLIMIT_LOCKS
    doit(RLIMIT_LOCKS);
#endif
#ifdef RLIMIT_MEMLOCK
    doit(RLIMIT_MEMLOCK);
#endif
#ifdef RLIMIT_NOFILE
    doit(RLIMIT_NOFILE);
#endif
#ifdef RLIMIT_RSS
    doit(RLIMIT_RSS);
#endif
#ifdef RLIMIT_SBSIZE
    doit(RLIMIT_SBSIZE);
#endif
#ifdef RLIMIT_STACK
    doit(RLIMIT_STACK);
#endif
#ifdef RLIMIT_VMEM
    doit(RLIMIT_VMEM);
#endif
    exit(0);
}

static void pr_limits(char *name, int resource)
{
    /*
      struct rlimit
      {
        rlim_t rlim_cur;   soft limit: current limit
        rlim_t rlim_max;   hard limit: maximum value for rlim_cur
      }
    */
    struct rlimit limit;

    /*
       int getrlimit(int resource, struct rlimit *rlptr);
       查询资源限制
       int setrlimit(int resource, const struct rlimit *rlptr);
       更改资源限制
    */
    if(getrlimit(resource, &limit) < 0)
        err_sys("getrlimit error for %s", name);
    printf("%-14s  ", name);
    if(limit.rlim_cur == RLIM_INFINITY)
        printf("(infinite)  ");
    else
        printf(FMT, limit.rlim_cur);
    if(limit.rlim_max == RLIM_INFINITY)
        printf("(infinite)  ");
    else
        printf(FMT, limit.rlim_max);
    putchar((int)'\n');
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/u012319493/article/details/80378184