uname的系统信息从哪来的?

uname 是一个常用的查看 Linux 系统信息的指令。

例如,在终端中输入:

maxiee@Maxiee ~ $ uname -a
Linux Maxiee 3.12.13-gentoo #1 SMP Fri Mar 21 17:20:36 CST 2014 x86_64 Intel(R) Core(TM) i7-3630QM CPU @ 2.40GHz GenuineIntel GNU/Linux

Maxiee 有一个疑问,上面的这些系统信息,是从哪里读出来的呢?

获取Linux信息

打开 coreutils 的 uname.c ,进入 main 函数,去代码里找答案。

在 main 函数中,有这么一行:

struct utsname name;

下面又紧跟这这几行:

[code language="cpp"]

  struct utsname name;

  if (uname (&name) == -1)
    error (EXIT_FAILURE, errno, _("cannot get system name"));

  if (toprint & PRINT_KERNEL_NAME)
    print_element (name.sysname);
  if (toprint & PRINT_NODENAME)
    print_element (name.nodename);
  if (toprint & PRINT_KERNEL_RELEASE)
    print_element (name.release);
  if (toprint & PRINT_KERNEL_VERSION)
    print_element (name.version);
  if (toprint & PRINT_MACHINE)
    print_element (name.machine);

[/code]

从中便可以看出,我们寻找的系统信息,原来保存在 utsname 结构体中。

结构体的声明在 <utsname.h> ,内容如下:

[code language="cpp"]</pre>
/* Structure describing the system and machine. /
struct utsname
{
/
Name of the implementation of the operating system. */
char sysname[_UTSNAME_SYSNAME_LENGTH];

/* Name of this node on the network.  */
char nodename[_UTSNAME_NODENAME_LENGTH];

/* Current release level of this implementation.  */
char release[_UTSNAME_RELEASE_LENGTH];
/* Current version level of this release.  */
char version[_UTSNAME_VERSION_LENGTH];

/* Name of the hardware type the system is running on.  */
char machine[_UTSNAME_MACHINE_LENGTH];

#if _UTSNAME_DOMAIN_LENGTH - 0
/* Name of the domain of this node on the network. */

ifdef __USE_GNU

char domainname[_UTSNAME_DOMAIN_LENGTH];

else

char __domainname[_UTSNAME_DOMAIN_LENGTH];

endif

#endif
};
<pre>[/code]

这个结构体包含了系统名、网络名、系统版本、系统硬件类型、主机名。对应于 uname -a 返回信息的前半部分。

获取处理器信息

顺着代码往下看,下面的是获取 cpu 类型的。在这里会有很多宏,其目的是根据不同的系统类型,来调取不同的函数。在 Linux 中,使用的是 sysctl 函数来获取处理器信息。

sysctl 是 C 标准库中的函数,声明如下:

[code language="cpp"]

 #include &lt;sys/types.h&gt;
 #include &lt;sys/sysctl.h&gt;

 int
 sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen);

 int
 sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
     size_t newlen);

 int
 sysctlnametomib(const char *name, int *mibp, size_t *sizep);

[/code]

sysctl 函数的作用是获取、设置系统信息。

uname 中获取处理器类型的代码为:

[code language="cpp"]

      static char processor[257];
      size_t s = sizeof processor;
      static int mib[] = { CTL_HW, UNAME_PROCESSOR };
      if (sysctl (mib, 2, processor, &amp;s, 0, 0) &gt;= 0)
        element = processor;

[/code]

其中,CTL_HW 是定义在 <sys/sysctl.h> 中的宏,表示的是“通用处理器”。

而 UNAME_PROCESSOR 在 uname.c 的开始被定义为 HW_MACHINE_ARCH ,这也是 <sys/sysctl.h> 中的宏,表示“计算机的结构类型”。

【注意】关于这一节的内容,我发现现在 Linux 下的 sysctl.h 定义已经变化了,也就是说,这一节的内容对于 UNIX 是适用的,而对 Linux ,可能要打上相应的 patch 才能用。

我在 Gentoo 里编译了 coreutils 8.22 ,发现编译出来的 uname -p 识别为 unknown