系统调用 uname() 用于获取当前操作系统内核的名称和信息。调用时先创建一个结构体类型变量,然后传入地址即可
#include
int uname(struct utsname *buf);
可用于获取一些系统统计信息
#include
int sysinfo(const sysinfo *info);
可以单独获取 Linux 系统主机名
#include
int gethostname(char *name, size_t len);
// 参数:用于存放主机名的缓冲区以及缓冲区大小
可在运行时获取系统的一些配置信息
#include
long sysconf(int name);
/* name:指定要获取哪个配置信息,可以使用 man 手册查看
* _SC_ARG_MAX:exec族函数的参数的最大长度,这里先不用了解exec族
* _SC_CHILD_MAX:每个用户的最大并发进程数
* _SC_HOST_NAME_MAX:主机名的最大长度
* _SC_LOGIN_NAME_MAX:登录名的最大长度
* _SC_CLK_TCK:每秒时钟滴答数,也就是系统节拍率
* _SC_OPEN_MAX:一个进程可以打开的最大文件数
* _SC_PAGESIZE:系统页大小
* _SC_TTY_NAME_MAX:终端设备名的最大长度
* ...
* /
操作系统中有两个时钟,一个是系统时钟,一个是实时时钟,也叫 RTC。系统时钟在系统启动之后由内核来维护,使用 date 命令获取到的就是系统时钟,在系统关机情况下不存在;实时时钟一般由 RTC 时钟芯片提供,该芯片有相应的电池,可以保证在系统关机的情况下依旧能够继续工作。
在启动之后先读取 RTC 作为系统时钟的初始值,之后一直维护系统时钟,然后就不会再对 RTC 进行读取操作。系统关机后,会将系统时钟写入到 RTC,进行同步操作。
内核定义的一个全局变量,使用该变量来记录系统从启动以来的系统节拍数,所以这个变量用来记录以系统节拍时间为单位的时间长度,Linux 内核在编译配置时定义了一个节拍时间,使用节拍率(一秒钟多少个节拍数)来表示,譬如节拍率为 200Hz,就表示一秒钟 200 个节拍,节拍时间为 1s/200。节拍率越低,每一个系统节拍的时间就越短,意味着 jiffies 记录的时间精度越高。 但是高节拍率会导致系统中断的产生更加频繁,会加剧系统的负担,一般默认情况下都是采用 100Hz 作为系统节拍率。
内核其实通过 jiffies 来维护系统时钟,在系统开机时会设置一个初始值,上面所说的读取 RTC就是用来初始化 jiffies 变量的。当我们需要获取到系统当前时间点时,就可以使用 jiffies 变量去计算。
获取当前时间,以秒为单位,返回值是从 1970-01-01 00:00:00 +0000(UTC) 以来的秒数
#include
time_t time(time_t *tloc);
// 如果 tloc 不是空,则返回值存储在 tloc 指向的内存中
time 函数只能精确到秒,而这个函数可以精确到微秒
#include
int gettimeofday(struct timeval *tv, struct timezone *tz);
// tz 直接设置为NULL即可
// 获取到的时间存储在tv中,这个结构体的有两个变量,得到的时间就是 tv_sec+tv_usec。tv_sec 的值和time获取的值相同
将时间转换为字符串形式
#include
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
// 成功就返回指向得到的字符串的指针,失败就返回NULl
// 但是 ctime 是一个不可重入的函数,推荐使用 ctime_r,是一个可重入函数,buf就是用于存放字符串的缓冲区地址。可重入后面再讲,_r 就一般表示可重入,也就是如果成功就返回buf
#include
#include
#include
#include
using namespace std;
int main()
{
char str[100]={0};
time_t tm;
tm=time(NULL);
ctimr_t(&tm,str);
cout << str<<endl;
return 0;
}
讲时间转换为一个 struct tm 结构体所表示的时间,对应的是本地时间
#include
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
将 time_t 转换为 struct tm 结构体表示的时间,但是是 UTC 时间,不是本地时间
#include
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
将 struct tm 结构体表示的时间转换为 time_t 时间
#include
time_t mktime(struct tm *tm);
和 ctime() 一样,但是可以将时间分解转换为固定格式字符串。
#include
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
可以根据自己的需要设定格式
#include
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
/* s:存放生成的字符串
* max:字符串的最大字节数
* format:格式
* tm:指向结构体的指针
* /
这些格式字段可以任意组合,比如:"%Y-%m-%d %H:%M:%S<%p> %B %A"
可以输出"2021-01-14 16:30:25
设置系统本地时间,而且只有超级用户才能设置时间
#include
int settimeofday(const struct timeval *tv, const struct timezone *tz);
// tz 目前已经废弃,直接设置NULL即可
进程时间指的是进程从创建后,也就是程序运行后,到目前为止这段时间内使用 CPU 资源的时间总数。内核将 CPU 时间,也就是进程时间分为两部分:
获取当前进程时间
#include
clock_t times(struct tms *buf);
// 返回值类型实际就是long类型,成功时返回从过去任意一个时间点所经过的时钟滴答数,就是系统节拍数,将节拍数/节拍率就是秒数,返回值可能会溢出,调用失败返回-1
// 计算一段程序耗费的进程时间和总的时间
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char *argv[])
{
struct tms _start;
struct tms _end;
clock_t start;
clock_t end;
long tck;
int i,j;
// 获取系统节拍率
tck = sysconf(_SC_CLK_TCK);
// 开始时间
start = times(&_start);
for(i=0;i<20000;i++);
{
for(j=0;j<20000;j++);
{}
}
sleep(1);
end = times(&_end);
cout << "时间总和: << (end-start)/double(tck) << endl;// 2.910000秒,从起点到终点所经过的时间,并不是进程时间
cout << "用户时间: << (_end.tms_utime-_start.tms_utime)/double(tck) << endl;// 1.900000秒
cout << "系统时间: << (_end.tms_stime-_start.tms_stime)/double(tck) << endl;// 0.000000秒
}
更简单的函数获取进程时间,返回值描述了进程使用的总的 CPU 时间,也就是进程时间。
#include
clock_t clock();
// 返回值就是到目前为止程序的进程时间,并不是系统节拍数,如果想要获取秒数,需要除 CLOCKS_PER_SEC,失败返回-1。但是此函数不能获取到单独的用户CPU时间和系统CPU时间
#include
int rand();
// 这个函数每一次运行程序获得的随机数都是相同的,需要使用srand函数设置随机数种子。rand将1作为随机数种子
#include
void srand(unsigned int seed);
一般都是将当前时间作为种子传递给seed,因为时间是一直在变化的。
// 生成一组随机数
#include
#include
#include
int main()
{
int random_number_arr[8];
int count;
srand(time(NULL));
for(count = 0; count<8;count++)
{
random_number_arr[count] = rand()%100;
}
for(count = 0; count<8;count++)
{
cout << random_number_arr[count] << " ";
}
cout << endl;
return 0;
}
#include
unsigned int sleep(unsigned int seconds);
// 如果休眠时长等于seconds,就返回0;如果被信号中断,返回剩余的秒数
#include
int usleep(useconds_t usec);
// 成功返回0,失败返回-1
#include
int nanosleep(const struct timespec *req, struct timespec *rem);
// req:设置休眠时长,可精确到纳秒级
// rem:可以设置NULL
// 如果成功休眠设定的时长,返回0;如果被信号中断或错误,返回-1,并将剩余时间记录在rem中,如果为NULL,表示不接收剩余时间
#include
void *malloc(size_t size); // 在使用时通常需要强制类型转换,该函数不会初始化内存空间
void *calloc(size_t nmemb, size_t size); // 分配nmemb个单位长度为size的连续空间,并初始化为0,总的大小是nmemb*size
void *realloc(void *ptr, size_t size); // 可以在原有的空间上扩容
void free(void *ptr); // 释放堆内存空间
当进程终止时,会自动释放申请的空间,有时,因为加入了多次的 free() 调用,可能会消耗掉大量的 CPU 时间。但是依旧建议手动释放,否则容易发生内存泄漏。
#include
int posix_memalign(void **memptr, size_t alignment, size_t size);
void *aligned_alloc(size_t alignment, size_t size);
void *valloc(size_t size);// 不建议使用
#include
void *memalign(size_t alignment, size_t size); // 不建议使用
void *pvalloc(size_t size);
posix_memalign: 在堆上分配 size 个字节大小的对齐内存空间,将 *memptr 指向分配的空间。alignment 表示对其字节数,必须是 2 的幂次方,也是指针大小的整数倍。size 是分配的内存大小,如果为0,指向的空间值为NULL
aligned_alloc: 分配 size 个字节大小的内存空间,返回指向该空间的指针
valloc: 以 pagesize 页大小作为对齐的长度,可以通过 getpagesize() 获取页大小
是一个虚拟文件系统,它以文件系统的方式为应用层访问系统内核数据提供了接口,用户和应用程序可以通过 proc 文件系统得到系统信息和进程相关信息,对 proc 文件系统的读写作为与内核进行通信的一种手段。但是与普通文件不同的是,proc 文件系统是动态创建的,文件本身不存在于磁盘当中,只存在于内存中。该文件系统挂载在 /proc 目录下
比如查看内核版本信息cat /proc/version
将你需要直到的信息读取到文件中