25

Where is uname -i pulling the information from?

Do the details exist in /etc/?

Do the details exist in /proc/?

If so, which file is it referencing to output those details?

1

4 Answers 4

31

uname uses the system call uname(2) to get the kernel related information it shows.

The synopsis is:

#include <sys/utsname.h>
int uname(struct utsname *buf);

where uname(2) returns information in the structure pointed to by buf. Also you can read the header file utsname.h from /usr/include/"$(arch)"-linux-gnu/sys/utsname.h to dig deeper.

Have a look at man 2 uname to get more idea about this.

7
  • when I run "uname -i", the output is "x86_64". When I cross reference "/usr/include/x86_64-linux-gnu/sys/utsname.h", I don't see anything that references "x86_64". I referenced the "man 2 uname" and it states that part of utsname information is referenced via "/proc/sys/kernel/{ostype}, {hostname}, {osrelease}, {version} and {domainname}" the problem is that none of those files reference anything stating "x86_64". Any other recommendations? Jan 23, 2016 at 23:40
  • @RoyHernandez Whats the output of locate --regex '^/usr/include/.*/sys/utsname.h$'?
    – heemayl
    Jan 24, 2016 at 1:04
  • The output is: "/usr/include/x86_64-linux-gnu/sys/utsname.h " Jan 24, 2016 at 6:40
  • @RoyHernandez This tells that the file does exist and you were doing something wrong..
    – heemayl
    Jan 24, 2016 at 6:48
  • When I run a uname -i the output is x86_64. When I run locate --regex '^/usr/include/.*/sys/utsname.h$' the output returns /usr/include/x86_64-linux-gnu/sys/utsname.h Jan 24, 2016 at 7:16
22

The program strace allows us to view the system calls an application may make. With uname -a it's apparent that the only open calls go to system libraries, so technically there is no file on the filesystem that the uname opens for reading. Rather it makes system calls using the C libraries.

As heemayl properly pointed out there exists sys call to retrieving the information stored in the uname structure. It's man page, suggests the following:

This is a system call, and the operating system presumably knows its name, release and version . . . . . . Part of the utsname information is also accessible via /proc/sys/ker‐ nel/{ostype, hostname, osrelease, version, domainname}.

Part of the utsname information is also accessible via /proc/sys/ker‐ nel/{ostype, hostname, osrelease, version, domainname}.

/proc filesystem however is virtual, meaning it exists only while the OS is running. Thus to some extend it is set within kernel or system libraries.

Finally, reading through the source code of uname.c which can be obtained with apt-get source coreutils , we can see that it indeed uses the utsname.h library(printed with line numbers):

 19 
 20 #include <config.h>
 21 #include <stdio.h>
 22 #include <sys/types.h>
 23 #include <sys/utsname.h>
 24 #include <getopt.h>
 25 

strace output:

