现在的位置: 首页 > 综合 > 正文

old《APUE 2e》学习笔记 第七章 进程环境

2014年02月02日 ⁄ 综合 ⁄ 共 5712字 ⁄ 字号 评论关闭

 第七章 进程环境

 

7.1 引言

 

7.2 main函数

1.内核执行C程序的顺序:

   A.调用一个特殊的启动例程。

   B.可执行程序文件将此启动例程指定为程序的起始地址。

   C.启动例程从内核取得命令行参数和环境变量值。

   D.从main函数开始执行。

 

7.3 进程终止

 

1.进程终止有8种方式,其中:

    5种正常方式:A.从main返回

                        B.调用exit

                        C.调用_exit或_Exit

                        D.最后一个线程从其启动例程返回

                        E.最后一个线程调用pthread_exit

    3种异常终止:A.调用abort

                        B.接到一个信号并终止

                        C.最后一个线程对取消请求做出响应

 

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

 

3.终止状态的两种情况:

   一.下面3中情形的终止状态是为定义的:

        A.若调用这些退出函数时不带终止状态。

        B.main执行了一个无返回值的return语句。

        C.main没有声明返回类型为整型。

   二.下面的情形的终止状态是0:

        若main的返回类型是整型,并且main执行到最后一条语句时返回(隐式返回),那么该进程的终止状态是0。

   注意:exit(0)等价于return(0)。

 

4. 终止处理程序:一个进程可以登记多达32个终止处理程序函数,将由exit自动调用。使用atexit函数来登记这些函数。exit调用这些

     函数的顺序与它们登记时候的顺序相反,同一函数如果登记多次,则也会调用多次。

 

5. 图示:一个c程序是如何启动,以及它可以终止的方法:

 一个c程序是如何启动,以及它可以终止的方法

 

6. 函数原型:

    void exit(int status);

    void _Exit(int status);

    头文件:stdlib.h

    函数功能:正常终止一个程序。

    void _exit(int status);

    头文件:unistd.h

    函数功能:正常终止一个程序。  

 

7. 示例:

    ******************** 例 7-1 ********************** 

    //终止处理程序的使用。使用到atexit函数

    #include <stdio.h>

    static void exit1(void)
   {
         printf("exit1/n");
   }
    static void exit2(void)
   {
         printf("exit2/n");
   }

    int main()
   {
        atexit(exit1);
        atexit(exit2);
        atexit(exit2);
        printf("main done!/n");
        return 0;
   }

   ***********************************************

 

7.4 命令行参数

 

7.5 环境表

1. 环境表是一个字符指针数组,全局变量environ则包含了该指针数组的地址:

    extern char ** environ;

 

2. 使用getenv和putenv函数来访问特定的环境变量。

    使用environ指针来获得整个环境表。

 

7.6 C程序的存储空间布局

 

1. C程序的组成:

     A. 正文段。这是由CPU执行的机器指令部分。

     B. 初始化数据段。通常将此段称为数据段。它包含了程序中需明确地赋初值的变量。

     C. 非初始化数据段。通常将此段称为bss段。在程序开始执行之前,内核将此段中的数据初始化为0或空指针。

     D. 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。

     E. 堆。通常在堆中进行动态存储分配。

 

2. 图示,典型的存储器安排:

     典型的存储器安排

 

7.7 共享库

      共享库使得可执行文件中不再需要包含公用的库例程,而只需在所有进程都可引用的存储区中维护这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。

 

7.8 存储器分配

1. malloc函数:分配指定字节数的存储区。此存储区中的初始值不确定。

    calloc函数:为指定数量和指定长度的对象分配存储空间,该空间每一位都初始化为0.

    realloc函数:更改以前分配区的长度(增加或减少),而新增区域内的初始值则不确定。

    注:使用sbrk系统调用实现。

 

2. 函数原型:

    void *malloc(size_t size);

    void *calloc(size_t nobj,size_t size);

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

    void free(void *ptr);

    头文件:stdlib.h

    返回值:前三个函数,若成功则返回非空指针,若出错则返回NULL。

 

7.9 环境变量

1. 函数原型

    char *getenv(const char * name);

    int putenv(char *str);

    int setenv(const char * name,const char *value,int rewrite);  //rewrite为非0,则改变其值;若为0,其值不变。

    int unsetenv(const char *name);

    头文件:stdlib.h

    函数功能:获取或设置环境变量

    返回值:getenv返回指向与name关联的value的指针,若未找到则返回NULL。其余函数若成功则返回0,若出错则返回非0

 

7.10 setjmp和longjmp函数

