姓名:郭佳朋 学号:14310116045
转载自:http://blog.csdn.net/kester_/article/details/71055901
【嵌牛导读】:NDK 开发时会涉及到 CPU 架构的适配,不同的机器上可能会有不同的 CPU 架构,也就是说,翻译到机器上使用的规则不一样,Android 上有7种 CPU 架构。
【嵌牛鼻子】:CPU架构
【嵌牛提问】: 了解CPU相关吗?
【嵌牛正文】:安卓CPU基础
凡是接触过安卓系统的朋友,对CPU一定不会陌生。
NDK 开发时会涉及到 CPU 架构的适配,不同的机器上可能会有不同的 CPU 架构,也就是说,翻译到机器上使用的规则不一样,Android 上有7种 CPU 架构。
1.armeabi
2.armeabi-v7a
3.arm64-v8a
4.x86
5.x86_64
6.MIPS
7.MIPS64
从厂家上来分是有三种,arm,x86,MIPS,arm 系列是绝大多数手机上使用的,x86 主要是运用在平板上,而 MIPS 基本上就没见过。
从类型来分,有32位和64位,名字中没有64的就是32位的了。
正常来说只使用 armeabi-v7a 就可以适配基本所有手机了,因为现在手机基本上都支持这种CPU架构,但是对于同时也能支持 arm64-v8a 的手机来说,性能上就不如使用对应 CPU 架构的快了,毕竟是32位和64位的区别,值得一提的是,arm 系列本身是没有64位,而是 intel 的x86_64先出现的,之后 arm 收购了 MIPS64,基于 MIPS64 改良出 arm64-v8a,所以也能理解为什么 MIPS 几乎没有,而另外,arm64-v8a 的 CPU 架构上也能运行 armeabi-v7a,为什么呢?不是64位上运行32位,而是 arm64-v8a 上本身搭载了 armeabi-v7a,所以在 arm64-v8a 上运行 armeabi-v7a 是使用32位处理的,没毛病。
如果应用中有不止一个 so,那就要注意了,如果这时你一个 so 同时支持了 armeabi-v7a 和arm64-v8a,而另一个 so 只支持了一种,那可能会运行有问题,这时要么另一个 so 也支持两种,要么把第一个 so 删掉对应目录,只支持相同的一种。
在提供支持多个 CPU 架构的 SDK 时,可以同时提供多个目录的 so,虽然此时 SDK 相对较大,但是被编译的 so 还是以你在 gradle 里设置的支持的 ndk 为准:
ndk {
abiFilters ‘armeabi-v7a’ // , ‘arm64-v8a’, ‘x86’, ‘x86_64’
}
查看设备支持的 CPU 架构或者 APP 提供的 CPU 架构可以使用 Native Libs Monitor。
1 查看手机CPU信息
cmd——adb shell——cd /proc------cat cpuinfo
2 获取cpu的是arm指令集,armv7指令集、还是neon指令集
[java] view plain copy
/*** * [获取cpu类型和架构]* * @return
* 三个参数类型的数组,第一个参数标识是不是ARM架构,第二个参数标识是V6还是V7架构,第三个参数标识是不是neon指令集
*/
public static Object[] getCpuArchitecture() {
if ((Integer) mArmArchitecture[1] != -1) {
return mArmArchitecture;
}
try {
InputStream is = new FileInputStream("/proc/cpuinfo");
InputStreamReader ir = new InputStreamReader(is);
BufferedReader br = new BufferedReader(ir);
try {
String nameProcessor = "Processor";
String nameFeatures = "Features";
String nameModel = "model name";
String nameCpuFamily = "cpu family";
while (true) {
String line = br.readLine();
String[] pair = null;
if (line == null) {
break;
}
pair = line.split(":");
if (pair.length != 2)
continue;
String key = pair[0].trim();
String val = pair[1].trim();
if (key.compareTo(nameProcessor) == 0) {
String n = "";
for (int i = val.indexOf("ARMv") + 4; i < val.length(); i++) {
String temp = val.charAt(i) + "";
if (temp.matches("\\d")) {
n += temp;
} else {
break;
}
}
mArmArchitecture[0] = "ARM";
mArmArchitecture[1] = Integer.parseInt(n);
continue;
}
if (key.compareToIgnoreCase(nameFeatures) == 0) {
if (val.contains("neon")) {
mArmArchitecture[2] = "neon";
}
continue;
}
if (key.compareToIgnoreCase(nameModel) == 0) {
if (val.contains("Intel")) {
mArmArchitecture[0] = "INTEL";
mArmArchitecture[2] = "atom";
}
continue;
}
if (key.compareToIgnoreCase(nameCpuFamily) == 0) {
mArmArchitecture[1] = Integer.parseInt(val);
continue;
}
}
} finally {
br.close();
ir.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return mArmArchitecture;
}
调用的该函数的示例方法
[java] view plain copy
/*
* 获取FFpeg解码库的名称(如果是插件,会涉及到一个向下兼容的问题,例如:如果当前cpu是V7neo,而又没有neon的解码库,必须要做向下兼容出来
* ,如果有V7的库就加载V7的库,有V6的库就加载V6的)
*/
public static String getFFmpegLibName(Context context) {
if (LIB_FFMPEG_NAME != null) {
return LIB_FFMPEG_NAME;
}
Object[] arch = getCpuArchitecture();
String libDir = getNativeLibraryDir(context);
String libSysDir = "/system/lib";
if ("ARM".equals(arch[0])) {
try {
String ffmpeg = String.format("ffmpeg-%d%s", (Integer) arch[1], (String) arch[2]);
if (isFileExist(libDir + "/lib" + ffmpeg + ".so") || isFileExist(libSysDir + "/lib" + ffmpeg + ".so")) {
return ffmpeg;
} else {
boolean isV7NeonCpu = "neon".equals(arch[2]);
boolean isV7 = ((Integer) arch[1]) == 7 && "".equals(arch[2]);
boolean isV6 = ((Integer) arch[1]) == 6;
if (isV7NeonCpu) {
if (isFileExist(libDir + "/libffmpeg-7neon.so")
|| isFileExist(libSysDir + "/libffmpeg-7neon.so")) {
LIB_FFMPEG_NAME = "ffmpeg-7neon";
return "ffmpeg-7neon";
} else if (isFileExist(libDir + "/libffmpeg-7.so")
|| isFileExist(libSysDir + "/libffmpeg-7.so")) {
LIB_FFMPEG_NAME = "ffmpeg-7";
return "ffmpeg-7";
} else if (isFileExist(libDir + "/libffmpeg-6.so")
|| isFileExist(libSysDir + "/libffmpeg-6.so")) {
LIB_FFMPEG_NAME = "ffmpeg-6";
return "ffmpeg-6";
}
} else if (isV7) {
if (isFileExist(libDir + "/libffmpeg-7.so") || isFileExist(libSysDir + "/libffmpeg-7.so")) {
LIB_FFMPEG_NAME = "ffmpeg-7";
return "ffmpeg-7";
} else if (isFileExist(libDir + "/libffmpeg-6.so")
|| isFileExist(libSysDir + "/libffmpeg-6.so")) {
LIB_FFMPEG_NAME = "ffmpeg-6";
return "ffmpeg-6";
}
} else if (isV6) {
if (isFileExist(libDir + "/libffmpeg-6.so") || isFileExist(libSysDir + "/libffmpeg-6.so")) {
LIB_FFMPEG_NAME = "ffmpeg-6";
return "ffmpeg-6";
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else if ("INTEL".equals(arch[0])) {
if (isFileExist(libDir + "/libffmpeg-x86atom.so") || isFileExist(libSysDir + "/libffmpeg-x86atom.so")) {
LIB_FFMPEG_NAME = "ffmpeg-x86atom";
return "ffmpeg-x86atom";
}
}
LIB_FFMPEG_NAME = null;
return null;
}