【问题标题】:What API do I call to get the system uptime?我应该调用什么 API 来获得系统正常运行时间?
【发布时间】:2009-10-08 21:31:51
【问题描述】:

我想在基于 linux 的系统上运行的 C 应用程序中获取系统正常运行时间。我不想调用 uptime(1) 并解析输出,我想调用我怀疑存在的底层 C API。有谁知道有没有这样的调用,或者 uptime(1) 只是简单地处理从 wtmp 获得的记录?

【问题讨论】:

  • 是否有可能在纳秒内获得正常运行时间???你试过了吗?

标签: c linux uptime


【解决方案1】:

您要查找的系统调用是 sysinfo()。

在 sys/sysinfo.h 中定义

它的签名是: int sysinfo(struct sysinfo *info)

自内核 2.4 以来,结构如下所示:

struct sysinfo {
    long uptime;             /* Seconds since boot */
    unsigned long loads[3];  /* 1, 5, and 15 minute load averages */
    unsigned long totalram;  /* Total usable main memory size */
    unsigned long freeram;   /* Available memory size */
    unsigned long sharedram; /* Amount of shared memory */
    unsigned long bufferram; /* Memory used by buffers */
    unsigned long totalswap; /* Total swap space size */
    unsigned long freeswap;  /* swap space still available */
    unsigned short procs;    /* Number of current processes */
    unsigned long totalhigh; /* Total high memory size */
    unsigned long freehigh;  /* Available high memory size */
    unsigned int mem_unit;   /* Memory unit size in bytes */
    char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */
};

玩得开心!

【讨论】:

  • 我已经按照上面 bdonlan 的建议实现了读取 /proc/uptime,但是调用 API 而不是读取“文件”正是我想要的。谢谢!
  • 是否可以获得纳秒级信息(正常运行时间)??
【解决方案2】:

应该是这样的。

#include <stdio.h>
#include <errno.h>
#include <linux/unistd.h>       /* for _syscallX macros/related stuff */
#include <linux/kernel.h>       /* for struct sysinfo */
#include <sys/sysinfo.h>

long get_uptime()
{
    struct sysinfo s_info;
    int error = sysinfo(&s_info);
    if(error != 0)
    {
        printf("code error = %d\n", error);
    }
    return s_info.uptime;
}

有关详细信息,请参阅“man sysinfo”。

【讨论】:

    【解决方案3】:

    读取文件/proc/uptime,取第一个十进制数作为正常运行时间,以秒为单位。

    来自man 5 proc

       /proc/uptime
              This file contains two numbers: the uptime of the  system  (sec‐
              onds), and the amount of time spent in idle process (seconds).
    

    【讨论】:

    • ...如果你 strace uptime(1) 命令,你会看到它就是这样做的。
    • caf:在linux机器上,BSD机器一般使用“当前时间-syctl kern.boottime”
    • @caf, uptime(1) 的作用远不止于此,因此可能有点难找 :)
    • @Tarrant:如果有人使用 'date' 或 settimeofday() API 重置当前时间,这种方法会给出错误的结果。我正在寻找不受时间/日期设置影响的基于刻度的东西
    【解决方案4】:

    还有clock_gettime(可能需要-lrt)。我看到的行为(我不会声称它是有保证的)但将CLOCK_MONOTONIC 指定为clk_id 是它在给定的struct timespec * 参数中返回系统正常运行时间。

    #include <stdio.h>
    #include <time.h>
    
    int main(int argc, char* argv[]) {
      struct timespec t;
      clock_gettime(CLOCK_MONOTONIC, &t);
      printf("tv_sec=%llu tv_nsec=%llu\n",
        (unsigned long long)t.tv_sec,
        (unsigned long long)t.tv_nsec);
      return 0;
    }
    

    【讨论】:

    • 不,它没有;单调时钟有一个任意的纪元。您链接的联机帮助页就是这么说的。
    • @BoundaryImposition 这个问题被标记为 linux 并且在 Linux 中的行为是(和still is,正如我所描述的)。 POSIX 说时代是任意的,Linux 实现与正常运行时间相关。请参阅kernel/time/posix-timers.cfs/proc/uptime.c。还有here is a relevant LKML thread
    • 您已链接到实施文件。这可能随时改变。问题是关于 API 的,API 说时代是任意的。任意并不意味着没有一个时代,它只是意味着不依赖于选择。您链接到我的 LKML 线程实际上说明了这一点。
    • 在我的回答中,我写道“我不会声称它是有保证的。”该问题的文本还特别提到“linux”作为用例。 LKML 线程还指出,该行为不太可能很快改变。 POSIX 有助于编写跨兼容平台可靠运行的代码。如果用例只涵盖一个平台,那么依赖平台的行为似乎是非常合理的。
    • 由于 Lightness Races In Orbit 所描述的原因,我认为这是一个糟糕的答案。有一个工作的 linux-specific api 将无法在其他操作系统上编译,这比依赖 os-general api 的特定于操作系统的行为更好到编译器。
    【解决方案5】:
    #include <sys/sysinfo.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <grp.h>
    
    int main() {
      struct sysinfo sys_info;
      struct group* grp;
    
        gid_t gid;
        char** users;
    
      int days, hours, mins, x = 1;
    
      system("clear");  
      printf("\033[4;40m            Systems information                   \033[0;m \n");
      if(sysinfo(&sys_info) != 0)
        perror("sysinfo");
    
      days = sys_info.uptime / 86400;
      hours = (sys_info.uptime / 3600) - (days * 24);
      mins = (sys_info.uptime / 60) - (days * 1440) - (hours * 60);
    
      printf("\033[1;33m  Uptime: \033[0;36m %ddays, %dhours, %dminutes, %ldseconds \033[0;m \n",
                          days, hours, mins, sys_info.uptime % 60);
    
      printf("\033[1;33m  Load Avgs: \033[0;m 1min(%ld) 5min(%ld) 15min(%ld) \n",
              sys_info.loads[0], sys_info.loads[1], sys_info.loads[2]);
    
      printf("\033[1;33m  Total Ram: \033[0;m %ldk \t Free: %ldk \n", sys_info.totalram / 1024, sys_info.freeram / 1024);
      printf(" \033[1;33m Shared Ram: \033[0;m %ldk ", sys_info.sharedram / 1024);
      printf("  Buffered Ram: %ldk \n", sys_info.bufferram / 1024);
      printf("\033[1;33m  Total Swap: \033[0;m %ldk \t Free swap: %ldk \n", sys_info.totalswap / 1024, sys_info.freeswap / 1024);
      printf("\033[1;33m  Total High Memory: \033[0;m %ldk  Free high memory: %ldk \033[0;m \n", sys_info.totalhigh / 1024, sys_info.freehigh / 1024);
      printf(" \n");
      printf("\033[1;44m Total Number of processes: %d \033[0;m \n", sys_info.procs);  
      gid = getgid();
        printf("  Group ID: \033[031m %d", gid);
        if((grp = getgrgid(gid)) == NULL ) return 1;
        printf("\033[0;m Group %s ", grp->gr_name );
        printf("\n  Users in your group ");
        for( users = grp->gr_mem; *users != NULL; users++,++x ); printf( "%d", ++x);     
        if(strcmp(grp->gr_passwd,"x") == 0) printf("  Password is protected by shadow file. \n");
        else printf("Password: %s ", grp->gr_passwd);   
    
        return 0;
    }
    

    【讨论】:

    • 一个好的答案不仅应该包括代码,还应该包括一些关于它是如何工作的以及它为什么回答问题的解释。尤其如此,因为该问题已经有一个公认的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 2019-10-25
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多