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;
}
#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 获取配置信息
sysconf
和confstr
不同在于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);
long pathconf(char *path, int 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 资源限制
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
- 功能:同时设置一个新的资源限值和获取旧的资源限制,是
getrlimit
和setrlimit
的结合体
- 语法:
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
的值
- 返回值: