文章目录
-
- 简介
- 核心结构
- 扫描设备原理
-
- scan_abi
- scan_burner
- scan_cdrom
- scan_cpufreq
- scan_cpuid
- scan_cpuinfo
- scan_device_tree
- scan_disk
- scan_display
- scan_dmi
- scan_fat
- scan_fb
- scan_graphics
- scan_ide
- scan_ideraid
- scan_input
- scan_isapnp
- scan_lvm
- scan_memory
- scan_mmc
- scan_mounts
- scan_network
- scan_nvme
- scan_parisc
- scan_partitions
- scan_pci、scan_pci_legacy
- scan_pcmcialegacy
- scan_pcmcia
- scan_pnp
- scan_s390_devices
- scan_scsi
- scan_smp
- scan_sound
- scan_spd
- scan_sysfs
- scan_usb
- scan_vio
- scan_virtio
- scan_volume
- 总结
- 参考
简介
lshw: HardWare LiSter for Linux 一般用来查看linux设备的硬件信息,包括内存、cpu、主板等信息。
bash
$ lshw --help
Hardware Lister (lshw) -
usage: lshw [-format] [-options ...]
lshw -version
-version print program version ()
format can be
-html output hardware tree as HTML
-xml output hardware tree as XML
-json output hardware tree as a JSON object
-short output hardware paths
-businfo output bus information
options can be
-class CLASS only show a certain class of hardware
-C CLASS same as '-class CLASS'
-c CLASS same as '-class CLASS'
-disable TEST disable a test (like pci, isapnp, cpuid, etc. )
-enable TEST enable a test (like pci, isapnp, cpuid, etc. )
-quiet don't display status
-sanitize sanitize output (remove sensitive information like serial numbers, etc.)
-numeric output numeric IDs (for PCI, USB, etc.)
-notime exclude volatile attributes (timestamps) from output
代码:https://ezix.org/src/pkg/lshw.git
核心结构
cpp
class hwNode
{
public:
hwNode(const string & id,
hw::hwClass c = hw::generic,
const string & vendor = "",
const string & product = "",
const string & version = "");
hwNode(const hwNode & o);
~hwNode();
hwNode & operator =(const hwNode & o);
string getId() const;
void setHandle(const string & handle);
string getHandle() const;
bool enabled() const;
bool disabled() const;
void enable();
void disable();
bool claimed() const;
void claim(bool claimchildren=false);
void unclaim();
hw::hwClass getClass() const;
const char * getClassName() const;
void setClass(hw::hwClass c);
string getDescription() const;
void setDescription(const string & description);
string getVendor() const;
void setVendor(const string & vendor);
string getSubVendor() const;
void setSubVendor(const string & subvendor);
string getProduct() const;
void setProduct(const string & product);
string getSubProduct() const;
void setSubProduct(const string & subproduct);
string getVersion() const;
void setVersion(const string & version);
string getDate() const;
void setDate(const string &);
string getSerial() const;
void setSerial(const string & serial);
unsigned long long getStart() const;
void setStart(unsigned long long start);
unsigned long long getSize() const;
void setSize(unsigned long long size);
unsigned long long getCapacity() const;
void setCapacity(unsigned long long capacity);
unsigned long long getClock() const;
void setClock(unsigned long long clock);
unsigned int getWidth() const;
void setWidth(unsigned int width);
string getSlot() const;
void setSlot(const string & slot);
string getModalias() const;
void setModalias(const string & modalias);
unsigned int countChildren(hw::hwClass c = hw::generic) const;
hwNode * getChild(unsigned int);
hwNode * getChildByPhysId(long);
hwNode * getChildByPhysId(const string &);
hwNode * getChild(const string & id);
hwNode * findChildByHandle(const string & handle);
hwNode * findChildByLogicalName(const string & handle);
hwNode * findChildByBusInfo(const string & businfo);
hwNode * findChildByResource(const hw::resource &);
hwNode * findChild(bool(*matchfunction)(const hwNode &));
hwNode * addChild(const hwNode & node);
bool isBus() const
{
return countChildren()>0;
}
bool isCapable(const string & feature) const;
void addCapability(const string & feature, const string & description = "");
void describeCapability(const string & feature, const string & description);
string getCapabilities() const;
vector<string> getCapabilitiesList() const;
string getCapabilityDescription(const string & feature) const;
void attractHandle(const string & handle);
void setConfig(const string & key, const string & value);
void setConfig(const string & key, unsigned long long value);
string getConfig(const string & key) const;
vector<string> getConfigKeys() const;
vector<string> getConfigValues(const string & separator = "") const;
vector<string> getLogicalNames() const;
string getLogicalName() const;
void setLogicalName(const string &);
string getDev() const;
void setDev(const string &);
string getBusInfo() const;
void setBusInfo(const string &);
string getPhysId() const;
void setPhysId(long);
void setPhysId(unsigned, unsigned);
void setPhysId(unsigned, unsigned, unsigned);
void setPhysId(const string &);
void assignPhysIds();
void addResource(const hw::resource &);
bool usesResource(const hw::resource &) const;
vector<string> getResources(const string & separator = "") const;
void addHint(const string &, const hw::value &);
hw::value getHint(const string &) const;
vector<string> getHints() const;
void merge(const hwNode & node);
void fixInconsistencies();
string asXML(unsigned level = 0);
string asJSON(unsigned level = 0);
string asString();
bool dump(const string & filename, bool recurse = true);
private:
void setId(const string & id);
bool attractsHandle(const string & handle) const;
bool attractsNode(const hwNode & node) const;
struct hwNode_i * This;
};
扫描设备原理
大部分都是通过读取/proc
、/sys
、/dev
虚拟文件系统下面的文件内容获取系统运行状态和设备信息。
下面就依次分析lshw源码中core文件夹下面提供的函数:
scan_abi
/proc/sys/abi
,含义参考https://www.kernel.org/doc/Documentation/admin-guide/sysctl/abi.rst
scan_burner
ioctl
执行scsi命令
scan_cdrom
核心代码:
c++
ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
ioctl(fd, CDROM_GET_CAPABILITY);
ioctl(fd, CDROM_DRIVE_STATUS, 0)
scan_cpufreq
/sys/devices/system/cpu/cpu%d/cpufreq/
,下面有cpu频率信息
bash
ls /sys/devices/system/cpu/cpu0/cpufreq/
affected_cpus cpuinfo_min_freq energy_performance_preference scaling_cur_freq scaling_max_freq
base_frequency cpuinfo_transition_latency related_cpus scaling_driver scaling_min_freq
cpuinfo_max_freq energy_performance_available_preferences scaling_available_governors scaling_governor scaling_setspeed
scan_cpuid
scan_cpuinfo
/proc/cpuinfo
,从该文件获取cpu信息。
scan_device_tree
/proc/device-tree
,从该路径下获取信息
scan_disk
核心代码:
c++
long size = 0;
unsigned long long bytes = 0;
int sectsize = 0;
int physsectsize = 0;
int fd = open(disk_path, O_RDONLY | O_NONBLOCK);
ioctl(fd, BLKPBSZGET, &physsectsize)
ioctl(fd, BLKSSZGET, §size)
ioctl(fd, BLKGETSIZE64, &bytes)
(ioctl(fd, BLKGETSIZE, &size)
scan_display
scan_dmi
/sys/firmware/dmi/tables
,扫描该路径下面信息。
bash
$ ls /sys/firmware/dmi/tables
DMI smbios_entry_point
还会尝试结合/dev/mem
、/sys/firmware/efi/systab
和/proc/efi/systab
的内容分析。
scan_fat
读取裸设备块数据,随后解析FAT文件系统格式。
scan_fb
从/proc/devices
中获取fb设备号,随后获取到framebuffer设备文件描述符fb,核心代码:
c++
#define FBIOGET_VSCREENINFO 0x4600
#define FBIOGET_FSCREENINFO 0x4602
ioctl(fd[i], FBIOGET_FSCREENINFO, &fbi);
ioctl(fd[i], FBIOGET_VSCREENINFO, &fbconfig);
scan_graphics
/sys/class/graphics
,扫描该路径下面的设备信息。
bash
ls /sys/class/graphics/fb0/
bits_per_pixel bl_curve cursor device modes pan rotate stride uevent
blank console dev mode name power state subsystem virtual_size
scan_ide
/proc/ide
,扫描该路径下设备的信息。
scan_ideraid
扫描ideraid设备,核心还是通过ioctl
来直接获取设备信息。
scan_input
/sys/class/input
,扫描该路径下面设备信息。
bash
$ ls /sys/class/input/
event0 event2 event4 input0 input3 input5 js0 mouse0 mouse2
event1 event3 event5 input1 input4 input6 mice mouse1
scan_isapnp
scan_lvm
通过读取裸设备文件,通过解析LVM2 structures获取lvm信息。
scan_memory
核心代码
c++
pagesize = sysconf(_SC_PAGESIZE);
physpages = sysconf(_SC_PHYS_PAGES);
stat("/proc/kcore", &buf)
读取/sys/bus/memory
、/sys/devices/system/memory/
bash
$ ls /sys/bus/memory/
devices drivers drivers_autoprobe drivers_probe uevent
$ ls /sys/devices/system/memory/
auto_online_blocks memory1 memory13 memory3 memory35 memory39 memory42 memory46 memory7 probe
block_size_bytes memory10 memory14 memory32 memory36 memory4 memory43 memory47 memory8 soft_offline_page
hard_offline_page memory11 memory15 memory33 memory37 memory40 memory44 memory5 memory9 uevent
memory0 memory12 memory2 memory34 memory38 memory41 memory45 memory6 power
scan_mmc
/sys/class/mmc_host/
scan_mounts
/proc/mounts
读取挂载信息。
scan_network
通过扫描/proc/net/dev
、/sys/class/net
获取网络设备,之后通过ioctl
获取设备信息。
scan_nvme
扫描/sys/class/nvme
获取nvme设备,之后再扫描磁盘。
scan_parisc
/sys/devices/parisc
scan_partitions
扫描磁盘分区
scan_pci、scan_pci_legacy
扫描/proc/bus/pci
、/sys/bus/pci
获取pci设备,随后读取设备裸数据来获取信息。
scan_pcmcialegacy
scan_pcmcia
scan_pnp
/sys/bus/pnp
scan_s390_devices
scan_scsi
扫描scsi设备,/proc/scsi
、/sys/class/scsi_*
。
scan_smp
/sys/devices/system/cpu/online
scan_sound
/sys/class/sound
scan_spd
/proc/sys/dev/sensors
、
scan_sysfs
scan_usb
/proc/bus/usb/devices
、/sys/kernel/debug/usb/devices
scan_vio
/sys/bus/vio
scan_virtio
/sys/bus/virtio
scan_volume
总结
lshw源码用到一下几点
- linux内核文件系统
- 系统接口如
ioctl
、stat
等 - 操作系统概念,比如文件系统结构、网络、总线
- 工程上抽象出统一的设备结构
以上只是对lshw的初步分析,进一步的理解还是需要直接阅读代码。
参考
Hardware Lister (lshw)
linux内核文件系统:proc、tmpfs、devfs、sysfs简要介绍
linux下 /proc 和 /sys 详解
Linux kernel简介
proc/sys目录介绍
Documentation for /proc/sys/abi/
The Linux Kernel documentation