跳转至

UNIX 系统信息

1 主机名称

  • 头文件:unistd.h
  • 语法:
  • long gethostid(void);:获取主机id
  • int sethostid(long hostid);:设置主机id
  • int gethostname(char *name, size_t len);获取主机名
  • int sethostname(const char *name, size_t len);设置主机名
  • 示例1:获取主机名和id
#include<unistd.h>
#include<stdio.h>
int main()
{
    long hostId = gethostid();
    char hostname[1024];
    gethostname(hostname, sizeof(hostname));
    printf("hostname: %s\n", hostname);
    printf("hostid: %ld\n", hostId);
    return 0;
}
  • 示例2:设置主机名和id(需root用户)
#include<unistd.h>
#include<string.h>
#include<stdio.h>
int main()
{
    int ret=0;
    char hostname[1024]={0};
    sprintf(hostname, "%s","hostname");
    ret=sethostname(hostname, strlen(hostname));
    printf("alter ret %d hostname: %s\n", ret,hostname);
    ret=sethostid(hostId);
    printf("alter ret %d hostid: %ld\n", ret,hostId);
}

2 获取配置信息

  • sysconfconfstr不同在于sysconf返回的是整型值,confstr返回的是字符串值

2.1 sysconf

  • 功能:获取系统配置信息
  • 语法:long int sysconf (int name);
  • name:系统变量名,在bits/confname.h中定义,以_SC开头,如下
    • _SC_PAGE_SIZE:页大小
    • _SC_ARG_MAX:exec函数参数最大长度
    • _SC_HOST_NAME_MAX:hostname的最大长度
  • 示例
#include<unistd.h>
#include<stdio.h>
int main()
{
    printf("arg_max: %ld\n", sysconf(_SC_ARG_MAX));
    printf("chars_max: %ld\n", sysconf(_SC_CHILD_MAX));
    printf("clock_res: %ld\n", sysconf(_SC_CLK_TCK));
    printf("data_seg_max: %ld\n", sysconf(_SC_DELAYTIMER_MAX));
    printf("exec_max: %ld\n", sysconf(_SC_EXPR_NEST_MAX));
    printf("fd_max: %ld\n", sysconf(_SC_OPEN_MAX));
    printf("proc_max: %ld\n", sysconf(_SC_NPROCESSORS_CONF));
    return 0;
}
// 输出结果
// arg_max: 2097152
// chars_max: 50521
// clock_res: 100
// data_seg_max: 2147483647
// exec_max: 32
// fd_max: 4096
// proc_max: 8

2.2 confstr

  • 功能:获取配置项的字符串变量值
  • 语法:size_t confstr (int name, char *buf, size_t len);
  • name:系统变量名,在bits/confname.h中定义,以_CS开头,如下
    • _CS_GNU_LIBC_VERSION:
    • _CS_PATH:
  • buf:存放查询结果的缓存
  • len:buf的大小
  • 返回值:成功返回查询结果的大小(结果为空=0),失败0
  • 示例
#include<unistd.h>
#include<stdio.h>
int main()
{
    char buf[1024]={0};
    confstr(_CS_PATH, buf, sizeof(buf));
    printf("path: %s\n", buf);
    printf("libc_version: %s\n", buf);
    confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf));
    printf("libpthread_version: %s\n", buf);
    return 0;
}
// 输出结果
// path: /bin:/usr/bin
// libc_version: /bin:/usr/bin
// libpthread_version: NPTL 2.31

2.3 pathconf和fpathconf

  • 功能:获取文件的配置值
  • 语法:
  • long fpathconf(int fd, int name);
    • fd:文件描述符
    • name:配置变量名
  • long pathconf(char *path, int name);
    • path:文件路径
    • name:配置变量名
  • name选项如下
    • _PC_LINK_MAX:returns the maximum number of links to the file.
    • _PC_MAX_CANON:returns the maximum length of a formatted input line, where fd or path must refer to a terminal.
    • _PC_MAX_INPUT:returns the maximum length of an input line, where fd or path must refer to a terminal.
    • _PC_NAME_MAX:returns the maximum length of a filename in the directory path or fd that the process is allowed to create.
    • _PC_PATH_MAX:returns the maximum length of a relative pathname when path or fd is the current working directory.
    • _PC_PIPE_BUF:returns the size of the pipe buffer, where fd must refer to a pipe or FIFO and path must refer to a FIFO.
  • 示例
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main()
{
    printf("path_max: %ld\n", pathconf("/", _PC_PATH_MAX));
    printf("pipe_max: %ld\n", pathconf("/", _PC_PIPE_BUF));
    int fd=open("/", O_RDONLY);
    printf("fd_max: %ld\n", fpathconf(fd, _PC_NAME_MAX));
    printf("link_max: %ld\n", pathconf("/", _PC_LINK_MAX));
    return 0;
}

