adb进入手机,执行ps,如下图所示,在USER一栏除了有system,root以外,还有类似media_rw,u0_a78这种名字,那么这些字符串到底代表了什么?

android用户和AID_Android教程

linux用户和组

android是在linux基础上构建的,而用户和组是linux中很重要的概念。linux系统允许多用户同时操作,用户和组主要是为了多用户同时工作来服务的。同时,linux还定义了对文件和目录进行操作的权限,操作的动作包括读、写、执行。

  • 1.读权限:
    对文件来说,顾名思义,允许读取文件的内容;对目录,读权限允许列出目录中的内容。
  • 2.写权限:
    对文件来说,就是可写入内容;对目录,允许修改目录的内容,比如删除、添加文件。
  • 3.可执行:
    对文件来说,就是可执行或者脚本;对目录有执行权限,可以允许你cd到该目录中,记得以前看过内核文件系统的路径解析代码,如果目录没可执行权限,则返回错误。

linux对某一文件或者目录的权限的管理分为:文件拥有者,文件所属于的组,其他用户。例如:

drwxr-xr-x 2 user user 4096 Jan  9 10:11 documents

文件documents,拥有者user的权限为读写可执行(rwx),组user的权限为读可执行(r-x),其他用户的权限为读可执行(r-x)。

注:linux一个用户可以属于多个组;而某个文件一般只属于一个组。但是如果支持posix acl扩展,利用setfacl getfacl等命令也能使得某个文件属于多个组。在我理解,acl扩展主要是为了弥补linux拥有者:组:其他用户这种模式的“粗犷”。
举个例子,如果用户user2也想去写documents这个文件,我们可以想到几种方法来实现:
1.将user2加入到组user中
2.给documents的其他用户增加写权限
从上面两个解决方法,都能感觉有些太过粗糙,对other定义的太过宽泛,而acl就是为了解决这个问题而产生的,简单地来说acl就是可以设置特定用户或者用户组对于一个文件的操作权限。

android UID

对android而言,是“单”用户的(从代码看貌似现在也支持多用户了),AOSP将linux用户这个概念做了修改。给每一个安装运行的app赋予不同的UID。下面结合代码看看这些system,root等字符串到底是什么(代码基于android 5.1)。
在system/core/include/private/android_filesystem_config.h中,有定义了数字的AID,从注释可以看出各个数字所对应的含义:

#define AID_ROOT             0  /* traditional unix root user */#define AID_SYSTEM        1000  /* system server */#define AID_RADIO         1001  /* telephony subsystem, RIL */#define AID_BLUETOOTH     1002  /* bluetooth subsystem */#define AID_GRAPHICS      1003  /* graphics devices */#define AID_INPUT         1004  /* input devices */#define AID_AUDIO         1005  /* audio devices */#define AID_CAMERA        1006  /* camera devices */#define AID_LOG           1007  /* log devices */#define AID_COMPASS       1008  /* compass device */#define AID_MOUNT         1009  /* mountd socket */#define AID_WIFI          1010  /* wifi subsystem */#define AID_ADB           1011  /* android debug bridge (adbd) */#define AID_INSTALL       1012  /* group for installing packages */#define AID_MEDIA         1013  /* mediaserver process */#define AID_DHCP          1014  /* dhcp client */#define AID_SDCARD_RW     1015  /* external storage write access */#define AID_VPN           1016  /* vpn system */#define AID_KEYSTORE      1017  /* keystore subsystem */#define AID_USB           1018  /* USB devices */#define AID_DRM           1019  /* DRM server */#define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */#define AID_GPS           1021  /* GPS daemon */#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */#define AID_MEDIA_RW      1023  /* internal media storage write access */#define AID_MTP           1024  /* MTP USB driver access */#define AID_UNUSED2       1025  /* deprecated, DO NOT USE */#define AID_DRMRPC        1026  /* group for drm rpc */#define AID_NFC           1027  /* nfc subsystem */#define AID_SDCARD_R      1028  /* external storage read access */#define AID_CLAT          1029  /* clat part of nat464 */#define AID_LOOP_RADIO    1030  /* loop radio devices */#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */#define AID_PACKAGE_INFO  1032  /* access to installed package details */#define AID_SDCARD_PICS   1033  /* external storage photos access */#define AID_SDCARD_AV     1034  /* external storage audio/video access */#define AID_SDCARD_ALL    1035  /* access all users external storage */#define AID_LOGD          1036  /* log daemon */#define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */#define AID_SHELL         2000  /* adb and debug shell user */#define AID_CACHE         2001  /* cache access */#define AID_DIAG          2002  /* access to diagnostic resources *//* The 3000 series are intended for use as supplemental group id's only.
 * They indicate special Android capabilities that the kernel is aware of. */#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */#define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */#define AID_NET_RAW       3004  /* can create raw INET sockets */#define AID_NET_ADMIN     3005  /* can configure interfaces and routing tables. */#define AID_NET_BW_STATS  3006  /* read bandwidth statistics */#define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */#define AID_NET_BT_STACK  3008  /* bluetooth: access config files */#define AID_EVERYBODY     9997  /* shared between all apps in the same profile */#define AID_MISC          9998  /* access to misc storage */#define AID_NOBODY        9999#define AID_APP          10000  /* first app user */#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */#define AID_ISOLATED_END   99999 /* end of uids for fully isolated sandboxed processes */#define AID_USER        100000  /* offset for uid ranges for each user */#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */#define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */

