的Linux
如您所建议,fcntl是在Linux上执行此操作的方法。您要转换的C代码如下所示:
static struct hd_driveid hd;int fd;if ((fd = open("/dev/hda", O_RDonLY | O_NONBLOCK)) < 0) { printf("ERROR opening /dev/hdan"); exit(1);}if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) { printf("%.20sn", hd.serial_no);} else if (errno == -ENOMSG) { printf("No serial number availablen");} else { perror("ERROR: HDIO_GET_IDENTITY"); exit(1);}在Ubuntu 9.10上将其翻译成Python,它有点像这样:
import sys, os, fcntl, structif os.geteuid() > 0: print("ERROR: Must be root to use") sys.exit(1)with open(sys.argv[1], "rb") as fd: # tediously derived from the monster struct defined in <hdreg.h> # see comment at end of file to verify hd_driveid_format_str = "@ 10H 20s 3H 8s 40s 2B H 2B H 4B 6H 2B I 36H I Q 152H" # Also from <hdreg.h> HDIO_GET_IDENTITY = 0x030d # How big a buffer do we need? sizeof_hd_driveid = struct.calcsize(hd_driveid_format_str) # ensure our format string is the correct size # 512 is extracted using sizeof(struct hd_id) in the c pre assert sizeof_hd_driveid == 512 # Call native function buf = fcntl.ioctl(fd, HDIO_GET_IDENTITY, " " * sizeof_hd_driveid) fields = struct.unpack(hd_driveid_format_str, buf) serial_no = fields[10].strip() model = fields[15].strip() print("Hard Disk Model: %s" % model) print(" Serial Number: %s" % serial_no)## For documentation purposes, this is the struct copied from <hdreg.h># struct hd_driveid {# unsigned short config; # unsigned short cyls; # unsigned short reserved2; # unsigned short heads; # unsigned short track_bytes; # unsigned short sector_bytes; # unsigned short sectors; # unsigned short vendor0; # unsigned short vendor1; # unsigned short vendor2; # unsigned char serial_no[20]; # unsigned short buf_type; # unsigned short buf_size; # unsigned short ecc_bytes; # unsigned char fw_rev[8]; # unsigned char model[40]; # unsigned char max_multsect; # unsigned char vendor3; # unsigned short dword_io; # unsigned char vendor4; # unsigned char capability; # unsigned short reserved50; # unsigned char vendor5; # unsigned char tPIO; # unsigned char vendor6; # unsigned char tDMA; # unsigned short field_valid; # unsigned short cur_cyls; # unsigned short cur_heads; # unsigned short cur_sectors; # unsigned short cur_capacity0; # unsigned short cur_capacity1; # unsigned char multsect; # unsigned char multsect_valid; # unsigned int lba_capacity; # unsigned short dma_1word; # unsigned short dma_mword; # unsigned short eide_pio_modes; # unsigned short eide_dma_min; # unsigned short eide_dma_time; # unsigned short eide_pio; # unsigned short eide_pio_iordy; # unsigned short words69_70[2]; # unsigned short words71_74[4]; # unsigned short queue_depth; # unsigned short words76_79[4]; # unsigned short major_rev_num; # unsigned short minor_rev_num; # unsigned short command_set_1; # unsigned short command_set_2; # unsigned short cfsse; # unsigned short cfs_enable_1; # unsigned short cfs_enable_2; # unsigned short csf_default; # unsigned short dma_ultra; # unsigned short trseuc; # unsigned short trsEuc; # unsigned short CurAPMvalues; # unsigned short mprc; # unsigned short hw_config; # unsigned short acoustic; # unsigned short msrqs; # unsigned short sxfert; # unsigned short sal; # unsigned int spg; # unsigned long long lba_capacity_2;# unsigned short words104_125[22];# unsigned short last_lun; # unsigned short word127; # unsigned short dlf; # unsigned short csfo; # unsigned short words130_155[26];# unsigned short word156; # unsigned short words157_159[3];# unsigned short cfa_power; # unsigned short words161_175[15];# unsigned short words176_205[30];# unsigned short words206_254[49];# unsigned short integrity_word; # };抱歉,我将原始的C结构作为注释包含在内非常有用。另外,我对
fcntl和
struct模块都还很陌生,所以我可能正在做一些单调的事情。无论如何,从命令行运行(具有root特权),它看起来像这样(为了保护隐私,我编辑了确切的序列号):
fmark@fmark-laptop:~/Desktop/hdserial$ sudo python hd.py "/dev/sda"Hard Disk Model: FUJITSU MHV2080BH PL Serial Number: NW--------
这里发生了什么?
为了能够了解这里发生的情况,您需要查看
#include<linux/hdreg.h>原始C程序中的。这包括导入
HDIO_GET_IDENTITY常量和
structhd_driveid。我已经将该结构作为注释复制到了上面的python源代码中,因此在此不再赘述。要找
HDIO_GET_IDENTITY出问题所在,请grep它的源代码(在Ubuntu上,位于
/usr/include/linux/hdreg.h。您应该找到类似以下内容:
#define HDIO_GET_IDENTITY 0x030d
因此,您发现这
HDIO_GET_IDENTITY只是一个常量,它告诉fcntl您对获取高清信息感兴趣。您将注意到,
0x030d在Python代码中,已将相同的值(以十六进制表示为整数)分配给变量。
视窗
我意识到现在您对Linux感兴趣,但是为了后代我将在这里保留。以下将获取Windows上的HDD序列号(您将需要安装wmi软件包):
import wmic = wmi.WMI()for item in c.Win32_PhysicalMedia(): print item