1. 函数原型:

    int setjmp(jmp_buf,env);

    void longjmp(jmp_buf env,int val);

    头文件:setjmp.h

    返回值:setjmp若直接调用则返回0,若从longjmp调用返回则返回非0(其值是longjmp设置的val的值).               

    函数功能:执行非局部跳转。

    使用方法:希望返回到的位置调用setjmp。需要跳转的地方调用longjmp。 

 

2.示例:

   *************** 例 7-2 ****************************

   //演示使用setjmp和longjmp实行非局部跳转

   //假设“i==2&&wrong2==1 ”和“i==4&&wrong4==1”时是错误,于是发生跳转

   #include <stdio.h>
   #include <setjmp.h>

 

   jmp_buf jmpbuffer;
   int wrong2=1;
   int wrong4=1;

 

   void dochar(int i)
  {
        if(i==2&&wrong2==1)
       {
              wrong2=0;
              longjmp(jmpbuffer,2);
       }
        if(i==4&&wrong4==1)
       {
              wrong4=0;
              longjmp(jmpbuffer,4);
       }
        printf("i=%d/n",i);
  }

  void doline(int i)
  {
         dochar(i);
  }

   int main()
  {
         int setReturn;
         int i=0;
         if((setReturn=setjmp(jmpbuffer))!=0)
        {
               printf("error,return=%d/n",setReturn);
        }
         for(i=0;i<=5;i++)
        {
              doline(i);
        }
         return 0;
   }

  运行结果:

   root@BDAMA:~/study# ./161
   i=0
   i=1
   error,return=2
   i=0
   i=1
   i=2
   i=3
   error,return=4
   i=0
   i=1
   i=2
   i=3
   i=4
   i=5

 

 

**************************************************** 

 

7.11 getrlimit和setrlimit函数

1. rlimit结构体:

    struct rlimit
   {
         rlim_t rlim_cur;      /* The current (soft) limit.  */
         rlim_t rlim_max;    /* The hard limit.  */
   };

2.更改资源限制时,须遵守的3条规则:

   A. 任何一个进程都可将一个软限制值改为小于或等于其硬限制值。

   B. 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种限制对普通用户是不可逆的。

   C. 只有超级用户进程可以提高硬限制值。

 

3. 函数原型

    int getrlimit(int resource,struct rlimit *rlptr);

    int setrlimit(int resource,const struct rlimit *rlptr);

    头文件:sys/resource.h

    返回值:若成功返回0,若出错返回非0值。

    函数功能:获取或修改资源的限制值。

 

4. 资源参数(getrlimit函数和setrlimit函数的resource的值)

    RLIMIT_CPU             //Per-process CPU limit, in seconds.
    RLIMIT_FSIZE           //Largest file that can be created, in bytes.
    RLIMIT_DATA            // Maximum size of data segment, in bytes.
    RLIMIT_STACK          //Maximum size of stack segment, in bytes.
    RLIMIT_CORE           //Largest core file that can be created, in bytes.
    RLIMIT_RSS              //Largest resident set size, in bytes.
    RLIMIT_NOFILE         //Number of open files.
    RLIMIT_AS                //Address space limit.
    RLIMIT_NPROC         //Number of processes.
    RLIMIT_MEMLOCK     //Locked-in-memory address space.
    RLIMIT_LOCKS          //Maximum number of file locks.
    RLIMIT_SIGPENDING //Maximum number of pending signals. 

    RLIMIT_MSGQUEUE   //Maximum bytes in POSIX message queues.
    RLIMIT_NICE             //Maximum nice priority allowed to raise to.
    RLIMIT_RTPRIO         //Maximum realtime priority allowed for non-priviledged processes.
    RLIMIT_NLIMITS

 

5. 示例:

    ********************** 例 7-3 ***************************

    //获取和修改资源限制的值

    #include <stdio.h>
    #include <sys/resource.h>

    int main()
   {
         struct rlimit prl;
         getrlimit(RLIMIT_DATA,&prl);
         printf("rlim_cur=%lu,rlim_max=%lu/n",prl.rlim_cur,prl.rlim_max);
         prl.rlim_cur=100;
         prl.rlim_max=200;
         if(setrlimit(RLIMIT_DATA,&prl)!=0)
         {
               printf("setrlimit wrong!/n");
         }

         getrlimit(RLIMIT_DATA,&prl);
         printf("rlim_cur=%lu,rlim_max=%lu/n",prl.rlim_cur,prl.rlim_max);

         return 0;
    }
   *********************************************************

 

链接:ttp://blog.csdn.net/wyjlovec/archive/2009/10/06/4635650.aspx

作者:wyjlovec

QQ:294448030

 

 

抱歉!评论已关闭.