正文
{
if
(
sLmkdSocket
==
null
)
{
//打开socket 【见小节2.4】
if
(
openLmkdSocket
()
==
false
)
{
try
{
Thread
.
sleep
(
1000
);
}
catch
(
InterruptedException
ie
)
{
}
continue
;
}
}
try
{
//将buf信息写入lmkd socket
sLmkdOutputStream
.
write
(
buf
.
array
(),
0
,
buf
.
position
());
return
;
}
catch
(
IOException
ex
)
{
try
{
sLmkdSocket
.
close
();
}
catch
(
IOException
ex2
)
{
}
sLmkdSocket
=
null
;
}
}
}
这个重新执行操作最多3次,如果3次后还失败,则writeLmkd操作会直接结束。尝试3次,则不管结果如何都将退出该操作,可见writeLmkd写入操作还有可能失败的。
2.4 PL.openLmkdSocket
private
static
boolean
openLmkdSocket
()
{
try
{
sLmkdSocket
=
new
LocalSocket
(
LocalSocket
.
SOCKET_SEQPACKET
);
//与远程lmkd守护进程建立socket连接
sLmkdSocket
.
connect
(
new
LocalSocketAddress
(
"lmkd"
,
LocalSocketAddress
.
Namespace
.
RESERVED
));
sLmkdOutputStream
=
sLmkdSocket
.
getOutputStream
();
}
catch
(
IOException
ex
)
{
Slog
.
w
(
TAG
,
"lowmemorykiller daemon socket open failed"
);
sLmkdSocket
=
null
;
return
false
;
}
return
true
;
}
sLmkdSocket采用的是SOCK_SEQPACKET,这是类型的socket能提供顺序确定的,可靠的,双向基于连接的socket endpoint,与类型SOCK_STREAM很相似,唯一不同的是SEQPACKET保留消息的边界,而SOCK_STREAM是基于字节流,并不会记录边界。
举例:本地通过write()系统调用向远程先后发送两组数据:一组4字节,一组8字节;对于SOCK_SEQPACKET类型通过read()能获知这是两组数据以及大小,而对于SOCK_STREAM类型,通过read()一次性读取到12个字节,并不知道数据包的边界情况。
常见的数据类型还有SOCK_DGRAM,提供数据报形式,用于udp这样不可靠的通信过程。
再回到openLmkdSocket()方法,该方法是打开一个名为lmkd的socket,类型为LocalSocket.SOCKET_SEQPACKET,这只是一个封装,真实类型就是SOCK_SEQPACKET。先跟远程lmkd守护进程建立连接,再向其通过write()将数据写入该socket,再接下来进入lmkd过程。
三. lmkd
lmkd是由init进程,通过解析init.rc文件来启动的lmkd守护进程,lmkd会创建名为lmkd的socket,节点位于/dev/socket/lmkd,该socket用于跟上层framework交互。
service
lmkd
/
system
/
bin
/
lmkd
class
core
critical
socket lmkd
seqpacket
0660
system system
writepid
/
dev
/
cpuset
/
system
-
background
/
tasks
lmkd启动后,接下里的操作都在platform/system/core/lmkd/lmkd.c文件,首先进入main()方法
3.1 main
int
main
(
int
argc
__unused
,
char
**
argv
__unused
)
{
struct
sched_param
param
=
{
.
sched_priority
=
1
,
};
mlockall
(
MCL_FUTURE
);
sched_setscheduler
(
0
,
SCHED_FIFO
,
&
param
);
//初始化【见小节3.2】
if
(
!
init
())
mainloop
();
//成功后进入loop [见小节3.3]
ALOGI
(
"exiting"
);
return
0
;
}
3.2 init
static
int
init
(
void
)
{
struct
epoll_event
epev
;
int
i
;
int
ret
;
page_k