linux下event机制,[转载]android & Linux uevent机制
Linux uevent机制Uevent是内核通知android有状态变化的一种方法,比如USB线插入、拔出,电池电量变化等等。其本质是内核发送(可以通过socket)一个字符串,应用层(android)接收并解释该字符串,获取相应信息。一、Kernel侧:UEVENT的发起在Kernel端,主要是通过函数int kobject_uevent_env(struct kobject*kobj, en
Linux uevent机制
Uevent是内核通知android有状态变化的一种方法,比如USB线插入、拔出,电池电量变化等等。其本质是内核发送(可以通过socket)一个字符串,应用层(android)接收并解释该字符串,获取相应信息。
一、Kernel侧:
UEVENT的发起在Kernel端,主要是通过函数
int kobject_uevent_env(struct kobject
*kobj, enum kobject_action action,char
*envp_ext[])
该函数的主要功能是根据参数组合一个字符串并发送。一个典型的字符串如下:change@/devices/platform/msm-battery/power_supply/usb纮ACTION=change纮DEVPATH=/devices/platform/msm-battery/power_supply/usb纮SUBSYSTEM=power_supply纮POWER_SUPPLY_NAME=usb纮POWER_SUPPLY_ONLINE=0纮SEQNUM=1486纮
上面这块来自网上,这段内容是否有问题,待考究。
下面看这个函数:
int kobject_uevent_env(struct
kobject *kobj, enum kobject_action action,
char *envp_ext[])
{
struct kobj_uevent_env
*env;
const char *action_string =
kobject_actions[action];//获取object的动作
//蓝色为为方便看代码加入的
static const char *kobject_actions[] =
{
[KOBJ_ADD] = "add",
[KOBJ_REMOVE] = "remove",
[KOBJ_CHANGE] = "change",
[KOBJ_MOVE] = "move",
[KOBJ_ONLINE] = "online",
[KOBJ_OFFLINE] = "offline",
};
//以上为kobject标准的动作,调用时需要传入相应的enum值
const char *devpath =
NULL;
const char
*subsystem;
struct kobject
*top_kobj;
struct kset *kset;
const struct kset_uevent_ops
*uevent_ops;
u64 seq;
int i = 0;
int retval = 0;
#ifdef CONFIG_NET
struct uevent_sock
*ue_sk;
#endif
pr_debug("kobject: '%s' (%p):
%sn",
kobject_name(kobj), kobj,
__func__);
=========================================================
这段代码用来查找该kobject所属于的kset,得到 uevent_ops
top_kobj = kobj;
while
(!top_kobj->kset &&
top_kobj->parent)
top_kobj =
top_kobj->parent;
if
(!top_kobj->kset) {
pr_debug("kobject: '%s' (%p):
%s: attempted to send uevent "
"without kset!n",
kobject_name(kobj), kobj,
__func__);
return -EINVAL;
}
kset =
top_kobj->kset;
uevent_ops =
kset->uevent_ops;
=========================================================
if
(kobj->uevent_suppress) {
pr_debug("kobject: '%s' (%p):
%s: uevent_suppress "
"caused the event to
drop!n",
kobject_name(kobj), kobj,
__func__);
return 0;
}
if (uevent_ops
&&
uevent_ops->filter)
if
(!uevent_ops->filter(kset, kobj)) {
pr_debug("kobject: '%s' (%p):
%s: filter function "
"caused the event to
drop!n",
kobject_name(kobj), kobj,
__func__);
return 0;
}
====================================================
获取subsystem信息
if (uevent_ops
&&
uevent_ops->name)
subsystem =
uevent_ops->name(kset, kobj);
else
subsystem =
kobject_name(&kset->kobj);
if (!subsystem) {
pr_debug("kobject: '%s' (%p):
%s: unset subsystem caused the "
"event to drop!n",
kobject_name(kobj), kobj,
__func__);
return 0;
}
=========================================================
env = kzalloc(sizeof(struct
kobj_uevent_env), GFP_KERNEL);
if (!env)
return -ENOMEM;
devpath =
kobject_get_path(kobj, GFP_KERNEL);//获取kobject的设备路径
if (!devpath) {
retval = -ENOENT;
goto exit;
}
//下面准备要传递的信息数据
retval = add_uevent_var(env, "ACTION=%s",
action_string);
if (retval)
goto exit;
retval = add_uevent_var(env, "DEVPATH=%s",
devpath);
if (retval)
goto exit;
retval = add_uevent_var(env, "SUBSYSTEM=%s",
subsystem);
if (retval)
goto exit;
//envp_ext[i]是传进来的参数,为该event时携带的一些自定义的信息
if (envp_ext) {
for (i = 0; envp_ext[i]; i++)
{
retval = add_uevent_var(env, "%s", envp_ext[i]);
if (retval)
goto exit;
}
}
if (uevent_ops
&&
uevent_ops->uevent) {
retval =
uevent_ops->uevent(kset, kobj, env);
if (retval) {
pr_debug("kobject: '%s' (%p):
%s: uevent() returned "
"%dn", kobject_name(kobj),
kobj,
__func__, retval);
goto exit;
}
}
if (action ==
KOBJ_ADD)
kobj->state_add_uevent_sent
= 1;
else if (action ==
KOBJ_REMOVE)
kobj->state_remove_uevent_sent
= 1;
//加入该event的序号
spin_lock(&sequence_lock);
seq =
++uevent_seqnum;
spin_unlock(&sequence_lock);
retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long
long)seq);
if (retval)
goto exit;
#if
defined(CONFIG_NET)
//下面通过网络socket将数据发送出去
mutex_lock(&uevent_sock_mutex);
list_for_each_entry(ue_sk,
&uevent_sock_list, list) {
struct sock *uevent_sock =
ue_sk->sk;
struct sk_buff
*skb;
size_t len;
len = strlen(action_string) +
strlen(devpath) + 2;
skb = alloc_skb(len +
env->buflen, GFP_KERNEL);//申请网络skb数据
if (skb) {
char *scratch;
scratch = skb_put(skb,
len);
sprintf(scratch, "%s@%s",
action_string, devpath);
此时scratch中就增加了change@/devices/platform/msm-battery/power_supply/usb的
//组长网络skb数据结构
for (i = 0; i
< env->envp_idx; i++) {
len =
strlen(env->envp[i]) + 1;
scratch = skb_put(skb,
len);
strcpy(scratch,
env->envp[i]);
}
NETLINK_CB(skb).dst_group =
1;//下面开始发送数据
retval =
netlink_broadcast_filtered(uevent_sock, skb,
0, 1, GFP_KERNEL,
kobj_bcast_filter,
kobj);
if (retval == -ENOBUFS ||
retval == -ESRCH)
retval = 0;
} else
retval = -ENOMEM;
}
mutex_unlock(&uevent_sock_mutex);
#endif
if (uevent_helper[0]
&& !kobj_usermode_filter(kobj))
{
char *argv [3];
argv [0] =
uevent_helper;
argv [1] = (char
*)subsystem;
argv [2] = NULL;
retval = add_uevent_var(env,
"HOME=/");
if (retval)
goto exit;
retval =
add_uevent_var(env,
"PATH=/sbin:/bin:/usr/sbin:/usr/bin");
if (retval)
goto exit;
retval =
call_usermodehelper(argv[0], argv,
env->envp,
UMH_WAIT_EXEC);
}
exit:
kfree(devpath);
kfree(env);
return retval;
}
二
android 侧
private final UEventObserver mUEventObserver = new
UEventObserver()
{
@Override
public void onUEvent(UEventObserver.UEvent
event) {
if
(DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString());
String state =
event.get("USB_STATE");
String accessory =
event.get("ACCESSORY");
//Added for USB Develpment debug, more log
for more debuging help
if(DEBUG) Log.w(TAG, "mUEventObserver:
onUEvent: state = " + state);
//Added for USB Develpment debug, more log
for more debuging help
if
(state != null) {
mHandler.updateState(state);
}
else if ("START".equals(accessory)) {
if
(DEBUG) Slog.d(TAG, "got accessory start");
setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY,
false);
}
}
};
在类初始化时会调用下面的动作,启动监听动作。
mUEventObserver.startObserving(USB_STATE_MATCH);
最终会调用到UEventObserver的addObserver:
private
ArrayList mObservers = new
ArrayList();
public void
addObserver(String match, UEventObserver observer) {
synchronized(mObservers)
{
mObservers.add(match);
mObservers.add(observer);
}
}
private static final String
USB_STATE_MATCH =
"DEVPATH=/devices/virtual/android_usb/android0";
该函数最终会将”DEVPATH=/devices/virtual/android_usb/android0”增加到匹配序列中,当kernel发送具有该字符串的数据时,就返回匹配成功,然后调用mUEventObserver
的onUEvent函数;
UeventObserver.java
private static class UEventThread extends
Thread {
private
ArrayList mObservers = new
ArrayList();
UEventThread() {
super("UEventObserver");
}
public void run() {
native_setup();
byte[] buffer = new byte[1024];
int len;
while (true) {
len = next_event(buffer);
if
(len > 0) {
String bufferStr = new String(buffer, 0,
len); // easier to search a String
synchronized (mObservers) {
for (int i = 0; i <
mObservers.size(); i += 2) {
if
(bufferStr.indexOf((String)mObservers.get(i)) != -1) {
((UEventObserver)mObservers.get(i+1))
.onUEvent(new
UEvent(bufferStr));
}
}
}
}
}
}
更多推荐



所有评论(0)