skolodya@ubuntu:$ strace uname -a
execve("/bin/uname", ["uname", "-a"], [/* 58 vars */]) = 0
brk(0)                                  = 0x1478000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6935000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=137226, ...}) = 0
mmap(NULL, 137226, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7efee6913000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7efee6350000
mprotect(0x7efee650b000, 2093056, PROT_NONE) = 0
mmap(0x7efee670a000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7efee670a000
mmap(0x7efee6710000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7efee6710000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6912000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6910000
arch_prctl(ARCH_SET_FS, 0x7efee6910740) = 0
mprotect(0x7efee670a000, 16384, PROT_READ) = 0
mprotect(0x606000, 4096, PROT_READ)     = 0
mprotect(0x7efee6937000, 4096, PROT_READ) = 0
munmap(0x7efee6913000, 137226)          = 0
brk(0)                                  = 0x1478000
brk(0x1499000)                          = 0x1499000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=7216688, ...}) = 0
mmap(NULL, 7216688, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7efee5c6e000
close(3)                                = 0
uname({sys="Linux", node="eagle", ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6934000
uname({sys="Linux", node="eagle", ...}) = 0
uname({sys="Linux", node="eagle", ...}) = 0
write(1, "Linux eagle 4.1.0-040100rc2-gene"..., 113Linux eagle 4.1.0-040100rc2-generic #201505032335 SMP Mon May 4 03:36:35 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
) = 113
close(1)                                = 0
munmap(0x7efee6934000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
9
  • when I run "uname -i", the output is "x86_64". When I cross reference "/usr/include/x86_64-linux-gnu/sys/utsname.h", I don't see anything that references "x86_64". I referenced the "man 2 uname" and it states that part of utsname information is referenced via "/proc/sys/kernel/{ostype}, {hostname}, {osrelease}, {version} and {domainname}" the problem is that none of those files reference anything stating "x86_64". Any other recommendations? Jan 23, 2016 at 23:41
  • @RoyHernandez In C it's possible to determine architecture of a CPU based on the size that integer takes , for instance - refer here. So the uname.c doesn't necessarily need to use a library for that - we can look at the source code, of course, to be sure. Jan 23, 2016 at 23:48
  • Actually, it does rely on a library . . . machine.h Jan 23, 2016 at 23:53
  • machine.h seems to be peppered throughout the system. Which machine.h file does it rely on? Jan 24, 2016 at 6:54
  • @RoyHernandez all the listed machine.h on my system seem to be in the /usr/src/linux-headers-3.19.0-33 directory. It's very likely that it uses the library provided by the currently running kernel Jan 24, 2016 at 7:02
6

Of course heemayl's answer is correct.

Just for fun, here's a working C snippet showcasing the data returned by uname() (a sort of a homemade uname if you want): compile it with gcc uname.c -o uname and run it with ./uname:

#include <stdio.h> // printf()
#include <sys/utsname.h> // uname()

int main() {
        int ret; // stores the return value of uname()
        struct utsname utsname; // stores the data returned by uname()
        struct utsname *utsname_ptr = &utsname; // pointer to the struct holding the data returned by uname()

        ret = uname(utsname_ptr); // calls uname() on utsname_ptr and stores its return value in ret

        /* prints the fields of utsname */

        printf("%s\n", utsname.sysname);
        printf("%s\n", utsname.nodename);
        printf("%s\n", utsname.release);
        printf("%s\n", utsname.version);
        printf("%s\n", utsname.machine);

        /* returns the return value of uname() */

        return(ret);
}
% ./uname 
Linux
user-X550CL
4.2.0-25-generic
#30-Ubuntu SMP Mon Jan 18 12:31:50 UTC 2016
x86_64
3
  • where is the printf("%\n", utsname.machine); pulling it's information from? Jan 24, 2016 at 6:58
  • @RoyHernandez From the struct utsname, which is populated during the call to uname(). The example probably it's not too straightforward to someone without C basics, but here's more or less what happens: a struct (C data type) of type utsname named utsname (type defined in <sys/utsname.h>) is declared; then a pointer to it named utsname_ptr is declared (since uname() accepts a pointer to a struct of type utsname as an argument, though this could have been avoided in this case, but that's another story).
    – kos
    Jan 24, 2016 at 9:36
  • Then the call to uname() has the effect of populating the struct utsname, which at the time of the printf() call contains the various values inside the various fields. Unluckily if you are not familiar with C this is probably not going to be easy to grasped in detail, but the point is that uname() populates a data structure built on purpose, whose fields are later printed via printf().
    – kos
    Jan 24, 2016 at 9:53
4

As an addition to heemayl's answer, you can get some information like in the uname command from /proc/version.

1
  • /proc/version contains "Linux version 3.19.0-47-generic (buildd@lgw01-19) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #53~14.04.1-Ubuntu SMP Mon Jan 18 16:09:14 UTC 2016" and "uname -i" output is "x86_64". Jan 23, 2016 at 23:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .