android servicemanager 怎么实现service管理

 我来答
huanglenzhi
推荐于2016-08-06 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
采纳数:117538 获赞数:517196
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。

向TA提问 私信TA
展开全部

  ServiceManager是android中比较重要的一个进程,它是在init进程启动之后启动,从名字上就可以看出来它是用来管理系统中的service。比如:InputMethodService、ActivityManagerService等。在ServiceManager中有两个比较重要的方法:add_service、check_service。系统的service需要通过add_service把自己的信息注册到ServiceManager中,当需要使用时,通过check_service检查该service是否存在。


  主函数(anrdroid4.0/frameworks/base/cmds/servicemanager/service_manager.c)


  从它的主函数代码开始:


  int main(int argc, char **argv)

  {

  struct binder_state *bs;

  void *svcmgr = BINDER_SERVICE_MANAGER;

  bs = binder_open(128*1024);

  if (binder_become_context_manager(bs)) {

  LOGE("cannot become context manager (%s)\n", strerror(errno));

  return -1;

  }

  svcmgr_handle = svcmgr;

  binder_loop(bs, svcmgr_handler);

  return 0;

  }

  从main函数中可以看出,它主要做了三件事情:


  打开/dev/binder设备,并在内存中映射128K的空间。

  通知Binder设备,把自己变成context_manager

  进入循环,不停的去读Binder设备,看是否有对service的请求,如果有的话,就去调用svcmgr_handler函数回调处理请求。

  服务注册


  再来看看ServiceManager中是怎么样去注册服务的。先来看先,当有对service的请求时,调用的回调函数svcmgr_handler:


  int svcmgr_handler(struct binder_state *bs,

  struct binder_txn *txn,

  struct binder_io *msg,

  struct binder_io *reply)

  {

  struct svcinfo *si;

  uint16_t *s;

  unsigned len;

  void *ptr;

  uint32_t strict_policy;

  //  LOGI("target=%p code=%d pid=%d uid=%d\n",

  //  txn->target, txn->code, txn->sender_pid, txn->sender_euid);

  if (txn->target != svcmgr_handle)

  return -1;

  // Equivalent to Parcel::enforceInterface(), reading the RPC

  // header with the strict mode policy mask and the interface name.

  // Note that we ignore the strict_policy and don't propagate it

  // further (since we do no outbound RPCs anyway).

  strict_policy = bio_get_uint32(msg);

  s = bio_get_string16(msg, &len);

  if ((len != (sizeof(svcmgr_id) / 2)) ||

  memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {

  fprintf(stderr,"invalid id %s\n", str8(s));

  return -1;

  }

  switch(txn->code) {

  case SVC_MGR_GET_SERVICE:

  case SVC_MGR_CHECK_SERVICE:

  s = bio_get_string16(msg, &len);

  ptr = do_find_service(bs, s, len);

  if (!ptr)

  break;

  bio_put_ref(reply, ptr);

  return 0;

  case SVC_MGR_ADD_SERVICE:

  s = bio_get_string16(msg, &len);

  ptr = bio_get_ref(msg);

  if (do_add_service(bs, s, len, ptr, txn->sender_euid))

  return -1;

  break;

  case SVC_MGR_LIST_SERVICES: {

  unsigned n = bio_get_uint32(msg);

  si = svclist;

  while ((n-- > 0) && si)

  si = si->next;

  if (si) {

  bio_put_string16(reply, si->name);

  return 0;

  }

  return -1;

  }

  default:

  LOGE("unknown code %d\n", txn->code);

  return -1;

  }

  bio_put_uint32(reply, 0);

  return 0;

  }

  在该回调函数中会判断Service有什么需要,如果是请求注册service,那么久执行:


  case SVC_MGR_ADD_SERVICE:

  s = bio_get_string16(msg, &len);

  ptr = bio_get_ref(msg);

  if (do_add_service(bs, s, len, ptr, txn->sender_euid))

  return -1;

  break;

  我们再来看看do_add_service中做了什么事情:


  int do_add_service(struct binder_state *bs,

  uint16_t *s, unsigned len,

  void *ptr, unsigned uid)

  {

  struct svcinfo *si;

  //    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);

  if (!ptr || (len == 0) || (len > 127))

  return -1;

  if (!svc_can_register(uid, s)) {

  LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",

  str8(s), ptr, uid);

  return -1;

  }

  si = find_svc(s, len);

  if (si) {

  if (si->ptr) {

  LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",

  str8(s), ptr, uid);

  return -1;

  }

  si->ptr = ptr;

  } else {

  si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));

  if (!si) {

  LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",

  str8(s), ptr, uid);

  return -1;

  }

  si->ptr = ptr;

  si->len = len;

  memcpy(si->name, s, (len + 1) * sizeof(uint16_t));

  si->name[len] = '\0';

  si->death.func = svcinfo_death;

  si->death.ptr = si;

  si->next = svclist;

  svclist = si;

  }

  binder_acquire(bs, ptr);

  binder_link_to_death(bs, ptr, &si->death);

  return 0;

  }

  在该函数中,首先会去检查是否有权限注册service,如果没有权限就直接返回,不能注册。


  if (!svc_can_register(uid, s)) {

  LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",

  str8(s), ptr, uid);

  return -1;

  }

  然后会去检查该service是否已经注册过了,如果已经注册过,那么就不能再注册了:


  si = find_svc(s, len);

  if (si) {

  if (si->ptr) {

  LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",

  str8(s), ptr, uid);

  return -1;

  }

  si->ptr = ptr;

  }

  再判断内存是否足够:


  si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));

  if (!si) {

  LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",

  str8(s), ptr, uid);

  return -1;

  }

  如果都没什么问题,会注册该service,加入到svcList中来。注意,在ServiceManager中维护service信息的地方就是svclist。里面存了service的name和handler。


  服务获取


  通过以上几个步骤,service就算注册成功了。那么当要获得该service的时候又是怎么去处理的。还是来看下回调函数中的判断:


  case SVC_MGR_CHECK_SERVICE:

  s = bio_get_string16(msg, &len);

  ptr = do_find_service(bs, s, len);

  if (!ptr)

  break;

  bio_put_ref(reply, ptr);

  return 0;


  如果是获取service,那么执行SVC_MGR_CHECK_SERVICE,并把返回的数据写入reply,返回给客户端。


  do_find_service函数中主要执行service的查找。


  void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)

  {

  struct svcinfo *si;

  si = find_svc(s, len);

  //    LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);

  if (si && si->ptr) {

  return si->ptr;

  } else {

  return 0;

  }

  }

  这样在ServiceManager中就完成了服务的注册和查找。来看下ServiceManager的功能图:

转载

大雅新科技有限公司
2024-11-19 广告
这方面更多更全面的信息其实可以找下大雅新。深圳市大雅新科技有限公司从事KVM延长器,DVI延长器,USB延长器,键盘鼠标延长器,双绞线视频传输器,VGA视频双绞线传输器,VGA延长器,VGA视频延长器,DVI KVM 切换器等,优质供应商,... 点击进入详情页
本回答由大雅新科技有限公司提供
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式