其中APP的AID是从10000开始,而AID_USER为100000。从注释上看,Android现在也支持多用户了,AID_USER(100000)是每个用户的offset;而AID_APP表示用户安装的app的赋值的起始数值,而system,root这些AID系统已经固定。大概的意思是,第n个用户所安装的第m个apk的uid为n*AID_USER+10000+m (其中n从0开始,m每个apk都不同)。例如用户1所安装的第123个apk所对应的AID为0*100000+10000+123为10123,而用户2所安装的第123个apk所对应的AID为1*100000+10000+123为110123(每个用户最多可能装99000-10000=89000个app^_^)。

static const struct android_id_info android_ids[] = {
    { "root",          AID_ROOT, },

    { "system",        AID_SYSTEM, },

    { "radio",         AID_RADIO, },
    { "bluetooth",     AID_BLUETOOTH, },
    { "graphics",      AID_GRAPHICS, },
    { "input",         AID_INPUT, },
    { "audio",         AID_AUDIO, },
    { "camera",        AID_CAMERA, },
    { "log",           AID_LOG, },
    { "compass",       AID_COMPASS, },
    { "mount",         AID_MOUNT, },
    { "wifi",          AID_WIFI, },
    { "adb",           AID_ADB, },
    { "install",       AID_INSTALL, },
    { "media",         AID_MEDIA, },
    { "dhcp",          AID_DHCP, },
    { "sdcard_rw",     AID_SDCARD_RW, },
    { "vpn",           AID_VPN, },
    { "keystore",      AID_KEYSTORE, },
    { "usb",           AID_USB, },
    { "drm",           AID_DRM, },
    { "mdnsr",         AID_MDNSR, },
    { "gps",           AID_GPS, },    // AID_UNUSED1
    { "media_rw",      AID_MEDIA_RW, },
    { "mtp",           AID_MTP, },    // AID_UNUSED2
    { "drmrpc",        AID_DRMRPC, },
    { "nfc",           AID_NFC, },
    { "sdcard_r",      AID_SDCARD_R, },
    { "clat",          AID_CLAT, },
    { "loop_radio",    AID_LOOP_RADIO, },
    { "mediadrm",      AID_MEDIA_DRM, },
    { "package_info",  AID_PACKAGE_INFO, },
    { "sdcard_pics",   AID_SDCARD_PICS, },
    { "sdcard_av",     AID_SDCARD_AV, },
    { "sdcard_all",    AID_SDCARD_ALL, },
    { "logd",          AID_LOGD, },
    { "shared_relro",  AID_SHARED_RELRO, },

    { "shell",         AID_SHELL, },
    { "cache",         AID_CACHE, },
    { "diag",          AID_DIAG, },

    { "net_bt_admin",  AID_NET_BT_ADMIN, },
    { "net_bt",        AID_NET_BT, },
    { "inet",          AID_INET, },
    { "net_raw",       AID_NET_RAW, },
    { "net_admin",     AID_NET_ADMIN, },
    { "net_bw_stats",  AID_NET_BW_STATS, },
    { "everybody",     AID_EVERYBODY, },
    { "misc",          AID_MISC, },
    { "nobody",        AID_NOBODY, },
};

那么ps中第一列的用户id字符串和AID数字到底是如何转换的?在bionic/libc/bionic/stubs.cpp中,app_id_from_name函数就是从字符串到数字AID的转换,从注释就可以看出具体的转换方法和含义。
字符串已u*_开始,其中*为0,1,2….,为不同的用户,后面a代表app,i代表isolated,system,root等可以参考上面的数组android_ids[]。

// Translate a user/group name to the corresponding user/group id.// u0_a1234 -> 0 * AID_USER + AID_APP + 1234// u2_i1000 -> 2 * AID_USER + AID_ISOLATED_START + 1000// u1_system -> 1 * AID_USER + android_ids['system']// returns 0 and sets errno to ENOENT in case of errorstatic unsigned app_id_from_name(const char* name) {  if (name[0] != 'u' || !isdigit(name[1])) {
    errno = ENOENT;    return 0;
  }

  char* end;
  unsigned long userid = strtoul(name+1, &end, 10);  if (end[0] != '_' || end[1] == 0) {
    errno = ENOENT;    return 0;
  }

  unsigned long appid = 0;  if (end[1] == 'a' && isdigit(end[2])) {    // end will point to \0 if the strtoul below succeeds.
    appid = strtoul(end+2, &end, 10) + AID_APP;
  } else if (end[1] == 'i' && isdigit(end[2])) {    // end will point to \0 if the strtoul below succeeds.
    appid = strtoul(end+2, &end, 10) + AID_ISOLATED_START;
  } else {    for (size_t n = 0; n < android_id_count; n++) {      if (!strcmp(android_ids[n].name, end + 1)) {
        appid = android_ids[n].aid;        // Move the end pointer to the null terminator.
        end += strlen(android_ids[n].name) + 1;
      }
    }
  }  // Check that the entire string was consumed by one of the 3 cases above.
  if (end[0] != 0) {
    errno = ENOENT;    return 0;
  }  // Check that user id won't overflow.
  if (userid > 1000) {
    errno = ENOENT;    return 0;
  }  // Check that app id is within range.
  if (appid >= AID_USER) {
    errno = ENOENT;    return 0;
  }  return (unsigned)(appid + userid*AID_USER);
}