2.4 getpagesize

  • 功能:获取页大小,等价于sysconf(_SC_PAGESIZE)
  • 语法:int getpagesize (void);
  • 返回值:页大小
  • 示例
#include<unistd.h>
#include<stdio.h>
int main()
{
    int pagesize = sysconf(_SC_PAGESIZE);
    printf("pagesize: %d\n", pagesize);
    int pagesize1 = getpagesize();
    printf("pagesize1: %d\n", pagesize1);
    return 0;
}
// 输出结果:
// pagesize: 4096
// pagesize1: 4096

2.5 getdtablesize

  • 功能:获取进程中文件描述符表的大小
  • 语法:int getdtablesize(void);
  • 返回值:进程可以打开的最大文件数
  • 示例
#include<unistd.h>
#include<stdio.h>
int main()
{
    int tablesize=getdtablesize();
    printf("tablesize: %d\n", tablesize);
    return 0;
}
// 输出结果:
// tablesize: 4096

3 获取网络信息

3.2 getifaddrs

  • 功能:获取网络接口地址,调用后需要使用freeifaddrs释放
  • 语法:
  • int getifaddrs(struct ifaddrs **ifap);
  • void freeifaddrs(struct ifaddrs *ifa);
  • ifaddrs结构如下
struct ifaddrs {
    struct ifaddrs  *ifa_next;    /* Next item in list */
    char            *ifa_name;    /* Name of interface */
    unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */
    struct sockaddr *ifa_addr;    /* Address of interface */
    struct sockaddr *ifa_netmask; /* Netmask of interface */
    union {
        struct sockaddr *ifu_broadaddr;
                         /* Broadcast address of interface */
        struct sockaddr *ifu_dstaddr;
                         /* Point-to-point destination address */
    } ifa_ifu;
#define              ifa_broadaddr ifa_ifu.ifu_broadaddr
#define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
    void            *ifa_data;    /* Address-specific data */
};
  • 示例
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    struct ifaddrs *ifaddr, *ifa;
    int family, s;
    char host[NI_MAXHOST];
    if (getifaddrs(&ifaddr) == -1)
    {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }
    /* Walk through linked list, maintaining head pointer so we
       can free list later */
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
    {
        if (ifa->ifa_addr == NULL)
            continue;
        family = ifa->ifa_addr->sa_family;
        /* Display interface name and family (including symbolic
           form of the latter for the common families) */
        printf("%s  address family: %d%s\n",
               ifa->ifa_name, family,
               (family == AF_PACKET) ? " (AF_PACKET)" : (family == AF_INET) ? " (AF_INET)"
                                                    : (family == AF_INET6)  ? " (AF_INET6)"
                                                                            : "");
        /* For an AF_INET* interface address, display the address */

        if (family == AF_INET || family == AF_INET6)
        {
            s = getnameinfo(ifa->ifa_addr,
                            (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
                            host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
            if (s != 0)
            {
                printf("getnameinfo() failed: %s\n", gai_strerror(s));
                exit(EXIT_FAILURE);
            }
            printf("\taddress: <%s>\n", host);
        }
    }
    freeifaddrs(ifaddr);
    exit(EXIT_SUCCESS);
}
  • 输出结果
lo  address family: 17 (AF_PACKET)
bond0  address family: 17 (AF_PACKET)
dummy0  address family: 17 (AF_PACKET)
tunl0  address family: 17 (AF_PACKET)
sit0  address family: 17 (AF_PACKET)
eth0  address family: 17 (AF_PACKET)
lo  address family: 2 (AF_INET)
        address: <127.0.0.1>
eth0  address family: 2 (AF_INET)
        address: <172.27.198.233>
lo  address family: 10 (AF_INET6)
        address: <::1>
eth0  address family: 10 (AF_INET6)
        address: <fe80::215:5dff:fefa:8b75%eth0>

4 获取进程信息

4.1 getpid、getppid、getpgrp、getpgid

/* Get the process ID of the calling process.  */
extern __pid_t getpid (void) __THROW;

/* Get the process ID of the calling process's parent.  */
extern __pid_t getppid (void) __THROW;

/* Get the process group ID of the calling process.  */
extern __pid_t getpgrp (void) __THROW;

/* Get the process group ID of process PID.  */
extern __pid_t getpgid (__pid_t __pid) __THROW;

5 资源限制

  • 功能:获取或设置资源限值
  • rlimit结构如下:
struct rlimit {
    rlim_t rlim_cur;  /* Soft limit (不能大于rlim_max)*/
    rlim_t rlim_max;  /* Hard limit (rlim_cur的上限) */
};

5.1 getrlimit

  • 功能:获取资源限制
  • 语法:int getrlimit(int resource, struct rlimit *rlim);
  • resource:操作的资源限制,以RLIMIT_开头
    • RLIMIT_AS:The maximum size of the process's virtual memory (address space) in bytes. 32位机器此值不大于2GiB
    • RLIMIT_CORE:core文件大小的最大值. When 0 no core dump files are created. When nonzero, larger dumps are truncated to this size.
    • RLIMIT_CPU:CPU时间限制(以秒为单位)。当进程达到软限制时,将发送一个SIGXCPU信号。此信号的默认操作是终止进程。但是,可以捕获信号,处理程序可以将控制权返回主程序。如果进程继续消耗CPU时间,它将每秒发送一次SIGXCPU,直到达到硬限制,此时它将被发送SIGKILL。(后一点描述了Linux行为。实现在处理达到软限制后继续消耗CPU时间的进程时会有所不同。需要捕获此信号的便携式应用程序应在第一次收到SIGXCPU时执行有序终止。
    • RLIMIT_DATA:The maximum size of the process's data segment (initialized data, uninitialized data, and heap).
    • RLIMIT_FSIZE:进程可能创建的最大文件大小。
    • RLIMIT_LOCKS (Early Linux 2.4 only):此进程可以使用flock(2) locks and fcntl(2) leases 的数量
    • RLIMIT_NICE (since Linux 2.6.12, but see BUGS below):Specifies a ceiling to which the process's nice value can be raised using setpriority(2) or nice(2). The actual ceiling for the nice value is calculated as 20 - rlim_cur. (This strangeness occurs because negative numbers cannot be specified as resource limit values, since they typically have special meanings. For example, RLIM_INFINITY typically is the same as -1.)
    • RLIMIT_NOFILE:进程可以打开的文件描述符数量. Attempts (open(2), pipe(2), dup(2), etc.) to exceed this limit yield the error EMFILE. (Historically, this limit was named RLIMIT_OFILE on BSD.)
    • RLIMIT_NPROC:可以为调用进程的真实用户ID创建的最大进程数(或者更准确地说,在Linux上是线程数)
    • RLIMIT_STACK:进程堆栈的最大大小,以字节为单位。Upon reaching this limit, a SIGSEGV signal is generated. To handle this signal, a process must employ an alternate signal stack (sigaltstack(2)).
  • rlim:获取到的资源限值
  • 返回值:成功返回0,失败返回-1
  • 示例
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    struct rlimit rlim;
    getrlimit(RLIMIT_NOFILE, &rlim);
    printf("RLIMIT_NOFILE %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_CORE, &rlim);
    printf("RLIMIT_CORE %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_DATA, &rlim);
    printf("RLIMIT_DATA %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_STACK, &rlim);
    printf("RLIMIT_STACK %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_AS, &rlim);
    printf("RLIMIT_AS %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_RSS, &rlim);
    printf("RLIMIT_RSS %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_MEMLOCK, &rlim);
    printf("RLIMIT_MEMLOCK %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_NPROC, &rlim);
    printf("RLIMIT_NPROC %lu\n", rlim.rlim_cur);
    return 0;
}
// 输出结果
// RLIMIT_NOFILE 4096
// RLIMIT_CORE 0
// RLIMIT_DATA 18446744073709551615
// RLIMIT_STACK 8388608
// RLIMIT_AS 18446744073709551615
// RLIMIT_RSS 18446744073709551615
// RLIMIT_MEMLOCK 65536
// RLIMIT_NPROC 50521

5.2 setrlimit

  • 功能:设置资源限制
  • 语法:int setrlimit(int resource, const struct rlimit *rlim);
  • resource:详见getrlimit
  • rlim:设置的资源限值
  • 返回值:成功返回0,失败返回-1
  • 示例
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    struct rlimit rlim;
    printf("RLIMIT_CORE %lu\n", rlim.rlim_cur);
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 1024*1024;
    rlim.rlim_max = 2*1024*1024;
    setrlimit(RLIMIT_CORE, &rlim);//注释掉这行,将不会产生core文件
    getrlimit(RLIMIT_CORE, &rlim);
    printf("RLIMIT_CORE %lu\n", rlim.rlim_cur);
    abort();
    return 0;
}
  • 输出分析:原先进程不会尝试core文件,设置后,异常终止产生了core文件
RLIMIT_CORE 0
RLIMIT_CORE 1048576
Aborted (core dumped)

5.3 prlimit

  • 功能:同时设置一个新的资源限值和获取旧的资源限制,是getrlimitsetrlimit的结合体
  • 语法:int prlimit(pid_t pid, int resource, const struct rlimit *new_limit,struct rlimit *old_limit);
  • pid:要操作的进程id。当pid==0时,就是操作调用进程;当操作其它进程时,需要确保本进程具有CAP_SYS_RESOURCE能力,否则失败
  • new_limit:需要设置的新的资源限值;当new_limit==NULL时,不设置新的限值
  • old_limit:获得的旧的资源限值;当old_limit!=NULL时,才会赋值
  • 返回值:成功返回0,失败返回-1
  • 示例
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#define errExit(msg)
do
{
    perror(msg);
    exit(EXIT_FAILURE);

} while (0) 
int main(int argc, char *argv[])
{
    struct rlimit old, new;
    struct rlimit *newp;
    pid_t pid;
    if (!(argc == 2 || argc == 4))
    {
        fprintf(stderr, "Usage: %s <pid> [<new-soft-limit> <new-hard-limit>]\n",argv[0]);
        exit(EXIT_FAILURE);
    }
    pid = atoi(argv[1]); /* PID of target process */
    newp = NULL;
    if (argc == 4)
    {
        new.rlim_cur = atoi(argv[2]);
        new.rlim_max = atoi(argv[3]);
        newp = &new;
    }
    /* Set CPU time limit of target process; retrieve and display
previous limit */
    if (prlimit(pid, RLIMIT_CPU, newp, &old) == -1)
        errExit("prlimit-1");
    printf("Previous limits: soft=%lld; hard=%lld\n",(long long)old.rlim_cur, (long long)old.rlim_max);
    /* Retrieve and display new CPU time limit */
    if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1)
        errExit("prlimit-2");
    printf("New limits: soft=%lld; hard=%lld\n",(long long)old.rlim_cur, (long long)old.rlim_max);
    exit(EXIT_FAILURE);
}

6 进程优先级

  • 进程优先级范围区间[0,{NZERO}*2-1],NZERO目前是20;同时进程的默认优先级也是NZERO
  • 设置低优先级需要超级用户权限,否则会执行失败,errno是EPERM(-1)

6.1 nice

  • 功能:改变进程的优先级
  • 语法:int nice(int incr);
  • incr:在原优先级上偏移多少,计算后总和不能超过[0,{NZERO}*2-1]这个范围,如原优先级是NZERO,incr区间是[-20,19]
  • 返回值:成功,返回修改后的进程优先级,范围 [-NZERO,NZERO-1],可以为负,因此判断是否执行成功,需要查看errno是否==0
  • 示例:注意在root用户下执行和普通用户下执行结果不同
#include<unistd.h>
#include<limits.h>
#include<sys/resource.h>
#include<stdio.h>
#include<errno.h>
#include<error.h>
int main()
{
    printf("%d\n",getpriority(PRIO_PROCESS,0));
    printf("nice %d\n",nice(-20));
    printf("errno %d \n",errno);
    printf("%d\n",getpriority(PRIO_PROCESS,0));
}
// 输出结果
// 0
// nice -20
// errno 0 
// -20

6.2 getpriority

  • 功能:获取进程、进程组、用户的优先级
  • 语法:int getpriority(int which, id_t who);
  • which:指定操作的是进程、进程组或用户
    • PRIO_PROCESS:进程
    • PRIO_PGRP:进程组
    • PRIO_USER:用户
  • who:依据which参数,是进程id(getpid)、进程组id(getpgid),还是用户id(getuid)
  • 返回值:成功返回优先级,区间[-NZERO,NZERO-1],失败返回-1,但同时需要通过errno来判断是否是执行失败
  • 示例
#include<unistd.h>
#include<sys/resource.h>
#include<stdio.h>
#include<errno.h>
int main()
{
    printf("%d\n",getpriority(PRIO_PROCESS,0));
    setpriority(PRIO_PROCESS,0,-10);
    printf("%d\n",getpriority(PRIO_PROCESS,0));
    setpriority(PRIO_PROCESS,0,20);
    printf("%d\n",getpriority(PRIO_PROCESS,0));

}
// 输出结果
// 0
// -10
// 19

6.3 setpriority

  • 功能:设置进程、进程组、用户的优先级
  • 语法:int setpriority(int which, id_t who, int value);
  • which:同getpriority
  • who:同getpriority
  • value:设置的优先级,实际设置的是value + NZERO的值,即value可取值区间是[-NZERO,NZEROs],这个不同于nice函数的
  • 示例:见getpriority

7 内存管理

7.1 malloc_trim

  • 功能:释放在堆顶的已经free了的内存
  • 头文件:#include <malloc.h>
  • 语法:int malloc_trim(size_t pad);:
  • pad:通常设置0,表示释放所有能释放的内存到系统中
  • 返回值:返回1表示成功释放内存到系统,返回0表示没有释放
  • 示例
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
#include <malloc.h>
#include <vector>
using namespace std;

int getVmRSS()
{
    int ret = 0;
    pid_t cur_pid = getpid();
    FILE *fl1 = NULL;
    char command[256] = {0};
    char buf[256] = {0};
    sprintf(command, "cat /proc/%u/status|grep VmRSS|awk '{print $2}'", cur_pid);
    fl1 = popen(command, "r");
    if (fl1 != NULL)
    {
        while (feof(fl1) == 0 && buf != NULL)
        {
            fread(buf, 1, 256, fl1);
        }
        pclose(fl1);
    }
    else
    {
        ret = -1;
    }
    uint32_t vmrss = atoi(buf);
    return vmrss;
}

int main(int argc, char *argv[])
{
    mallopt(M_MMAP_THRESHOLD, 128 * 1024);
    if (argc < 2)
    {
        printf("需要一个参数\n");
        return 1;
    }
    int MEMORY_SIZE = atoi(argv[1]);
    vector<char *> Array;
    printf("befor new current VmRSS [%u]\n", getVmRSS());
    for (int j = 0; j < 2064; j++)
    {
        char *Buff = new char[MEMORY_SIZE];
        for (int i = 0; i < MEMORY_SIZE; i++)
            Buff[i] = i;
        Array.push_back(Buff);
    }
    printf("end new current VmRSS [%u]\n", getVmRSS());
    sleep(2);
    for (int j = 0; j < 2064; j++)
        delete[] Array[j];
    printf(" delete current VmRSS [%u]\n", getVmRSS());
    sleep(2);
    malloc_trim(0);
    printf(" malloc_trim current VmRSS [%u]\n", getVmRSS());
}
  • 结果
$ g++ test.cc
$ ./a.out 65535
befor new current VmRSS [1280]
end new current VmRSS [133292]
 delete current VmRSS [132676]
 malloc_trim current VmRSS [1356]

7.2 mallopt

  • 功能:设置内存分配的参数
  • 语法:int mallopt(int param, int value);
  • param:
    • M_MMAP_MAX:
    • M_MMAP_THRESHOLD:设置分配内存时采用mmap的阈值;大于等于时用mmap分配内存,小于时用sbrk分配内存
    • M_TRIM_THRESHOLD : 设置调用 sbrk 释放已经 free 的堆顶内存到系统的阈值;大于等于时释放内存
  • value:对应param的值
  • 返回值: