Linux系统信息与系统资源
系统信息与系统资源
系统信息
系统标识uname
系统调用uname()用于获取有关当前操作系统内核的名称和信息,原型可以通过man 2 uname查看
函数参数和返回值含义如下:
buf:struct utsname 结构体类型指针,指向一个 struct utsname 结构体类型对象。
返回值:成功返回 0;失败将返回-1,并设置 errno。
uname()函数用法非常简单,先定义一个 struct utsname 结构体变量,调用 uname()函数时传入变量的地
址即可,struct utsname 结构体如下所示:
1 | struct utsname { |
sysinfo函数
sysinfo 系统调用可用于获取一些系统统计信息
1 |
|
info:struct sysinfo 结构体类型指针,指向一个 struct sysinfo 结构体类型对象。
返回值:成功返回 0;失败将返回-1,并设置 errno。
1 | struct sysinfo { |
gethostname函数
此函数可用于单独获取 Linux 系统主机名,与 struct utsname 数据结构体中的 nodename 变量一样,原型通过命令man 2 gethostname查看。
name:指向用于存放主机名字符串的缓冲区。
len:缓冲区长度。
返回值:成功返回 0,;失败将返回-1,并会设置 errno。
sysconf函数
sysconf()函数是一个库函数,可在运行时获取系统的一些配置信息。
1 |
|
⚫ _SC_ARG_MAX:exec 族函数的参数的最大长度,exec 族函数后面会介绍,这里先不管!
⚫ _SC_CHILD_MAX:每个用户的最大并发进程数,也就是同一个用户可以同时运行的最大进程数。
⚫ _SC_HOST_NAME_MAX:主机名的最大长度。
⚫ _SC_LOGIN_NAME_MAX:登录名的最大长度。
⚫ _SC_CLK_TCK:每秒时钟滴答数,也就是系统节拍率。
⚫ _SC_OPEN_MAX:一个进程可以打开的最大文件数。
⚫ _SC_PAGESIZE:系统页大小(page size)。
⚫ _SC_TTY_NAME_MAX:终端设备名称的最大长度。
更多请用man指令查询。
时间、日期
time函数
系统调用time()用于获取当前时间,以秒为单位,返回值是自 1970-01-01 00:00:00 +0000 (UTC)以来的秒数,原型可通过man2 time查看
tloc:如果 tloc 参数不是 NULL,则返回值也存储在 tloc 指向的内存中。
返回值:成功则返回自 1970-01-01 00:00:00 +0000 (UTC)以来的时间值(以秒为单位);失败则返回-1,
并会设置 errno。
time 函数获取得到的是一个时间段,也就是从 1970-01-01 00:00:00 +0000 (UTC)到现在这段时间所经过的秒数,把这个称之为日历时间或 time_t 时间
1 |
|
gettimeofday函数
gettimeofday()函数提供微秒级时间精度。原型可通过man 2 gettimeofday查看
tv:参数 tv 是一个 struct timeval 结构体指针变量,struct timeval 结构体在前面章节内容中已经给大家介绍过,具体参考示例代码 5.6.3。
tz:参数 tz 是个历史产物,早期实现用其来获取系统的时区信息,目前已遭废弃,在调用 gettimeofday()函数时应将参数 tz 设置为 NULL。
返回值:成功返回 0;失败将返回-1,并设置 errno。
1 |
|
时间转换函数
ctime函数
ctime可以将日历时间转换为可打印输出的字符串形式
1 |
|
timep:time_t 时间变量指针。
返回值:成功将返回一个 char *类型指针,指向转换后得到的字符串;失败将返回 NULL。
1 |
|
localtime函数
localtime()函数可以把 time()或 gettimeofday()得到的秒数(time_t 时间或日历时间)变成一个 struct tm
结构体所表示的时间,该时间对应的是本地时间。
1 |
|
timep:需要进行转换的 time_t 时间变量对应的指针,可通过 time()或 gettimeofday()获取得到。
result:是一个 struct tm 结构体类型指针,稍后给大家介绍 struct tm 结构体,参数 result 是可重入函数
localtime_r()需要额外提供的参数。
返回值:对于不可重入版本 localtime()来说,成功则返回一个有效的 struct tm 结构体指针,而对于可重入版本 localtime_r()来说,成功执行情况下,返回值将会等于参数result;失败则返回 NULL。
1 | struct tm { |
1 |
|
gmtime()函数把time_t时间变为struct tm结构体所表示的时间,得到的是UTC国际标准时间,不是本地时间。
1 |
|
1 |
|
mktime函数可以将使用 struct tm 结构体表示的分解时间转换为 time_t时间(日历时间)
1 |
|
tm:需要进行转换的 struct tm 结构体变量对应的指针。
返回值:成功返回转换得到 time_t 时间值;失败返回-1。
asctime函数与 ctime()函数的作用一样,也可将时间转换为可打印输出的字符串形式,与 ctime()函数
的区别在于,ctime()是将 time_t 时间转换为固定格式字符串、而 asctime()则是将 struct tm 表示的分解时间转换为固定格式的字符串。
1 |
|
tm:需要进行转换的 struct tm 表示的时间。
buf:可重入版本函数 asctime_r 需要额外提供的参数 buf,指向一个缓冲区,用于存放转换得到的字符串。
返回值:转换失败将返回 NULL;成功将返回一个 char *类型指针,指向转换后得到的时间字符串,对asctime_r 函数来说,返回值就等于参数 buf。
1 |
|
strftime 函数可以自定义时间显示格式。
1 |
|
s:指向一个缓存区的指针,该缓冲区用于存放生成的字符串。
max:字符串的最大字节数。
format:这是一个用字符串表示的字段,包含了普通字符和特殊格式说明符,可以是这两种字符的任意
组合。特殊格式说明符将会被替换为 struct tm 结构体对象所指时间的相应值。
特殊格式可用命令man strftime查询。
设置时间 settimeofday
使用 settimeofday()函数可以设置时间,也就是设置系统的本地时间
1 |
|
tv:参数 tv 是一个 struct timeval 结构体指针变量,struct timeval 结构体在前面章节内容中已经给大家介绍了,需要设置的时间便通过参数 tv 指向的 struct timeval 结构体变量传递进去。
tz:参数 tz 是个历史产物,早期实现用其来设置系统的时区信息,目前已遭废弃,在调用 settimeofday()函数时应将参数 tz 设置为 NULL。
返回值:成功返回 0;失败将返回-1,并设置 errno。
使用 settimeofday 设置系统时间时内核会进行权限检查,只有超级用户(root)才可以设置系统时间,普通用户将无操作权限。
进程时间
进程时间指的是进程从创建后(也就是程序运行后)到目前为止这段时间内使用 CPU 资源的时间总数,出于记录的目的,内核把 CPU 时间(进程时间)分为以下两个部分:
⚫ 用户 CPU 时间:进程在用户空间(用户态)下运行所花费的 CPU 时间。有时也成为虚拟时间(virtual time)。
⚫ 系统 CPU 时间:进程在内核空间(内核态)下运行所花费的 CPU 时间。这是内核执行系统调用或代表进程执行的其它任务(譬如,服务页错误)所花费的时间。
一般来说,进程时间指的是用户 CPU 时间和系统 CPU 时间的总和,也就是总的 CPU 时间。
times函数
1 |
|
buf:times()会将当前进程时间信息存在一个 struct tms 结构体数据中
返回值:返回值类型为 clock_t(实质是 long 类型),调用成功情况下,将返回从过去任意的一个时间点(譬如系统启动时间)所经过的时钟滴答数(其实就是系统节拍数),将(节拍数 / 节拍率)便可得到秒数,返回值可能会超过 clock_t 所能表示的范围(溢出);调用失败返回-1,并设置 errno。
1 | struct tms |
clock函数
库函数 clock()提供了一个更为简单的方式用于进程时间,它的返回值描述了进程使用的总的 CPU 时间
1 |
|
无参数。
返回值:返回值是到目前为止程序的进程时间,为 clock_t 类型,注意 clock()的返回值并不是系统节拍数,如果想要获得秒数,请除以 CLOCKS_PER_SEC(这是一个宏)。如果返回的进程时间不可用或其值无法表示,则该返回值是-1。
clock()函数虽然可以很方便的获取总的进程时间,但并不能获取到单独的用户 CPU 时间和系统 CPU 时间,在实际编程当中,根据自己的需要选择。
产生随机数
rand()函数用于获取随机数。(是一种伪随机数)
1 |
|
返回值:返回一个介于 0 到 RAND_MAX(包含)之间的值,也就是数学上的[0, RAND_MAX]。程度当中调用 rand()可以得到[0, RAND_MAX]之间的伪随机数,多次调用 rand()便可以生成一组伪随机树序列,但是这里有个问题,就是每一次运行程序所得到的随机数序列都是相同的,那如何使得每一次启动应用程序所得到的随机数序列是不一样的呢?那就通过设置不同的随机数种子,可通过 srand()设置随机数种子。
如果没有调用 srand()设置随机数种子的情况下,rand()会将 1 作为随机数种子,如果随机数种子相同,那么每一次启动应用程序所得到的随机数序列就是一样的,所以每次启动应用程序需要设置不同的随机数种子,这样就可以使得程序每次运行所得到随机数序列不同。
srand 函数
使用 srand()函数为 rand()设置随机数种子。
1 |
|
seed:指定一个随机数中,int 类型的数据,一般尝尝将当前时间作为随机数种子赋值给参数 seed,譬如 time(NULL),因为每次启动应用程序时间上是一样的,所以就能够使得程序中设置的随机数种子在每次启动程序时是不一样的。
返回值:void
常用的用法 srand(time(NULL))
1 |
|
休眠
有时需要将进程暂停或休眠一段时间,进入休眠状态之后,程序将暂停运行,直到休眠结束。常用的系统调用和 C 库函数有 sleep()、usleep()以及 nanosleep(),这些函数在应用程序当中通常作为延时使用。
秒级休眠sleep
1 |
|
seconds:休眠时长,以秒为单位。
返回值:如果休眠时长为参数 seconds 所指定的秒数,则返回 0;若被信号中断则返回剩余的秒数。
sleep()是一个秒级别休眠函数,程序在休眠过程中,是可以被其它信号所打断的。
微秒休眠usleep
1 |
|
高精度休眠nanosleep
nanosleep()与 sleep()以及 usleep()类似,都用于程序休眠,但 nanosleep()具有更高精度来设置休眠时间长度,支持纳秒级时长设置。与 sleep()、usleep()不同的是,nanosleep()是一个 Linux 系统调用。
req:一个 struct timespec 结构体指针,指向一个 struct timespec 变量,用于设置休眠时间长度,可精确到纳秒级别。
rem:也是一个 struct timespec 结构体指针,指向一个 struct timespec 变量,也可设置 NULL。
返回值:在成功休眠达到请求的时间间隔后,nanosleep()返回 0;如果中途被信号中断或遇到错误,则返回-1,并将剩余时间记录在参数 rem 指向的 struct timespec 结构体变量中(参数 rem 不为 NULL 的情况下,如果为 NULL 表示不接收剩余时间),还会设置 errno 标识错误类型。
申请堆内存
在操作系统下,内存资源是由操作系统进行管理、分配的,当应用程序想要内存时(这里指的是堆内存),可以向操作系统申请内存,然后使用内存;当不再需要时,将申请的内存释放、归还给操作系统。
堆上分配内存:malloc和free
malloc为程序分配一段堆内存
1 |
|
size:需要分配的内存大小,以字节为单位。
返回值:返回值为 void *类型,如果申请分配内存成功,将返回一个指向该段内存的指针,void *并不是说没有返回值或者返回空指针,而是返回的指针类型未知,所以在调用 malloc()时通常需要进行强制类型转换,将 void *指针类型转换成我们希望的类型;如果分配内存失败(譬如系统堆内存不足)将返回 NULL,如果参数 size 为 0,返回值也是 NULL。
malloc()在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的,所以通常需要程序员对 malloc()分配的堆内存进行初始化操作。
free释放堆内存
1 |
|
ptr:指向需要被释放的堆内存对应的指针。
返回值:无返回值。
用 calloc()分配内存
calloc()函数用来动态地分配内存空间并初始化为 0,其函数原型如下所示:
1 |
|
使用该函数同样也需要包含头文件。
calloc()在堆中动态地分配 nmemb 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 nmemb * size 个字节长度的内存空间,并且每个字节的值都是 0。
返回值:分配成功返回指向该内存的地址,失败则返回 NULL。
calloc()与 malloc()的一个重要区别是:calloc()在动态分配完内存后,自动初始化该内存空间为零,而malloc()不初始化,里边数据是未知的垃圾数据。下面的两种写法是等价的:
1 | // calloc()分配内存空间并初始化 |
分配对齐内存
C 函数库中还提供了一系列在堆上分配对齐内存的函数,对齐内存在某些应用场合非常有必要,常用于分配对其内存的库函数有:posix_memalign()、aligned_alloc()、memalign()、valloc()、pvalloc()。
1 |
|
posix_memalign()函数
posix_memalign()函数用于在堆上分配 size 个字节大小的对齐内存空间,将*memptr 指向分配的空间,分配的内存地址将是参数 alignment 的整数倍。参数 alignment 表示对齐字节数,alignment 必须是 2 的幂次方(譬如 2^4、2^5、2^8 等),同时也要是 sizeof(void *)的整数倍,对于 32 位系统来说sizeof(void *)等于4,如果是 64 位系统 sizeof(void *)等于 8。
函数参数和返回值含义如下:
memptr:void *类型的指针,内存申请成功后会将分配的内存地址存放在memptr 中。
alignment:设置内存对其的字节数,alignment 必须是 2 的幂次方(譬如 2^4、2^5、2^8 等),同时也要是 sizeof(void )的整数倍。
size:设置分配的内存大小,以字节为单位,如果参数 size 等于 0,那么memptr 中的值是 NULL。
返回值:成功将返回 0;失败返回非 0 值。
1 |
|
proc文件系统
(1)proc是虚拟文件系统,虚拟的意思就是proc文件系统里的文件不对应硬盘上任何文件,我们用去查看proc目录下的文件大小都是零;
(2)proc文件系统是开放给上层了解内核运行状态的窗口,通过读取proc系统里的文件,可以知道内核中一些重要数据结构的数值,从而知道内核的运行情况,也可以方便调试内核和应用程序;
(3)proc文件系统的思路:在内核中构建一个虚拟文件系统/proc,内核运行时将内核中一些关键的数据结构以文件的方式呈现在/proc目录中的一些特定文件中,这样相当于将不可见的内核中的数据结构以可视化的方式呈现给内核的开发者
文件名 | 作用 |
---|---|
/proc/cmdline | 查看内核的启动参数 |
/proc/cpuinfo | 查看CPU的信息 |
/proc/devices | 查看内核中已经注册的设备 |
/proc/filesystems | 内核当前支持的文件系统类型 |
/proc/interrupts | 中断的使用及触发次数,调试中断时很有用 |
/proc/misc | 内核中注册的misc类设备 |
/proc/modules | 已经加载的模块列表,对应lsmod命令 |
/proc/partitions | 系统的分区表 |
/proc/version | 系统的版本 |
数字 | 数字的文件夹都是相应的进程 |
/proc/mounts | 已加载的文件系统的列表,对应mount命令 |
/proc/meminfo | 内核的内存信息 |
/proc/fb | 内核中注册的显示设备 |
proc 文件系统的使用就是去读取/proc 目录下的这些文件,获取文件中记录的信息,可以直接使用 cat 命令读取,也可以在应用程序中调用 open()打开、然后再使用 read()函数读取。