Where is "uname" pulling information from?
Solution 1
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.
Solution 2
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 +++
Solution 3
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
Solution 4
As an addition to heemayl's answer, you can get some information like in the uname
command from /proc/version
.
Related videos on Youtube
![Roy Hernandez](https://lh4.googleusercontent.com/-6AZZ0Vy9r1g/AAAAAAAAAAI/AAAAAAAAFJs/xkVFn5YRKu8/photo.jpg?sz=256)
Roy Hernandez
Updated on September 18, 2022Comments
-
Roy Hernandez almost 2 years
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?
-
Mark Plotnick over 8 years
-
-
Roy Hernandez over 8 yearswhen 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?
-
Roy Hernandez over 8 yearswhen 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?
-
Roy Hernandez over 8 years/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".
-
Sergiy Kolodyazhnyy over 8 years@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. -
heemayl over 8 years@RoyHernandez Whats the output of
locate --regex '^/usr/include/.*/sys/utsname.h$'
? -
Roy Hernandez over 8 yearsThe output is: "/usr/include/x86_64-linux-gnu/sys/utsname.h "
-
heemayl over 8 years@RoyHernandez This tells that the file does exist and you were doing something wrong..
-
Roy Hernandez over 8 years
machine.h
seems to be peppered throughout the system. Whichmachine.h
file does it rely on? -
Roy Hernandez over 8 yearswhere is the
printf("%\n", utsname.machine);
pulling it's information from? -
Sergiy Kolodyazhnyy over 8 years@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 -
Roy Hernandez over 8 yearsWhen I run a
uname -i
the output isx86_64
. When I runlocate --regex '^/usr/include/.*/sys/utsname.h$'
the output returns/usr/include/x86_64-linux-gnu/sys/utsname.h
-
Roy Hernandez over 8 yearsI am not sure... I don't see a
machine.h
on my computer within the/usr/src/linux-headers-3.19.0-33
directory. I am not sure how to cross reference the output ofuname -i
. -
heemayl over 8 years@RoyHernandez so, i don't get it..whats wrong with
/usr/include/"$(uname -i)"-linux-gnu/sys/utsname.h
? -
Sergiy Kolodyazhnyy over 8 yearsHow about this ?
find /usr/src/linux-headers-$(uname -r)/include/ -name "machine.h"
-
Sergiy Kolodyazhnyy over 8 yearsLet me actually read the source of
uname.c
a bit more, and I'll get back to you later once i figure this out. -
Roy Hernandez over 8 years
find /usr/src/linux-headers-$(uname -r)/include/ -name "machine.h"
output is/usr/src/linux-headers-3.19.0-47-generic/include/config/stop/machine.h
-
Roy Hernandez over 8 yearsI am not sure. I am just trying to figure out where
uname -i
is gathering it's output and it seems to be verify difficult. -
kos over 8 yearsThen the call to
uname()
has the effect of populating the structutsname
, which at the time of theprintf()
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 thatuname()
populates a data structure built on purpose, whose fields are later printed viaprintf()
.