uevent
/android/system/core/libcutils/uevent.c
uevent 是通过netlink socket发送消息给用户进程,这里的应用单纯接收组播消息。
android/system/extras/tests/uevents
./uevents
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73280292536 DRIVER=disp MODALIAS=platform:disp SEQNUM=5044
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73297201120 DRIVER=disp MODALIAS=platform:disp SEQNUM=5045
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73314112620 DRIVER=disp MODALIAS=platform:disp SEQNUM=5046
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73331023036 DRIVER=disp MODALIAS=platform:disp SEQNUM=5047
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73347935120 DRIVER=disp MODALIAS=platform:disp SEQNUM=5048
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73364849703 DRIVER=disp MODALIAS=platform:disp SEQNUM=5049
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73381759411 DRIVER=disp MODALIAS=platform:disp SEQNUM=5050
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73398670578 DRIVER=disp MODALIAS=platform:disp SEQNUM=5051
change@/devices/platform/disp ACTION=change DEVPATH=/devices/platform/disp SUBSYSTEM=platform VSYNC0=73415581370 DRIVER=disp MODALIAS=platform:disp SEQNUM=505
enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOVE, //更改了目录结构。
KOBJ_ONLINE, //设备上线/下线事件,常表示使能或者去使能。
KOBJ_OFFLINE,
KOBJ_MAX
};
static const char *kobject_actions[] = {
[KOBJ_ADD] = "add",
[KOBJ_REMOVE] = "remove",
[KOBJ_CHANGE] = "change",
[KOBJ_MOVE] = "move",
[KOBJ_ONLINE] = "online",
[KOBJ_OFFLINE] = "offline",
};
用户空间 libcutils.so
./core/libcutils/uevent.c
打开 uevent socket
//netlink socket
int uevent_open_socket(int buf_sz, bool passcred)
{
struct sockaddr_nl addr;
int on = passcred;
int s;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
//可以接收所有的family消息 , 单播设置0
addr.nl_groups = 0xffffffff;
//地址族(Address Family) PF_NETLINK
//协议号NETLINK_KOBJECT_UEVENT
//数据传输方式/socket类型 SOCK_DGRAM | SOCK_CLOEXEC
s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if(s < 0)
return -1;
setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &buf_sz, sizeof(buf_sz));
//SO_PEERCRED 远端的资格
setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
return -1;
}
return s;
}
/**
* Like recv(), but checks that messages actually originate from the kernel.
*/
ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length)
{
uid_t uid = -1;
return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid);
}
/**
* Like the above, but passes a uid_t in by pointer. In the event that this
* fails due to a bad uid check, the uid_t will be set to the uid of the
* socket's peer.
*
* If this method rejects a netlink message from outside the kernel, it
* returns -1, sets errno to EIO, and sets "user" to the UID associated with the
* message. If the peer UID cannot be determined, "user" is set to -1."
*/
ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer, size_t length