专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
51好读  ›  专栏  ›  安卓开发精选

Android LowMemoryKiller原理分析(上)

安卓开发精选  · 公众号  · android  · 2016-10-14 08:26

正文

请到「今天看啥」查看全文


{

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 ;

}

}

}


  • 当sLmkdSocket为空,并且打开失败,重新执行该操作;

  • 当sLmkdOutputStream写入buf信息失败,则会关闭sLmkdSocket,重新执行该操作;


这个重新执行操作最多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







请到「今天看啥」查看全文