bash top first_line - ceragon/LinuxDoc GitHub Wiki
top - 10:49:30 up 4 days, 13:08, 1 user, load average: 0.10, 0.28, 0.20
任务: 306 total, 1 running, 304 sleeping, 0 stopped, 1 zombie
%Cpu(s): 3.5 us, 1.4 sy, 0.0 ni, 95.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 15897.9 total, 235.3 free, 8007.0 used, 7655.7 buff/cache
MiB Swap: 2048.0 total, 1687.5 free, 360.5 used. 7403.8 avail Mem
进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND
446465 ceragon 20 0 11.7g 5.1g 535188 S 25.0 33.0 38:23.92 ld-linux-x86-64
517659 ceragon 20 0 15112 3984 3204 R 12.5 0.0 0:00.02 top
452 root -51 0 0 0 0 S 6.2 0.0 0:52.38 irq/168-iwlwifi
328018 ceragon 20 0 11.7g 2.4g 465028 S 6.2 15.2 69:05.34 ld-linux-x86-64
1 root 20 0 169256 11512 6604 S 0.0 0.1 0:09.36 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.09 kthreadd
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
top - 10:49:30
static char buf[256];
char *sprint_uptime(int human_readable) {
struct tm *realtime;
time_t realseconds;
// ======= 调用 glibc 的 time 方法
time(&realseconds);
// ======= 调用 glibc 的 localtime 方法
// 当前时间
realtime = localtime(&realseconds);
// 打印时分秒
pos = sprintf(buf, " %02d:%02d:%02d ",
realtime->tm_hour, realtime->tm_min, realtime->tm_sec);
}
up 4 days, 13:08,
char *sprint_uptime(int human_readable) {
int updays;
double uptime_secs, idle_secs;
uptime(&uptime_secs, &idle_secs);
// 将秒转换为天
updays = (int) uptime_secs / (60*60*24);
// 追加字符串 up
strcat (buf, "up ");
pos += 3;
if (updays)
// 打印启动后的天数
pos += sprintf(buf + pos, "%d day%s, ", updays, (updays != 1) ? "s" : "");
// 分钟
upminutes = (int) uptime_secs / 60;
// 小时
uphours = upminutes / 60;
uphours = uphours % 24;
upminutes = upminutes % 60;
// 打印启动后的小时和分钟
pos += sprintf(buf + pos, "%2d:%02d, ", uphours, upminutes);
}
手动执行命令可以看到的信息
$ cat /proc/uptime
1291.55 9247.65
方法实现
#define UPTIME_FILE "/proc/uptime"
static int uptime_fd = -1;
static char buf[8192];
int uptime(double *restrict uptime_secs, double *restrict idle_secs) {
double up=0, idle=0;
FILE_TO_BUF(UPTIME_FILE,uptime_fd);
// buf 是个字符串,格式是两个 double 类型的数字,如下面所示
sscanf(buf, "%lf %lf", &up, &idle);
SET_IF_DESIRED(uptime_secs, up);
return up;
}
FILE_TO_BUF() 宏的展开
void FILE_TO_BUF(){
static int local_n;
// 由于 /proc/uptime 是个文件,所以要像文件一样操作
if (uptime_fd == -1 && (uptime_fd = open("/proc/uptime", 00)) == -1) {
return;
}
// 重置读索引
lseek(uptime_fd, 0L, 0);
// 读取信息到 buf 中
if ((local_n = read(uptime_fd, buf, sizeof buf - 1)) < 0) {
return;
}
buf[local_n] = '\0';
}
1 user,
struct utmp {
short int ut_type; /* Type of login. */
pid_t ut_pid; /* Process ID of login process. */
char ut_user[UT_NAMESIZE] /* Username. */
};
#define USER_PROCESS 7 /* Normal process. */
#define ut_name ut_user
char *sprint_uptime(int human_readable) {
struct utmp *utmpstruct;
numuser = 0;
// 重置文件的读入流
setutent();
// Read next entry from a utmp-like file.
// ========== getutent() 调用 glibc 的库
while ((utmpstruct = getutent())) {
// 类型是 7,且用户名不为空
if ((utmpstruct->ut_type == USER_PROCESS) &&
(utmpstruct->ut_name[0] != '\0'))
// 用户数 +1
numuser++;
}
// 结束文件读入
endutent();
// 打印在线用户数
pos += sprintf(buf + pos, "%2d user%s, ", numuser, numuser == 1 ? "" : "s");
}
load average: 0.10, 0.28, 0.20
static double av[3];
char *sprint_uptime(int human_readable) {
loadavg(&av[0], &av[1], &av[2]);
pos += sprintf(buf + pos, " load average: %.2f, %.2f, %.2f",
av[0], av[1], av[2]);
}
$ cat /proc/loadavg
0.15 0.19 0.19 1/622 11603
void loadavg(double *restrict av1, double *restrict av5, double *restrict av15) {
double avg_1=0, avg_5=0, avg_15=0;
FILE_TO_BUF(LOADAVG_FILE,loadavg_fd);
if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) {
return;
}
SET_IF_DESIRED(av1, avg_1);
SET_IF_DESIRED(av5, avg_5);
SET_IF_DESIRED(av15, avg_15);
}
void FILE_TO_BUF(){
static int local_n;
// 由于 /proc/loadavg 是个文件,所以要像文件一样操作
if (uptime_fd == -1 && (uptime_fd = open("/proc/loadavg", 00)) == -1) {
return;
}
// 重置读索引
lseek(uptime_fd, 0L, 0);
// 读取信息到 buf 中
if ((local_n = read(uptime_fd, buf, sizeof buf - 1)) < 0) {
return;
}
buf[local_n] = '\0';
}