Android5.0 vold-注册过程(下)

转载请标明出处:http://www.jianshu.com/users/183339cdc7ae/latest_articles

概述

这篇文章主要讲解的是,kernel/drvier是如何通过netlink发送uevent到userspace的,以及netlink协议在kernel中的注册过程

相关文章

Android5.0 vold-整体架构
Android5.0 vold-启动过程
Android5.0 vold-注册过程(上)

NetlinkManager

由之前的文章可以知道,netlinkManager可以接受从kernel/drvier发送过来的uevent信息,这里我们来看下它是如何接受消息的

监听

当native vold启动的时候,会创建NetlinkManager,然后调用setupSocket方法
这里会使用socket这个接口来创建netlink,然后就可以接听从kernel发过来的消息了
先假设大家都知道什么是netlinke,以及其使用方法. 不知道什么是netlink以及和socket区别的可以看这里,socket, netlink

NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily, int groups, int format) {
  ...
  nladdr.nl_family = AF_NETLINK;
  nladdr.nl_pid = getpid();
  nladdr.nl_groups = groups; 
  if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)) < 0) {...}
      ...
  if (bind(*sock, (struct sockaddr *) &nladdr,  sizeof (nladdr)) < 0) {...}

用流程图来表示如下:

Android5.0 vold-注册过程(下)_第1张图片
_regester_2.jpeg

kernel/driver

无论是socket还是netlink,都有一个服务端和客服端,上面只是一个客服端,这里我们来看看服务端是如何启动的以及如何发消息的

netlink协议注册

这里core_initcall方法,是kernel启动的时候会首先加载的模块
netlink_proto_init该方法除了做一些数据结构,对象实例化外,还向socket中进行了注册
这样,当userspace使用socket接口传入netlink协议的时候就会调用到af_netlink模块中

core_initcall(netlink_proto_init);
...
staticint__init netlink_proto_init(void)
{
 ...
 interr = proto_register(&netlink_proto, 0);
 ...
}
FilePath : kernel/net/netlink/af_netlink.c

kobject_uevent封装

我们一般向用户空间发送uevent消息的时候,不是直接使用af_netlink模块中的方法,而是使用kernel中有一个类似的工具类kobject_uevent来发送
我们来看看kobject_uevent模块是如何加载的
这里postcore_initcall是在core_initcall方法后加载的模块
会调用到ops里面的init方法,该方法会向af_netlink中进行注册
这里重点是netlink_kernel_create方法,如果想要自己进行封装,也就是对函数netlink_kernel_create进行封装

postcore_initcall(kobject_uevent_init);
static int __init kobject_uevent_init(void) {
  return register_pernet_subsys(&uevent_net_ops);
}
static struct pernet_operations uevent_net_ops = {
  .init  = uevent_net_init,
  .exit = uevent_net_exit,
};

static int uevent_net_init(struct net *net) {
  ...
  ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
  ...
  return 0;
}
FilePath : kernel/lib/kobject_uevent.c

kobject_uevent发送

当我们的驱动程序检测到事件,如:sd卡/otg插拔等,会调用kobject_uevent.c中kobject_uevent方法
其中action就是add或者remove之类的动作
最后kobject_uevent_env方法调用到af_netlink模块中,通知注册监听了uevent事件的进程

int kobject_uevent(struct kobject *kobj,  enum kobject_action action) {
  return kobject_uevent_env(kobj, action, NULL);
}
File : kernel/lib/kobject_uevent.c

用户socket接口注册

由之前可以知道,af_netlink启动的时候,会向socket进行注册
这样,当用户空间使用socket这个接口,并且传入netlink这个协议的时候,就可以找到af_netlink模块
当我们使用了socket这个接口后,还会调用bind方法,该方法会将pid,gid插入到af_netlink的数据结构中,以方便有数据的时候好知道通知哪

总结

用流程图来看,如下:

Android5.0 vold-注册过程(下)_第2张图片
_regester_3.jpeg

你可能感兴趣的:(Android5.0 vold-注册过程(下))