进程环境二(环境变量、C程序的存储空空间布局、库、函数跳转、资源的获取以及控制)

环境变量

KEY=VALUE
查看环境变量:export
环境变量:environ,定义为一个char**,是一个字符指针数组的起始位置。
环境变量的存放,类似argv的存放
请添加图片描述

例子:

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

extern char **environ;
int main()
{
    int i=0;
    for(i=0;environ[i]!=NULL;i++)
        puts(environ[i]);
    

    exit(0);

}

运行就可以看到环境变量
请添加图片描述

相关函数:
getenv();
----------------------- get an environment variable

   #include <stdlib.h>
   char *getenv(const char *name);

例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{

        puts(getenv("PATH"));

        exit(0);
}

运行后就可以得到PATH值:
请添加图片描述

setenv();
--------------change or add an environment variable

   #include <stdlib.h>
   int setenv(const char *name, const char *value, int overwrite);

第一个参数:环境变量的名字,存在就是改变,不存在就是增加
第三个参数:是否覆盖,如果是真则用现在的覆盖以前的,如果是假,则新的不会生效

putenv();
---------------------- change or add an environment variable

   #include <stdlib.h>
   int putenv(char *string);//不好用

C程序的存储空空间布局

请添加图片描述

相关命令pmap:

让代码停在getchar处:

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


int main()
{

        puts(getenv("PATH"));

        getchar();

        exit(0);
}

ps axf//查看进程关系
请添加图片描述
pmap 2997查看地址空间的分布
请添加图片描述

    动态库
    静态库
    手工装载库:开机启动的时候
相关函数:

dlopen
dlclose
------------------------open and close a shared object

dlerror
------------------------ obtain error diagnostic for functions in the dlopen API

dlsym
--------------------obtain address of a symbol in a shared object or executable

   #include <dlfcn.h>
   void *dlopen(const char *filename, int flags);
   int dlclose(void *handle);
   char *dlerror(void);
   void *dlsym(void *handle, const char *symbol);

注意:Link with -ldl.

例子(man手册中的例子,可自行查看):

#include <stdio.h>
       #include <stdlib.h>
       #include <dlfcn.h>
       #include <gnu/lib-names.h>  /* Defines LIBM_SO (which will be a
                                      string such as "libm.so.6") */
       int
       main(void)
       {
           void *handle;
           double (*cosine)(double);
           char *error;

           handle = dlopen(LIBM_SO, RTLD_LAZY);
           if (!handle) {
               fprintf(stderr, "%s\n", dlerror());
               exit(EXIT_FAILURE);
           }

           dlerror();    /* Clear any existing error */

           cosine = (double (*)(double)) dlsym(handle, "cos");

           /* According to the ISO C standard, casting between function
              pointers and 'void *', as done above, produces undefined results.
              POSIX.1-2003 and POSIX.1-2008 accepted this state of affairs and
              proposed the following workaround:

                  *(void **) (&cosine) = dlsym(handle, "cos");

              This (clumsy) cast conforms with the ISO C standard and will
              avoid any compiler warnings.

              The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a.
              POSIX.1-2013) improved matters by requiring that conforming
              implementations support casting 'void *' to a function pointer.
              Nevertheless, some compilers (e.g., gcc with the '-pedantic'
              option) may complain about the cast used in this program. */

           error = dlerror();
           if (error != NULL) {
               fprintf(stderr, "%s\n", error);
               exit(EXIT_FAILURE);
           }

           printf("%f\n", (*cosine)(2.0));
           dlclose(handle);
           exit(EXIT_SUCCESS);
       }

函数跳转

在这里插入图片描述

例子:

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


static void  d(void)
{

        printf("%s():begin.\n",__FUNCTION__);

        printf("%s():End.\n",__FUNCTION__);


}


static void  c(void)
{

        printf("%s():begin.\n",__FUNCTION__);
        printf("%s():Call d().\n",__FUNCTION__);
        d();
        printf("%s():d() returned.\n",__FUNCTION__);

        printf("%s():End.\n",__FUNCTION__);


}


