android netd守护进程机制 --- netd分析

来源:互联网 发布:大芒果数据库密码 编辑:程序博客网 时间:2024/05/16 15:23

3 netd分析

3.1 CommandListener初始化

CommandListener的构造方法分为3大步骤:

1,父类初始化,传入netd socket

FrameworkListener("netd", true)

父类FrameworkListener的构造方法如下,

FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :                            SocketListener(socketName, true, withSeq) {    init(socketName, withSeq);//初始化}

父类SocketListener的构造方法如下,

SocketListener::SocketListener(int socketFd, bool listen) {    init(NULL, socketFd, listen, false);}

FrameworkListener的init方法创建了FrameworkCommandCollection list。

mCommands = new FrameworkCommandCollection();

FrameworkCommand.h中的FrameworkCommandCollection定义如下,

typedef android::sysutils::List<FrameworkCommand *> FrameworkCommandCollection;

SocketListener的init方法创建了SocketClientCollection list。

mClients = new SocketClientCollection();

SocketClient.h的SocketClientCollection定义如下,

typedef android::sysutils::List<SocketClient *> SocketClientCollection;

2 注册不同的命令,新建不同的命令处理类

新建了十多个父类都为NetdCommand的子类,然后添加到FrameworkCommandCollection中,最后新加命令处理类。

例如,

registerCmd(new PppdCmd());

父类FrameworkListener的构造方法如下,

void FrameworkListener::registerCmd(FrameworkCommand *cmd) {    mCommands->push_back(cmd);}

当然, NetdCommand继承于FrameworkCommand。

创建NetworkController对象如下,

sNetCtrl = new NetworkController();

3.2 socket监听/消息分发

从startListener方法开始,

cl->startListener()

SocketListener 的startListener方法如下,

int SocketListener::startListener() {    return startListener(4);}

startListener主要逻辑如下,

mSock = android_get_control_socket(mSocketName))  //获取socket  •••listen(mSock, backlog) //监听客户端•••if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) //开启子线程监听socket

threadStart方法主要调用runListener方法,主要逻辑如下,

1, 等待Socket客户端发启连接请求

do {    alen = sizeof(addr);     c = accept(mSock, &addr, &alen);     SLOGV("%s got %d from accept", mSocketName, c);}

2,如果有客户端发起请求,说明有活动了,

pthread_mutex_lock(&mClientsLock);mClients->push_back(new SocketClient(c, true, mUseCmdNum));//将活动放入mClients中
3,调用onDataAvailable方法处理活动,
while (!pendingList.empty()) {            /* Pop the first item from the list */            it = pendingList.begin();            SocketClient* c = *it;            pendingList.erase(it);            /* Process it, if false is returned, remove from list */            if (!onDataAvailable(c)) {                release(c, false);            }            c->decRef();        }

FrameworkListener的onDataAvailable方法首先读取socket的指令,然后调用dispatchCommand分发指令,

len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer)));•••dispatchCommand(c, buffer + offset);

dispatchCommand从mCommands中取出注册的NetdCommand对象,逐个调用其runCommand方法。

for (i = mCommands->begin(); i != mCommands->end(); ++i) {        FrameworkCommand *c = *i;        if (!strcmp(argv[0], c->getCommand())) {            if (c->runCommand(cli, argc, argv)) {                SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));            }            goto out;        }}

3.3 消息处理

如果是上层NetworkManagementService.java通过netd socket发送过来的消息,调用的就是CommandListener.cpp

的内部类NetworkCommand的runCommand方法,

runCommand方法逻辑很简单,根据解析的指令调用NetworkController对应的方法,例如,

if (!strcmp(argv[1], "interface")) {        if (argc != 5) {            return syntaxError(client, "Missing argument");        }        unsigned netId = stringToNetId(argv[3]);        if (!strcmp(argv[2], "add")) { //add指令            if (int ret = sNetCtrl->addInterfaceToNetwork(netId, argv[4])) {                return operationError(client, "addInterfaceToNetwork() failed", ret);            }        } else if (!strcmp(argv[2], "remove")) { //remove指令             if (int ret = sNetCtrl->removeInterfaceFromNetwork(netId, argv[4])) {                return operationError(client, "removeInterfaceFromNetwork() failed", ret);            }        } else {            return syntaxError(client, "Unknown argument");        }        return success(client);    }

最后处理完成之后,调用success方法通过socket向上层发送消息。最后会调用

SocketClient的sendDataLockedv方法发送,

for (;;) {     ssize_t rc = TEMP_FAILURE_RETRY(      writev(mSocket, iov + current, iovcnt - current));//写入socket
原创粉丝点击