Câu trả lời:
uname
sử dụng lệnh gọi hệ thống uname(2)
để lấy thông tin liên quan đến kernel mà nó hiển thị.
Bản tóm tắt là:
#include <sys/utsname.h>
int uname(struct utsname *buf);
nơi uname(2)
trả về thông tin trong cấu trúc được chỉ bởi buf
. Ngoài ra, bạn có thể đọc tệp tiêu đề utsname.h
từ /usr/include/"$(arch)"-linux-gnu/sys/utsname.h
để đào sâu hơn.
Có một cái nhìn man 2 uname
để có thêm ý tưởng về điều này.
locate --regex '^/usr/include/.*/sys/utsname.h$'
?
uname -i
đầu ra là x86_64
. Khi tôi chạy locate --regex '^/usr/include/.*/sys/utsname.h$'
kết quả đầu ra/usr/include/x86_64-linux-gnu/sys/utsname.h
Chương trình strace
cho phép chúng tôi xem các cuộc gọi hệ thống mà một ứng dụng có thể thực hiện. Với uname -a
nó rõ ràng rằng chỉ open
các cuộc gọi đi đến các thư viện hệ thống, vì vậy về mặt kỹ thuật không có tập tin trên hệ thống tập tin mà uname
mở ra để đọc. Thay vào đó, nó thực hiện các cuộc gọi hệ thống bằng cách sử dụng các thư viện C.
Như heemayl đã chỉ ra một cách chính xác, có tồn tại lệnh gọi sys để lấy thông tin được lưu trữ trong uname
cấu trúc. Đó là trang đàn ông, gợi ý như sau:
Đây là một cuộc gọi hệ thống và hệ điều hành có lẽ biết tên, phiên bản và phiên bản của nó. . . . . . Một phần thông tin utsname cũng có thể truy cập thông qua / Proc / sys / ker‐ nel / {lasype, tên máy chủ, osrelease, phiên bản, tên miền}.
Một phần thông tin utsname cũng có thể truy cập thông qua / Proc / sys / ker‐ nel / {lasype, tên máy chủ, osrelease, phiên bản, tên miền}.
/proc
Tuy nhiên, hệ thống tập tin là ảo, có nghĩa là nó chỉ tồn tại trong khi HĐH đang chạy. Do đó, với một số phần mở rộng, nó được đặt trong các thư viện kernel hoặc hệ thống.
Cuối cùng, đọc qua mã nguồn uname.c
có thể lấy được apt-get source coreutils
, chúng ta có thể thấy rằng nó thực sự sử dụng utsname.h
thư viện (được in bằng số dòng):
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
đầu ra:
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
không nhất thiết phải sử dụng một thư viện cho điều đó - tất nhiên chúng ta có thể nhìn vào mã nguồn để chắc chắn.
machine.h
machine.h
dường như được tiêu trên toàn hệ thống. Những machine.h
tập tin nào nó dựa vào?
machine.h
trên hệ thống của tôi dường như nằm trong /usr/src/linux-headers-3.19.0-33
thư mục. Rất có khả năng nó sử dụng thư viện được cung cấp bởi kernel hiện đang chạy
Tất nhiên câu trả lời của heemayl là chính xác.
Để giải trí, đây là đoạn mã C hoạt động hiển thị dữ liệu được trả về uname()
(một loại tự chế uname
nếu bạn muốn): biên dịch nó với gcc uname.c -o uname
và chạy với ./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);
kéo nó thông tin từ đâu?
utsname
, được điền trong cuộc gọi đến uname()
. Ví dụ có lẽ không quá đơn giản với người không có kiến thức cơ bản về C, nhưng đây là những gì xảy ra: một struct
(kiểu dữ liệu C) utsname
có tên utsname
(kiểu được xác định trong <sys/utsname.h>
) được khai báo; sau đó một con trỏ tới nó được đặt tên utsname_ptr
được khai báo (vì uname()
chấp nhận một con trỏ đến một struct
kiểu utsname
làm đối số, mặc dù điều này có thể tránh được trong trường hợp này, nhưng đó là một câu chuyện khác).
uname()
có tác dụng điền vào cấu trúc utsname
, tại thời điểm printf()
cuộc gọi chứa các giá trị khác nhau bên trong các trường khác nhau. Thật không may nếu bạn không quen thuộc với C, điều này có lẽ sẽ không dễ nắm bắt chi tiết, nhưng điểm quan trọng là uname()
tạo ra một cấu trúc dữ liệu được xây dựng trên mục đích, có các trường được in sau đó printf()
.
Ngoài câu trả lời của heemayl, bạn có thể nhận được một số thông tin như trong uname
lệnh từ /proc/version
.