Skip to content
Published at:

进程环境

命令行参数(main)

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

/**
 * @brief 命令行及其传参
 *
 * @param argc :(argument count) 参数的个数
 * @param argv :(argument vector) 参数的字符串数组
 * @return int
 */
// ./main_args_demo xixi hehe haha
int main(int argc, char* argv[]) {
    // argc = 3
    // argv = {"./main_args_demo", "xixi", "hehe", "haha"}

    printf("argc = %d\n", argc);
    for (int i = 0; argv[i] != NULL; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}

环境变量

每个程序都会收到一张环境表.

全局变量保存了该指针数组的地址:

c
extern char** environ;

表结构:

shell
key=value

getenv/setenv/unsetenv

  • char *getenv(const char *name); 通过key,获取value
  • int setenv(const char *name, const char *value, int overwrite); 设置环境变量
  • int unsetenv(const char *name); 通过key,取消环境变量的设置

Example:

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

// extern char** environ
// getenv
// setenv

// 声明
extern char** environ;

int main(int argc, char* argv[]) {
    // for (int i = 0; environ[i] != NULL; i++) {
    //     printf("%s\n", environ[i]);
    // }
    char* shell = getenv("SHELL");
    printf("shell = %s\n", shell);

    char* home = getenv("HOME");
    printf("home = %s\n", home);

    // xixi=hehe
    setenv("xixi", "hehe", 1);
    setenv("xixi", "haha", 1);
    char* hehe = getenv("xixi");
    printf("home = %s\n", hehe);
    return 0;
}

getrlimit/setrlimit函数

每个进程都有一组资源限制, 可以通过getrlimit/setrlimit函数查询和更改 ulimit

  • int getrlimit(int resource, struct rlimit *rlim);
  • int setrlimit(int resource, const struct rlimit *rlim);
c
struct rlimit {
    rlim_t rlim_cur;  /* Soft limit */
    rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
};

参数resource

  • RLIMIT_AS //进程的最大虚内存空间,字节为单位。
  • RLIMIT_CORE //内核转存文件的最大长度。
  • RLIMIT_CPU //最大允许的CPU使用时间,秒为单位。当进程达到软限制,内核将给其发送SIGXCPU信号,这一信号的默认行为是终止进程的执行。然而,可以捕捉信号,处理句柄可将控制返回给主程序。如果进程继续耗费CPU时间,核心会以每秒一次的频率给其发送SIGXCPU信号,直到达到硬限制,那时将给进程发送 SIGKILL信号终止其执行。
  • RLIMIT_DATA //进程数据段的最大值。
  • RLIMIT_FSIZE //进程可建立的文件的最大长度。如果进程试图超出这一限制时,核心会给其发送SIGXFSZ信号,默认情况下将终止进程的执行。
  • RLIMIT_LOCKS //进程可建立的锁和租赁的最大值。
  • RLIMIT_MEMLOCK //进程可锁定在内存中的最大数据量,字节为单位。
  • RLIMIT_MSGQUEUE //进程可为POSIX消息队列分配的最大字节数。
  • RLIMIT_NICE //进程可通过setpriority() 或 nice()调用设置的最大完美值。
  • RLIMIT_NOFILE //指定比进程可打开的最大文件描述词大一的值,超出此值,将会产生EMFILE错误。
  • RLIMIT_NPROC //用户可拥有的最大进程数。
  • RLIMIT_RTPRIO //进程可通过sched_setscheduler 和 sched_setparam设置的最大实时优先级。
  • RLIMIT_SIGPENDING //用户可拥有的最大挂起信号数。
  • RLIMIT_STACK //最大的进程堆栈,以字节为单位。

命令程序ulimit

shell
$ ulimit --help
  -a:显示目前资源限制的设定;
  -c <core文件上>:设定core文件的最大值,单位为区块;
  -d <数据节区大>:程序数据节区的最大值,单位为KB;
  -f <文件大>:shell所能建立的最大文件,单位为区块;
  -H:设定资源的硬性限制,也就是管理员所设下的限制;
  -m <内存大>:指定可使用内存的上限,单位为KB;
  -n <文件数>:指定同一时间最多可开启的文件数;
  -p <缓冲区大>:指定管道缓冲区的大小,单位512字节;
  -s <堆叠大>:指定堆叠的上限,单位为KB;
  -S:设定资源的弹性限制;
  -t <CPU时>:指定CPU使用时间的上限,单位为秒;
  -u <程序数>:用户最多可开启的程序数目;
  -v <虚拟内存大>:指定可使用的虚拟内存上限,单位为KB。

$ ulimit -a
  core file size          (blocks, -c) 0           #core文件的最大值为100 blocks。
  data seg size           (kbytes, -d) unlimited   #进程的数据段可以任意大。
  scheduling priority             (-e) 0
  file size               (blocks, -f) unlimited   #文件可以任意大。
  pending signals                 (-i) 98304       #最多有98304个待处理的信号。
  max locked memory       (kbytes, -l) 32          #一个任务锁住的物理内存的最大值为32KB。
  max memory size         (kbytes, -m) unlimited   #一个任务的常驻物理内存的最大值。
  open files                      (-n) 1024        #一个任务最多可以同时打开1024的文件。
  pipe size            (512 bytes, -p) 8           #管道的最大空间为4096字节。
  POSIX message queues     (bytes, -q) 819200      #POSIX的消息队列的最大值为819200字节。
  real-time priority              (-r) 0
  stack size              (kbytes, -s) 10240       #进程的栈的最大值为10240字节。
  cpu time               (seconds, -t) unlimited   #进程使用的CPU时间。
  max user processes              (-u) 98304       #当前用户同时打开的进程(包括线程)的最大个数为98304。
  virtual memory          (kbytes, -v) unlimited   #没有限制进程的最大地址空间。
  file locks                      (-x) unlimited   #所能锁住的文件的最大个数没有限制。

ulimit_demo.c

c
// #include "apue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <unistd.h>

#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_MEMLOCK
    doit(RLIMIT_MEMLOCK);
#endif

#ifdef RLIMIT_MSGQUEUE
    doit(RLIMIT_MSGQUEUE);
#endif

#ifdef RLIMIT_NICE
    doit(RLIMIT_NICE);
#endif

    doit(RLIMIT_NOFILE);

#ifdef RLIMIT_NPROC
    doit(RLIMIT_NPROC);
#endif

#ifdef RLIMIT_NPTS
    doit(RLIMIT_NPTS);
#endif

#ifdef RLIMIT_RSS
    doit(RLIMIT_RSS);
#endif

#ifdef RLIMIT_SBSIZE
    doit(RLIMIT_SBSIZE);
#endif

#ifdef RLIMIT_SIGPENDING
    doit(RLIMIT_SIGPENDING);
#endif

    doit(RLIMIT_STACK);

#ifdef RLIMIT_SWAP
    doit(RLIMIT_SWAP);
#endif

#ifdef RLIMIT_VMEM
    doit(RLIMIT_VMEM);
#endif

    exit(0);
}

static void pr_limits(char* name, int resource) {
    struct rlimit limit;
    unsigned long long lim;

    if (getrlimit(resource, &limit) < 0) {

        printf("getrlimit error for %s", name);
        return;
    }
    printf("%-14s  ", name);
    if (limit.rlim_cur == RLIM_INFINITY) {
        printf("(infinite)  ");
    } else {
        lim = limit.rlim_cur;
        printf("%10lld  ", lim);
    }
    if (limit.rlim_max == RLIM_INFINITY) {
        printf("(infinite)");
    } else {
        lim = limit.rlim_max;
        printf("%10lld", lim);
    }
    putchar((int)'\n');
}

环境变量

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

extern char** environ;

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

相关函数

c
#include <stdlib.h>

char * getenv(const char *name); // 获取

int setenv(const char *name, const char *value, int overwrite); // 设置

int putenv(char *string); //

int unsetenv(const char *name); // unset