概述

UID一般理解为User Identifier,在linux中就是用户的ID,表明是哪个用户运行了这个程序,GID则表明了这个用户属于哪个组。它们主要用于权限的管理。

而在Android中,部分权限的管理是依赖底层的linux的,所以了解Android的UID/GID十分必要。

网上有下面的一段话:
而在Android 中又有所不同,因为Android为单用户系统,这时UID 便被赋予了新的使命,android为每个应用几乎都分配了不同的UID,不像传统的linux,每个用户相同就为之分配相同的UID。(当然这也就表明了一个问题,android只能时单用户系统,在设计之初就被他们的工程师给阉割了多用户),使之成了数据共享的工具。

这段话有对有错,这篇文章将结合源码来分析UID与GID的分配,使我们有个最清晰的理解。源码版本为4.3。

首先需要明确的一点是,App的UID和GID是安装的时候确认的。而与安装相关的源码目录是:
frameworks\base\services\java\com\android\server\pm

PackageManagerService.java的scanPackageLI方法

private PackageParser.Package scanPackageLI(PackageParser.Package pkg,            int parseFlags, int scanMode, long currentTime) {    ............    //获取一系列属性    pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,                    destResourceFile, pkg.applicationInfo.nativeLibraryDir,                    pkg.applicationInfo.flags, true, false);    ............    //UID赋值    pkg.applicationInfo.uid = pkgSetting.appId;    ............

可以看到在getPackageLPw方法中,获取了UID,那我们打开这个函数看看:
Settings.java的getPackageLPw方法

    private PackageSetting getPackageLPw(String name, PackageSetting origPackage,            String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,            String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {            .........            s.userId = newUserIdLPw(s);            .........            }

可以看到UID是newUserIdLPw()指定的,那再打开这个看看:
依然是Settings文件

private int newUserIdLPw(Object obj) {        // Let's be stupidly inefficient for now...        final int N = mUserIds.size();        for (int i = 0; i < N; i++) {            if (mUserIds.get(i) == null) {                mUserIds.set(i, obj);                return Process.FIRST_APPLICATION_UID + i;            }        }        // None left?        if (N > (Process.LAST_APPLICATION_UID-Process.FIRST_APPLICATION_UID)) {            return -1;        }        mUserIds.add(obj);        return Process.FIRST_APPLICATION_UID + N;    }

至此,UID就算是分配下来了。
可以看到for循环和if (mUserIds.get(i) == null)语句限定了一个APP只有一个UID,而这个Process.FIRST_APPLICATION_UID是在frameworks/base/core/java/android/os/Process.java中定义的,其值为10000,这就是为什么Android的UID都是从10000开始的。

再回到PackageManagerService.javascanPackageLI代码:

//invoke installer to do the actual installation    //第二个uid就是GID    int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,            pkg.applicationInfo.uid);    if (ret < 0) {        // Error from installer        mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;        return null;    }    // Create data directories for all users    // 指定工作目录    sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);    if (dataPath.exists()) {        pkg.applicationInfo.dataDir = dataPath.getPath();    } else {        Slog.w(TAG, "Unable to create data directory: " + dataPath);        pkg.applicationInfo.dataDir = null;    }

可以看到此函数在运行时,将UID的值直接赋值给了GID,所以通常UID和GID也是相同的。从官方注释这可以看到Android有多用户。事实上,Android某些平板对多用户是支持的,我猜大家常见的是阉割版的吧,所以有误会。
打开UserManagerinstallPackageForAllUsers方法可以看到:

public void installPackageForAllUsers(String packageName, int uid) {    for (int userId : mUserIds) {        // Don't do it for the primary user, it will become recursive.        if (userId == 0)            continue;        mInstaller.createUserData(packageName, UserId.getUid(userId, uid),                userId);    }}

写了这么多,相信大家对UID/GID的分配有了更深刻的理解。欢迎一起讨论哈。

更多相关文章

  1. Android、iPhone和Java三个平台一致的加密方法
  2. 最新的数据显示,十分之四的 Android 用户还在吃煎饼
  3. Android中Bitmap类getPixel方法获取的像素值为负
  4. Android的View体系(三):View坐标以及方法说明
  5. Android控制闪光灯的方法(打开与关闭)
  6. android中setVisibility方法无效的可能原因与解决办法
  7. Android 文件保存getFilesDir()丶getCacheDir()、getExternalFil
  8. Android零基础入门第16节:Android用户界面开发概述

随机推荐

  1. android studio和 Eclipse中代码的注释,让
  2. android中获取屏幕相关信息
  3. 谈谈Android中WIFI 架构和控制流程
  4. Android中控制屏幕旋转的相关设置
  5. Android(安卓)读取本地图片文件和读取图
  6. Android(安卓).gitignore 忽略文件
  7. [转]Jollen 的 Android(安卓)教學,#8: 沒
  8. linux中如何使用javah命令生成jni头文件
  9. Android(安卓)Httpclient重定向问题
  10. 转载:Sensor传感器源码的阅读与应用开发简