linux系统java通过jni方式获取硬盘序列号

33 篇文章 0 订阅
12 篇文章 0 订阅

最近项目需要从linux系统获取硬盘序列号,特把成果分享一下。至于什么是jni这里就不介绍了需要的童鞋可以google百度一把。这里包括两部分代码,一部分是java的代码供上层调用,一部分是c代码编译成so动态链接库供java代码,下面从c代码开始。

一 代码

c代码

getLocalSysInfo.cpp

  1. #include "getLocalSysInfo.h"    
  2. #include <stdio.h>    
  3. #include <sys/ioctl.h>  
  4. #include <linux/hdreg.h>  
  5. #include <sys/fcntl.h>  
  6.   
  7. JNIEXPORT void JNICALL Java_getSysInfo_getLocalHdSn(JNIEnv * env, jobject arg)  
  8. {     
  9.     struct hd_driveid id;  
  10.       
  11.      /*打开设备文件*/  
  12.     int fd = open("/dev/sda", O_RDONLY);  
  13.     if (fd < 0)   
  14.     {  
  15.         printf("oh can not open sda/n");    
  16.         return ;   
  17.     }  
  18.       
  19.     /*读取设备信息*/  
  20.     if(!ioctl(fd, HDIO_GET_IDENTITY, &id))  
  21.     {  
  22.         /*打印磁盘序列号信息*/  
  23.         printf("Serial Number=%s\n",id.serial_no);  
  24.     }  
  25.         
  26.     return;  
  27. }    

头文件

getLocalSysInfo.h

这个头文件是在执行

javac getSysInfo.java

后生成getSysInfo.class文件后再执行

javah -classpath . -jni getSysInfo

后生成getSysInfo.h头文件,我手痒生成后把它改为getLocalSysInfo.h的(^0^)。

  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class HelloWorld */  
  4.   
  5. #ifndef _Included_HelloWorld  
  6. #define _Included_HelloWorld  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /* 
  11.  * Class:     getSysInfo 
  12.  * Method:    getLocalHdSn 
  13.  * Signature: ()V 
  14.  */  
  15. JNIEXPORT void JNICALL Java_getSysInfo_getLocalHdSn  
  16.   (JNIEnv *, jobject);  
  17.   
  18. #ifdef __cplusplus  
  19. }  
  20. #endif  
  21. #endif  

在c代码中打开硬盘设备文件/dev/sda( 注意每个系统可能不一样请根据自己的系统修改路径),然后调用ioctrl读取设备信息获取硬盘序列号并打印出来。接下来就是编译了我写了个小小的makefile文件:
[plain] view plain copy
  1. CC=g++  
  2. JDK_INCLUDE=/usr/lib/jvm/jdk1.7.0/include  
  3. INCLUDE=-I $(JDK_INCLUDE) -I $(JDK_INCLUDE)/linux  
  4. FLAG=-fPIC -shared  
  5. OBJ=libgetLocalSysInfo.so  
  6. all:getLocalSysInfo.cpp getLocalSysInfo.h  
  7.     $(CC) $(FLAG) -cpp getLocalSysInfo.cpp -o $(OBJ)  $(INCLUDE)  
  8. clean:  
  9.     rm -rf *.o *.so getLocalSysInfo  

编译器我用的是g++,我jdk的路径是/usr/lib/jvm/jdk1.7.0/include,这个必须包含否则会提示找不到jni.h这个文件。编译标致选择-fPIC和-shared这两个的含义如下:

-fPIC

    生成的目标文件可在不固定内存位置执行,就是可动态链接的意思了。

-shared

   生成的目标文件可以被共享即可以多进程调用,如不加该选项会提示要你添加main函数(呵呵你懂的)。

java代码

