浅谈Android PID与UID原理

作为一位在Android系统里摸爬滚打多年的"老兵",我来给你讲讲PID和UID这对"好基友"的故事。咱们不用那些晦涩的术语,就用一个有趣的比喻把它们讲明白。

一场精彩的"公司派对"比喻

想象一下,Android系统就是一个超级大的公司派对

  • 公司大楼 = 你的Android设备
  • 派对主办方 = Android系统
  • 各个部门 = 不同的App
  • 部门员工 = App中的各个进程
  • 工牌权限 = UID
  • 临时工作证 = PID

主要角色介绍

UID(用户ID) - 你的"部门工牌"

  • 每个部门(App)有唯一的工牌颜色和权限
  • 安装App时,系统就给它发了一个永久的"工牌"
  • 决定了能访问哪些公司资源(比如财务部能进金库,市场部能用宣传材料)

PID(进程ID) - "临时工作证"

  • 每次部门开展新项目,就派几个员工(进程)去干活
  • 每个员工都会拿到一个临时工作证号码
  • 项目结束(进程关闭),工作证就收回,下次可能发给别人

代码里的"工牌"和"工作证"

来看看在实际代码中怎么找到这些信息:

java 复制代码
// 获取当前进程的PID和UID
public class ProcessInfoDemo {
    
    public void printProcessInfo() {
        // 获取PID - 临时工作证号码
        int pid = android.os.Process.myPid();
        System.out.println("我的临时工作证号(PID): " + pid);
        
        // 获取UID - 部门工牌
        int uid = android.os.Process.myUid();
        System.out.println("我的部门工牌(UID): " + uid);
        
        // 获取进程名称
        String processName = getProcessName();
        System.out.println("我正在做的项目: " + processName);
    }
    
    private String getProcessName() {
        try {
            File file = new File("/proc/self/cmdline");
            BufferedReader reader = new BufferedReader(new FileReader(file));
            return reader.readLine().trim();
        } catch (Exception e) {
            return "未知项目";
        }
    }
}

现实中的有趣场景

场景1:微信的"多部门协作"

java 复制代码
// 微信可能同时运行多个进程
public class WeChatExample {
    public void showMultiProcess() {
        // 主进程 - 聊天界面
        int mainPid = 1001;  // 每次启动可能不同
        int weChatUid = 10123; // 安装时就固定了
        
        // 后台进程 - 接收消息
        int backgroundPid = 1002; // 不同的PID
        int sameWeChatUid = 10123; // 但UID相同!
        
        System.out.println("同一个微信,不同的工作进程:" + 
            (mainPid != backgroundPid) + // true - PID不同
            ", 但工牌相同:" + 
            (weChatUid == sameWeChatUid)); // true - UID相同
    }
}

故事时间:微信就像一个大部门,有前台接待(主进程)负责跟你聊天,还有后勤人员(后台进程)负责收快递(消息)。他们干不同的活(PID不同),但都戴着微信的工牌(相同UID),所以都能进出微信的办公室。

场景2:权限检查 - "保安查岗"

java 复制代码
// 系统如何检查权限
public class SecurityCheck {
    
    // 这是系统内部的权限检查机制
    public boolean checkPermission(int callerPid, int callerUid, String permission) {
        // 步骤1:根据UID查这个部门有哪些权限
        List<String> grantedPermissions = getPermissionsForUid(callerUid);
        
        // 步骤2:检查是否有所需权限
        if (grantedPermissions.contains(permission)) {
            System.out.println("工牌 " + callerUid + " 有权限: " + permission);
            return true;
        } else {
            System.out.println("工牌 " + callerUid + " 没权限: " + permission);
            return false;
        }
        // 注意:这里主要看UID,PID只是辅助标识!
    }
    
    // 应用间通信时的权限检查
    public void binderCallExample() {
        // 当App A调用App B的服务时
        int callerPid = android.os.Process.myPid();    // A的PID
        int callerUid = android.os.Process.myUid();   // A的UID
        
        // 系统会检查:A的UID是否有权限调用B的服务
        // 而不是看A的PID!
    }
}

系统层面的深度原理

UID分配的秘密

java 复制代码
// 系统在安装App时的UID分配
public class PackageManagerService {
    
