Je vais essayer de résumer mon expérience concernant le stockage numéro de série du disque de récupération sur linux.
Je suppose que vous voulez le numéro de série de la périphérique de stockage identité (conformément à la spécification SCSI) pas le numéro de série de la périphérique USB (conformément à la spécification USB sous Descripteur De Périphérique ), ce sont deux entités différentes.
AVIS!
La plupart des appareils ont tendance à mettre en œuvre un numéro de série dans le port USB-Contrôleur et laisser le numéro de série de l'interne SCSI disque non mises en œuvre.
Donc si vous voulez vous identifier de manière unique un dispositif USB, le meilleur moyen est de créer une chaîne de caractères à partir de la Descripteur De Périphérique (spécification USB) comme Id-ProductId-HardwareRevision-SerialNumber
Dans la suite, je décrirai comment récupérer la SN de l'unité de stockage, comme l'a demandé.
Disques tombent en 2 catégories (en fait plus, mais simplifions): ATA-like (hda, hdb ...) et SCSI (sda, sdb,...).
Les lecteurs USB de l'automne dans la deuxième catégorie, ils sont appelés SCSI disques connectés.
Dans les deux situations ioctl appels peut être utilisé pour récupérer les informations nécessaires (dans notre cas, le numéro de série).
Pour périphériques SCSI (et ceux-ci comprennent les lecteurs USB) Linux pilote générique et c'est l'API est documenté à tldp.
Le numéro de série sur les périphériques SCSI est disponible à l'intérieur de la Les Données Vitales Du Produit (court: VPD) et est récupérable par l'aide de la D'interrogation SCSI Commande.
Un commad ligne de l'utilitaire sous linux qui permet de récupérer cette VPD est sdparm:
> yum install sdparm
> sdparm --quiet --page=sn /dev/sda
Unit serial number VPD page:3BT1ZQGR000081240XP7
Noter que tous les appareils ont le numéro de série, le marché est inondé avec piou knockoffs, et certains disques flash usb de retour étrange publications en série (par exemple, pour ma sandisk cruzer retourne juste la lettre "u"). Pour surmonter ce que certaines personnes choisissent pour créer un identifiant unique par le mélange de différentes chaînes de VPD comme ID de Produit, l'ID du Fournisseur et le Numéro de Série.
Code en c:
#include<stdlib.h>#include<stdio.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<errno.h>#include<scsi/scsi.h>#include<scsi/sg.h>#include<sys/ioctl.h>int scsi_get_serial(int fd,void*buf,size_t buf_len){//we shall retrieve page 0x80 as per http://en.wikipedia.org/wiki/SCSI_Inquiry_Commandunsignedchar inq_cmd[]={INQUIRY,1,0x80,0, buf_len,0};unsignedchar sense[32];struct sg_io_hdr io_hdr;int result;
memset(&io_hdr,0,sizeof(io_hdr));
io_hdr.interface_id ='S';
io_hdr.cmdp = inq_cmd;
io_hdr.cmd_len =sizeof(inq_cmd);
io_hdr.dxferp = buf;
io_hdr.dxfer_len = buf_len;
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.sbp = sense;
io_hdr.mx_sb_len =sizeof(sense);
io_hdr.timeout =5000;
result = ioctl(fd, SG_IO,&io_hdr);if(result <0)return result;if((io_hdr.info & SG_INFO_OK_MASK)!= SG_INFO_OK)return1;return0;}int main(int argc,char** argv){char*dev ="/dev/sda";char scsi_serial[255];int rc;int fd;
fd = open(dev, O_RDONLY | O_NONBLOCK);if(fd <0){
perror(dev);}
memset(scsi_serial,0,sizeof(scsi_serial));
rc = scsi_get_serial(fd, scsi_serial,255);//scsi_serial[3] is the length of the serial number//scsi_serial[4] is serial number (raw, NOT null terminated)if(rc <0){
printf("FAIL, rc=%d, errno=%d\n", rc, errno);}elseif(rc ==1){
printf("FAIL, rc=%d, drive doesn't report serial number\n", rc);}else{if(!scsi_serial[3]){
printf("Failed to retrieve serial for %s\n", dev);return-1;}
printf("Serial Number: %.*s\n",(size_t) scsi_serial[3],(char*)& scsi_serial[4]);}
close(fd);return(EXIT_SUCCESS);}
Pour le bien du souci d'exhaustivité, je vais également fournir le code pour récupérer le numéro de série pour périphériques ATA (hda, hdb ...). Cela ne fonctionnera PAS pour les périphériques USB.
#include<stdlib.h>#include<stdio.h>#include<sys/ioctl.h>#include<linux/hdreg.h>#include<fcntl.h>#include<errno.h>#include<string.h>#include<cctype>#include<unistd.h>int main(){struct hd_driveid *id;char*dev ="/dev/hda";int fd;
fd = open(dev, O_RDONLY|O_NONBLOCK);if(fd <0){
perror("cannot open");}if(ioctl(fd, HDIO_GET_IDENTITY, id)<0){
close(fd);
perror("ioctl error");}else{//if we want to retrieve only for removable drives use this branchingif((id->config &(1<<7))||(id->command_set_1 &4)){
close(fd);
printf("Serial Number: %s\n", id->serial_no);}else{
perror("support not removable");}
close(fd);}}
Excellente description et j'aime bien la séparation entre l'ATA et SCSI. excellent travail, le seul manquant chose est de savoir comment déterminer si un disque est en ide ou scsi? c'est super, mais il y a un bug, la vérification de la ioctl le succès n'est pas suffisant pour vérifier que vous avez une série valide... vous devez aussi vérifier if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) return -1 Mise à jour de réponse avec le correctif ci-dessus.
Et ce bout de code va obtenir la clé USB numéro de série... il n'est pas impressionnant techniquement que clyfe, mais il semble faire le tour à chaque fois.
#include<unistd.h>#include<string.h>#include<stdio.h>int main(int arg,char**argv){ssize_t len;char buf[256],*p;char buf2[256];int i;
len = readlink("/sys/block/sdb", buf,256);
buf[len]=0;//printf("%s\n", buf);
sprintf(buf2,"%s/%s","/sys/block/", buf);for(i=0; i<6; i++){
p = strrchr(buf2,'/');*p =0;}//printf("%s\n", buf2);
strcat(buf2,"/serial");//printf("opening %s\n", buf2);int f = open(buf2,0);
len = read(f, buf,256);if(len <=0){
perror("read()");}
buf[len]=0;
printf("serial: %s\n", buf);}
Je l'ai essayé et elle a produit des résultats erronés.
Le meilleur moyen est sans doute de faire ce que les outils de ligne de commande (encore une fois, probablement) à faire: examiner les fichiers en /proc ou /sys, mais à partir de code C++.
Je vais essayer de résumer mon expérience concernant le stockage numéro de série du disque de récupération sur linux.
Je suppose que vous voulez le numéro de série de la périphérique de stockage identité (conformément à la spécification SCSI) pas le numéro de série de la périphérique USB (conformément à la spécification USB sous Descripteur De Périphérique ), ce sont deux entités différentes.
Disques tombent en 2 catégories (en fait plus, mais simplifions): ATA-like (hda, hdb ...) et SCSI (sda, sdb,...).
Les lecteurs USB de l'automne dans la deuxième catégorie, ils sont appelés SCSI disques connectés.
Dans les deux situations ioctl appels peut être utilisé pour récupérer les informations nécessaires (dans notre cas, le numéro de série).
Pour périphériques SCSI (et ceux-ci comprennent les lecteurs USB) Linux pilote générique et c'est l'API est documenté à tldp.
Le numéro de série sur les périphériques SCSI est disponible à l'intérieur de la Les Données Vitales Du Produit (court: VPD) et est récupérable par l'aide de la D'interrogation SCSI Commande.
Un commad ligne de l'utilitaire sous linux qui permet de récupérer cette VPD est sdparm:
Noter que tous les appareils ont le numéro de série, le marché est inondé avec piou knockoffs, et certains disques flash usb de retour étrange publications en série (par exemple, pour ma sandisk cruzer retourne juste la lettre "u"). Pour surmonter ce que certaines personnes choisissent pour créer un identifiant unique par le mélange de différentes chaînes de VPD comme ID de Produit, l'ID du Fournisseur et le Numéro de Série.
Code en c:
Pour le bien du souci d'exhaustivité, je vais également fournir le code pour récupérer le numéro de série pour périphériques ATA (hda, hdb ...). Cela ne fonctionnera PAS pour les périphériques USB.
excellent travail, le seul manquant chose est de savoir comment déterminer si un disque est en ide ou scsi?
c'est super, mais il y a un bug, la vérification de la ioctl le succès n'est pas suffisant pour vérifier que vous avez une série valide... vous devez aussi vérifier
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) return -1
Mise à jour de réponse avec le correctif ci-dessus.
OriginalL'auteur
Et ce bout de code va obtenir la clé USB numéro de série... il n'est pas impressionnant techniquement que clyfe, mais il semble faire le tour à chaque fois.
OriginalL'auteur Orwellophile
J'ai trouvé quelque chose qui pourrait être intéressant aussi pour vous:
"Comment détecter si /dev/* est un périphérique USB?"
OriginalL'auteur Programming
Le meilleur moyen est sans doute de faire ce que les outils de ligne de commande (encore une fois, probablement) à faire: examiner les fichiers en
/proc
ou/sys
, mais à partir de code C++.OriginalL'auteur unwind