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?
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.
locate --regex '^/usr/include/.*/sys/utsname.h$'
?
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
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 +++
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
machine.h
seems to be peppered throughout the system. Which machine.h
file does it rely on?
Jan 24, 2016 at 6:54
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
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
printf("%\n", utsname.machine);
pulling it's information from?
Jan 24, 2016 at 6:58
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).
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()
.
As an addition to heemayl's answer, you can get some information like in the uname
command from /proc/version
.