    private static final int FIRST_APPLICATION_UID = 10000;
    private static int nextUid = FIRST_APPLICATION_UID;
    
    public int assignUidForNewApp() {
        // 每个新App获得一个唯一的UID
        int newUid = nextUid++;
        System.out.println("为新App分配工牌: " + newUid);
        return newUid;
    }
    
    // 共享UID的情况 - 比如同一公司的多个App
    public void assignSharedUid(String sharedUserId) {
        // 如果指定了sharedUserId,多个App会共享同一个UID
        // 这样它们就能互相访问数据了
    }
}

PID的生命周期管理

java 复制代码
// 进程管理服务
public class ActivityManagerService {
    
    private int nextPid = 1000;
    
    public int startProcess(String processName, int uid) {
        // 为新进程分配PID
        int newPid = nextPid++;
        
        // 创建进程结构
        ProcessRecord app = new ProcessRecord(uid, newPid, processName);
        
        System.out.println("创建新进程: " + processName + 
                         ", PID=" + newPid + ", UID=" + uid);
        
        // 实际fork进程的底层调用
        forkNewProcess(newPid, uid);
        
        return newPid;
    }
    
    public void killProcess(int pid) {
        // 结束进程,PID可以被重用
        System.out.println("回收工作证: " + pid);
        // 但UID保持不变,等待下次使用
    }
}

完整的调用时序图

下面用mermaid时序图展示整个调用过程:

实际开发中的应用

判断是否在同一进程

java 复制代码
public class ProcessUtils {
    
    public static boolean isInSameProcess(Context context1, Context context2) {
        // 判断两个组件是否在同一个进程
        int pid1 = getPidForContext(context1);
        int pid2 = getPidForContext(context2);
        return pid1 == pid2;
    }
    
    public static boolean isSameApp(int uid1, int uid2) {
        // 判断是否同一个应用
        return uid1 == uid2;
    }
}

多进程应用架构

java 复制代码
// 在AndroidManifest.xml中配置多进程
<application>
    <activity android:name=".MainActivity"
              android:process=":main"/>
              
    <service android:name=".BackgroundService"
             android:process=":background"/>
             
    <provider android:name=".DataProvider"
              android:process=":data"/>
</application>

// 运行时检查
public class MultiProcessApp {
    public void checkCurrentProcess() {
        String processName = getProcessName();
        int pid = android.os.Process.myPid();
        int uid = android.os.Process.myUid();
        
        System.out.println("当前进程: " + processName + 
                         ", PID: " + pid + 
                         ", 但UID始终是: " + uid);
    }
}

总结一下

PID(进程ID)

  • 就像员工的临时工作证
  • 每次启动进程都可能不同
  • 进程结束就被回收
  • 用于系统管理进程生命周期

UID(用户ID)

  • 就像部门的永久工牌
  • 安装App时就确定,一般不会变
  • 决定了应用的权限和资源访问
  • 用于权限检查和进程间通信

它们的关系

  • 一个UID(部门)可以有多个PID(员工)
  • 系统通过UID判断"你是谁",通过PID判断"你现在在做什么"
  • 权限检查主要看UID,进程管理主要看PID

记住这个比喻:UID是你的公司工牌,PID是你今天在哪个工位上班。工牌决定了你能进哪些办公室,工位只是你今天坐的地方,明天可能就换了!

相关推荐
TimeFine6 小时前
Android AWS KVS WebRTC 通话声道切换到媒体音乐声道
android
用户2018792831677 小时前
Android文件下载完整性保证:快递员小明的故事
android
用户2018792831678 小时前
自定义 View 的 “快递失踪案”:为啥 invalidate () 喊不动 onDraw ()?
android
没有了遇见8 小时前
Android 稀奇古怪系列:新版本签名问题-Algorithm HmacPBESHA256 not available
android
小妖怪的夏天8 小时前
react native android设置邮箱,进行邮件发送
android·spring boot·react native
东风西巷8 小时前
Avast Cleanup安卓版(手机清理优化) 修改版
android·学习·智能手机·软件需求
用户2018792831678 小时前
Android断点续传原理:小明的"读书笔记"故事
android
用户2018792831679 小时前
ART 内存模型:用 “手机 APP 小镇” 讲明白底层原理
android
liulangrenaaa9 小时前
Android NDK 命令规范
android