getSysInfo.java

  1. public class getSysInfo {  
  2.     /*java本地方法申明*/   
  3.     public native void getLocalHdSn( );   
  4.         
  5.     public getSysInfo() {    
  6.     }    
  7.     /*装入动态链接库getHdSn.so*/  
  8.     static {    
  9.             System.loadLibrary("getLocalSysInfo");    
  10.     }    
  11. }  

  1. System.loadLibrary("getLocalSysInfo");    

加载动态链接库libgetLocalSysInfo.so。编译java命令:

getHdSn.java

  1. public class getHdSn{  
  2.     /**  
  3.      * @param args  
  4.      */    
  5.     public static void main(String[] args) {    
  6.         getSysInfo sysInfo = new getSysInfo();    
  7.         sysInfo.getLocalHdSn( );    
  8.     }    
  9. }     

调用或者硬盘序列号方法。


编译和运行

编译和运行命令如下:



方法二

想通过java写一个读取安装在linux系统上的硬盘的序列号的util类。

我写的代码是:


Java代码  

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * Description: 获取各个操作系统下硬盘序列号
 *
 *
 * @version 1.0 Aug 25, 2008 12:12:36 PM
 *       
 */

public class HDUtil {

    /**
     * Return Opertaion System Name;
     *
     * @return os name.
     */
    public static String getOsName() {
        String os = "";
        os = System.getProperty("os.name");
        return os;
    }

    /**
     * Returns the HD SerialNo. of the computer.
     *
     * @return the HD SerialNo.
     */
    public static String getHDSerialNo() {
        String sn = "";
        String os = getOsName();
        if (os.startsWith("Linux")) {
            if (isSCSIorIDEHD() == "scsi") {
                // 注意如果是ubuntu等系统用户,本身没有root权限,请先:chmod 777 /dev/sda
                String command = "hdparm -i /dev/sda";
                Process p;
                try {
                    p = Runtime.getRuntime().exec(command);
                    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                    String line;
                    while ((line = br.readLine()) != null) {
                        if (line.contains("SerialNo")) {
                            int index = line.indexOf("SerialNo") + "SerialNo".length() + 1;
                            sn = line.substring(index);
                            break;
                        }
                    }
                    br.close();
                } catch (IOException e) {
                }
            } else if (isSCSIorIDEHD() == "ide") {
                // 注意如果是ubuntu等系统用户,本身没有root权限,请先:chmod 777 /dev/sda
                String command = "hdparm -i /dev/hda";
                Process p;
                try {
                    p = Runtime.getRuntime().exec(command);
                    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                    String line;
                    while ((line = br.readLine()) != null) {
                        if (line.contains("SerialNo")) {
                            int index = line.indexOf("SerialNo") + "SerialNo".length() + 1;
                            sn = line.substring(index);
                            break;
                        }
                    }
                    br.close();
                } catch (IOException e) {
                }
            } else {
                sn = "unknown";
            }

        }
        sn = sn.trim();
        return sn;
    }

    public static String isSCSIorIDEHD() {
        String os = getOsName();
        if (os.startsWith("Linux")) {
            // ubuntu系统下确定有root权限
            String command = "fdisk -l";
            Process p;
            try {
                p = Runtime.getRuntime().exec(command);
                BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while ((line = br.readLine()) != null) {
                    if (line.contains("sd")) {
                        return "scsi";
                    }
                    if (line.contains("hd")) {
                        return "ide";
                    }
                }
                br.close();
            } catch (IOException e) {
            }
        }
        return "unkonwn"; // 未知类型
    }

    /**
     * Main Class.
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Operation System=" + getOsName());
        System.out.println("HD SerialNo=" + getHDSerialNo());
    }
}

现在在本地机器ubuntu上可以运行,但是放到其他比如Centos或suse上获取不了。
根本原因是通过java调用的一个SHELL>"hdparm -i /dev/sda1" ,这个命令对于SCSI 的硬盘好像支持不了。


有谁做过的给个建议阿。好多人说用c写个底层的,然后通过jni调用。那样不是系统得有c的运行环境吗?
我觉得一个util类有这个必要吗?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值