system_server进程启动后不止启动了很多重要的服务,还开启了一些重要的观察着(Observer),如:DockObserver、WiredAccessoryObserver。接着以WiredAccessoryObserver为例详细分析。
WiredAccessoryObserver继承于UeventObserver。WiredAccessoryObserver的构造方法里会注册系统开机广播,收到开机广播后调用父类的startObserving方法把相关设备的DEVPATH加入到UeventObserver中,并开启UEventThread线程,run方法被执行,该方法调用native_setup、next_event获取kernel发来的uevent消息,并调用子类的onUEvent完成事件的处理。
native_setup、next_event是native方法@android_os_UEventObserver.cpp,
native_setup调用uevent_init@hardware中uevent.c创建套接字
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = 0xffffffff;
s = socket(PF_NETLINK, SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);
bind(s, (struct sockaddr *) &addr, sizeof(addr));
next_event调用uevent_next_event通过recv接收kernel发送的uevent事件。
上面是用户空间如何接收uevent,下面分析kernel如何发送uevent:
设备驱动程序中一般在probe函数调用switch_set_state@switch_class.c调用kobject_uevent_env@kobject_uevent.c调用netlink_broadcast_filtered完成uevent的发送。
细心的读者可能要问,netlink如何与用户空间的socket对应起来呢?
postcore_initcall(kobject_uevent_init);会使kernel初始化时调用kobject_uevent_init,有兴趣的读者可以研究一下postcore_initcall的细节。kobject_uevent_init中调用register_pernet_subsys(&uevent_net_ops);register_pernet_subsys中会调用uevent_net_ops的init函数,也就是调用uevent_net_init,这里面可以看到netlink_kernel_create(net,NETLINK_KOBJECT_UEVENT,1, NULL, NULL, THIS_MODULE);netlink_kernel_create()函数创建一个socket套接字,该函数原型在netlink.h有定义,其类型是表示往用户空间发送消息的NETLINK_KOBJECT_UEVENT,groups=1,由于uevent只往用户空间发送消息而不接受,因此其输入回调函数input和cb_mutex都设置为NULL。