static void  b(void)
{

        printf("%s():begin.\n",__FUNCTION__);
        printf("%s():Call c().\n",__FUNCTION__);
        c();
        printf("%s():c() returned.\n",__FUNCTION__);

        printf("%s():End.\n",__FUNCTION__);


}


static void  a(void)
{

        printf("%s():begin.\n",__FUNCTION__);
        printf("%s():Call a().\n",__FUNCTION__);
        b();
        printf("%s():a() returned.\n",__FUNCTION__);

        printf("%s():End.\n",__FUNCTION__);


}


int main()
{

    printf("%s():begin.\n",__FUNCTION__);
    printf("%s():Call a().\n",__FUNCTION__);
    a();
    printf("%s():a() returned.\n",__FUNCTION__);

    printf("%s():End.\n",__FUNCTION__);

    exit(0);

}

运行结果:
在这里插入图片描述
可以看到压栈和弹栈的过程

setjmp()//设置跳转点
---------------------save stack context for nonlocal goto

   #include <setjmp.h>
   int setjmp(jmp_buf env);

返回值:执行一次返回两次,如果是设置跳转点,那么返回值就是0,如果是从别的地方跳转回来,那么返回值就是非0值
setjmp() and sigsetjmp() return 0 if returning directly, and nonzero
when returning from longjmp(3) or siglongjmp(3) using the saved context.

longjmp()//往回跳
--------------------- nonlocal jump to a saved stack context

    #include <setjmp.h>
    void longjmp(jmp_buf env, int val);

以上两个函数可以实现跨函数跳转

例子:

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

static jmp_buf save;

static void  d(void)
{

        printf("%s():begin.\n",__FUNCTION__);
    printf("%s():Jump now!\n",__FUNCTION__);
    longjmp(save,6);
        printf("%s():End.\n",__FUNCTION__);


}


static void  c(void)
{

        printf("%s():begin.\n",__FUNCTION__);
        printf("%s():Call d().\n",__FUNCTION__);
        d();
        printf("%s():d() returned.\n",__FUNCTION__);

        printf("%s():End.\n",__FUNCTION__);


}


static void  b(void)
{

        printf("%s():begin.\n",__FUNCTION__);
        printf("%s():Call c().\n",__FUNCTION__);
        c();
        printf("%s():c() returned.\n",__FUNCTION__);

        printf("%s():End.\n",__FUNCTION__);


}


static void  a(void)
{
    int ret;
        printf("%s():begin.\n",__FUNCTION__);
    
    ret=setjmp(save);
    if(ret==0)
    {    
            printf("%s():Call a().\n",__FUNCTION__);
               b();
               printf("%s():a() returned.\n",__FUNCTION__);
    }
    else
    {
        printf("%s():Iumped back here with code %d\n",__FUNCTION__,ret);
    }
        printf("%s():End.\n",__FUNCTION__);


}


int main()
{

    printf("%s():begin.\n",__FUNCTION__);
    printf("%s():Call a().\n",__FUNCTION__);
    a();
    printf("%s():a() returned.\n",__FUNCTION__);

    printf("%s():End.\n",__FUNCTION__);

    exit(0);

}

运行结果:
在这里插入图片描述

资源的获取以及控制

getrlimit();//获取资源总量
setrlimit();//设置资源总量

   #include <sys/time.h>
   #include <sys/resource.h>
   int getrlimit(int resource, struct rlimit *rlim);
   int setrlimit(int resource, const struct rlimit *rlim);
struct rlimit {
               rlim_t rlim_cur;  /* Soft limit */
               rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
           };

root用户和普通用户使用这个函数的权限是不一样的
通用的规则:软限制可以升高可以降低,但是即使升高也不能超过硬限制
普通用户对于硬限制只可以降低不可以升高,对于软限制可以提高和降低
root用户对于硬限制可以升高也可以降低,对于软限制可以升高也可以降低
利用这两个函数可以封装ulimit命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值