NetlinkManager类负责管理捕获内核的uevent事件,这里使用了Netlink套接字。
Netlink的概念:Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。Netlink套接字可以使用标准的套接字APIs来创建。socket(), bind(), sendmsg(), recvmsg() 和 close()很容易地应用到 netlink socket。netlink包含于头文件linux/netlink.h中。
平时的应用层一般都不会用到Netlink这个套接字,了解就行。
在Main.cpp文件中的main函数里面,有一个准备工作是用来开启监听内核uevent事件的线程,源码如下:
1
2
3
4
|
if
(nm->start()) {
SLOGE(
"Unable to start NetlinkManager (%s)"
,
strerror
(
errno
));
exit
(1);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
/**********************************************************************************
**file:system/vold/NetlinkManager.cpp
**以下一些socket的初始化,跟linux的应用层的tcp/udp使用差不多。
**********************************************************************************/
int
NetlinkManager::start() {
struct
sockaddr_nl nladdr;
int
sz = 64 * 1024;
memset
(&nladdr, 0,
sizeof
(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = 0xffffffff;
if
((mSock = socket(PF_NETLINK, SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
SLOGE(
"Unable to create uevent socket: %s"
,
strerror
(
errno
));
return
-1;
}
if
(setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz,
sizeof
(sz)) < 0) {
SLOGE(
"Unable to set uevent socket options: %s"
,
strerror
(
errno
));
return
-1;
}
if
(bind(mSock, (
struct
sockaddr *) &nladdr,
sizeof
(nladdr)) < 0) {
SLOGE(
"Unable to bind uevent socket: %s"
,
strerror
(
errno
));
return
-1;
}
/**********************************************************************************
**这里先说明NetlinkHandler类的继承关系:
**NetlinkHandler --> NetlinkListener --> SocketListener(父类)
**NetlinkHandler类的start()函数调用了SocketListener::startListener()函数,源码如下。
**********************************************************************************/
mHandler =
new
NetlinkHandler(mSock);
if
(mHandler->start()) {
SLOGE(
"Unable to start NetlinkHandler: %s"
,
strerror
(
errno
));
return
-1;
}
return
0;
}
/**********************************************************************************
**file:system/vold/NetlinkHandler.cpp
**该函数使用this指针调用自身的startListener函数,可以发现,在NetlinkHandler没有
**startListener()这个函数,这函数是它的父类的函数SocketListener::startListener;
**********************************************************************************/
int
NetlinkHandler::start() {
return
this
->startListener();
}
/**********************************************************************************
**file:system/core/libsysutils/src/SocketListener.cpp
**以下这个函数就涉及到其他方面的内容了,不在vold部分。
**********************************************************************************/
int
SocketListener::startListener() {
if
(!mSocketName && mSock == -1) {
SLOGE(
"Failed to start unbound listener"
);
errno
= EINVAL;
return
-1;
}
else
if
(mSocketName) {
if
((mSock = android_get_control_socket(mSocketName)) < 0) {
SLOGE(
"Obtaining file descriptor socket '%s' failed: %s"
,
mSocketName,
strerror
(
errno
));
return
-1;
}
}
if
(mListen && listen(mSock, 4) < 0) {
SLOGE(
"Unable to listen on socket (%s)"
,
strerror
(
errno
));
return
-1;
}
else
if
(!mListen)
mClients->push_back(
new
SocketClient(mSock));
if
(pipe(mCtrlPipe)) {
SLOGE(
"pipe failed (%s)"
,
strerror
(
errno
));
return
-1;
}
/**********************************************************************************
**该函数开启了一个监听线程。
**********************************************************************************/
if
(pthread_create(&mThread, NULL, SocketListener::threadStart,
this
)) {
SLOGE(
"pthread_create (%s)"
,
strerror
(
errno
));
return
-1;
}
return
0;
}
/**********************************************************************************
**该线程函数在类里面声明为静态函数:static void *threadStart(void *obj);
**所以不能调用this指针来指向自身的函数,所以通过pthread_create线程的创建函数来传递
**一个参数,将this指针传递给它;
**这里使用reinterpret_cast运算符是用来处理无关类型之间的转换,
**它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。
**********************************************************************************/
void
*SocketListener::threadStart(
void
*obj) {
SocketListener *me =
reinterpret_cast
<SocketListener *>(obj);
me->runListener();
pthread_exit(NULL);
return
NULL;
}
/**********************************************************************************
**该函数才是真正的处理函数了,使用select集合,结合fd_set结构体,可以判断套接字有无
**信息可读,如果没有,立即返回,不阻塞;
**还使用了管道,仅仅判断该套接字的读端是否有数据可读。
**********************************************************************************/
void
SocketListener::runListener() {
while
(1) {
SocketClientCollection::iterator it;
fd_set read_fds;
int
rc = 0;
int
max = 0;
FD_ZERO(&read_fds);
if
(mListen) {
max = mSock;
FD_SET(mSock, &read_fds);
}
FD_SET(mCtrlPipe[0], &read_fds);
if
(mCtrlPipe[0] > max)
max = mCtrlPipe[0];
pthread_mutex_lock(&mClientsLock);
for
(it = mClients->begin(); it != mClients->end(); ++it) {
FD_SET((*it)->getSocket(), &read_fds);
if
((*it)->getSocket() > max)
max = (*it)->getSocket();
}
pthread_mutex_unlock(&mClientsLock);
if
((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
SLOGE(
"select failed (%s)"
,
strerror
(
errno
));
sleep(1);
continue
;
}
else
if
(!rc)
continue
;
if
(FD_ISSET(mCtrlPipe[0], &read_fds))
break
;
if
(mListen && FD_ISSET(mSock, &read_fds)) {
struct
sockaddr addr;
socklen_t alen =
sizeof
(addr);
int
c;
if
((c = accept(mSock, &addr, &alen)) < 0) {
SLOGE(
"accept failed (%s)"
,
strerror
(
errno
));
sleep(1);
continue
;
}
pthread_mutex_lock(&mClientsLock);
mClients->push_back(
new
SocketClient(c));
pthread_mutex_unlock(&mClientsLock);
}
do
{
pthread_mutex_lock(&mClientsLock);
for
(it = mClients->begin(); it != mClients->end(); ++it) {
int
fd = (*it)->getSocket();
if
(FD_ISSET(fd, &read_fds)) {
pthread_mutex_unlock(&mClientsLock);
/**********************************************************************************
**onDataAvailable是SocketListener类声明的一个纯虚函数,在其子类NetlinkListener实现
**onDataAvailable函数,函数里面调用了NetlinkHandler类的onEvent函数,该函数是
**在NetlinkListener类中定义的纯虚函数,在vold中的NetlinkHandler类中实现。
**********************************************************************************/
if
(!onDataAvailable(*it)) {
close(fd);
pthread_mutex_lock(&mClientsLock);
delete
*it;
it = mClients->erase(it);
pthread_mutex_unlock(&mClientsLock);
}
FD_CLR(fd, &read_fds);
continue
;
}
}
pthread_mutex_unlock(&mClientsLock);
}
while
(0);
}
}
/**********************************************************************************
**file:system/core/libsysutils/src/NetlinkListener.cpp
**该函数用来处理内核的uevent事件,然后调用onEvent函数,让onEvent函数去捕获这些事件
**的信息。
**********************************************************************************/
bool
NetlinkListener::onDataAvailable(SocketClient *cli)
{
int
socket = cli->getSocket();
int
count;
if
((count = recv(socket, mBuffer,
sizeof
(mBuffer), 0)) < 0) {
SLOGE(
"recv failed (%s)"
,
strerror
(
errno
));
return
false
;
}
NetlinkEvent *evt =
new
NetlinkEvent();
if
(!evt->decode(mBuffer, count)) {
SLOGE(
"Error decoding NetlinkEvent"
);
goto
out;
}
/*下一篇文章介绍该函数*/
onEvent(evt);
out:
delete
evt;
return
true
;
}
|
原文:http://blog.csdn.net/gzshun/article/details/7100547