linux 获取硬盘序列号
找了好久,找到下面代码:
// a.cpp
//在Linux下获取硬盘物理系列号的程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* ioperm() */
#include <sys/io.h> /* outb(), inb() */
//#include <asm/io.h> //推荐不要使用这个asm/io.h
#define _DEBUG_ 1
/* get serial number */
int gethddsn(char *ide)
{
unsigned int ide_info[257];
unsigned int info_off;
unsigned long loop2 = 0;
int loop, loop1 = 0;
if( ioperm(0x1F6, 1, 1) ) {
perror("ioperm");
//exit(-1);
return 0;
}
outb(0xA0, 0x1F6);
if( ioperm(0x1F7, 1, 1) ) {
perror("ioperm");
//exit(-1);
return 0;
}
outb(0xEC, 0x1F7);
do {
if( ioperm(0x1F7, 1, 1) ) {
perror("ioperm");
//exit(-1);
return 0;
}
}while( inb(0x1F7) != 0x58 && loop2++ < 0xFFFF );
for( info_off = 0; info_off != 256; info_off++) {
if( ioperm(0x1F0, 2, 1) ) {
perror("ioperm");
//exit(-1);
return 0;
}
ide_info[info_off] = inw(0x1F0);
}
for(loop = 10, loop1 = 0; loop <= 19; loop++)
{
ide[loop1++] = (char)(ide_info[loop]/256);
ide[loop1++] = (char)(ide_info[loop]%256);
}
ide[loop1] = 0x00; //字符串结束
if( loop1 > 20 )
{
printf("*hdsn too len:[%d] error!*\n", loop1);
return 0;
}
return 1;
}
#if _DEBUG_
int main(void) //print hard disk number
{
static char serial[21];
if (gethddsn(serial))
printf("IDE hard disk s/n: %s\n", serial);
for (int i = 0; i < 20; ++i)
printf("%d ", serial[i]);
printf("\n");
return 0;
}
#endif
// b.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/hdreg.h>
int main(int argc,char *argv[])
{
static int open_flags = O_RDONLY|O_NONBLOCK;
static int errno = 1;
static struct hd_driveid id;
int fd;
const char *devname = "/dev/hda"; // 改成 "/dev/sda"时ioctl会出错, errno == 22
fd = open(devname,open_flags);
if(fd < 0)
{
perror(devname);
exit(errno);
}
ioctl(fd,HDIO_GET_IDENTITY,&id);
printf("Model = %40s,FwRev = %8s,SerialNo = %20s\n",id.model,id.fw_rev,id.serial_no);
close(fd);
return 0;
}
// c.cpp
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
#define SCSI_TIMEOUT 5000 /* ms */
static const char * device = "/dev/sda";
int scsi_io(int fd, unsigned char *cdb, unsigned char cdb_size, int xfer_dir,
unsigned char *data, unsigned int *data_size,
unsigned char *sense, unsigned int *sense_len)
{
sg_io_hdr_t io_hdr;
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
/* CDB */
io_hdr.cmdp = cdb;
io_hdr.cmd_len = cdb_size;
/* Where to store the sense_data, if there was an error */
io_hdr.sbp = sense;
io_hdr.mx_sb_len = *sense_len;
*sense_len=0;
/* Transfer direction, either in or out. Linux does not yet
support bidirectional SCSI transfers ?
*/
io_hdr.dxfer_direction = xfer_dir;
/* Where to store the DATA IN/OUT from the device and how big the
buffer is
*/
io_hdr.dxferp = data;
io_hdr.dxfer_len = *data_size;
/* SCSI timeout in ms */
io_hdr.timeout = SCSI_TIMEOUT;
if(ioctl(fd, SG_IO, &io_hdr) < 0){
perror("SG_IO ioctl failed");
return -1;
}
/* now for the error processing */
if((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK){
if(io_hdr.sb_len_wr > 0){
*sense_len=io_hdr.sb_len_wr;
return 0;
}
}
if(io_hdr.masked_status){
printf("status=0x%x\n", io_hdr.status);
printf("masked_status=0x%x\n", io_hdr.masked_status);
return -2;
}
if(io_hdr.host_status){
printf("host_status=0x%x\n", io_hdr.host_status);
return -3;
}
if(io_hdr.driver_status){
printf("driver_status=0x%x\n", io_hdr.driver_status);
return -4;
}
return 0;
}
int scsi_inquiry_unit_serial_number(int fd)
{
unsigned char cdb[]={0x12,0x01,0x80,0,0,0};
unsigned int data_size=0x00ff;
unsigned char data[data_size];
unsigned int sense_len=32;
unsigned char sense[sense_len];
int res, pl, i;
cdb[3]=(data_size>>8)&0xff;
cdb[4]=data_size&0xff;
printf("INQUIRY Unit Serial Number:\n");
res=scsi_io(fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, data, &data_size, sense, &sense_len);
if(res){
printf("SCSI_IO failed\n");
return -1;
}
if(0==sense_len){ // 注意:原代码是 if (sense_len),我改了下
return -1;
}
/* Page Length */
pl=data[3];
/* Unit Serial Number */
printf("Unit Serial Number:");
for(i=4;i<(pl+4);i++)printf("%c",data[i]&0xff);printf("\n");
return 0;
}
int open_scsi_device(const char *dev)
{
int fd, vers;
if((fd=open(dev, O_RDWR))<0){
printf("ERROR could not open device %s\n", dev);
return -1;
}
if ((ioctl(fd, SG_GET_VERSION_NUM, &vers) < 0) || (vers < 30000)) {
printf("/dev is not an sg device, or old sg driver\n");
close(fd);
return -1;
}
return fd;
}
int main(int argc, const char *argv[])
{
int fd;
fd=open_scsi_device(device);
if(fd<0){
printf("Could not open SCSI device %s\n",device);
_exit(10);
}
scsi_inquiry_unit_serial_number(fd);
return 0;
}