netd学习记录(二)kernel主动上报流程解析(一)

netd是连接framework以及kernel的中间桥梁,那么就看看首先是如何进行连接的吧。
两种方式:
1.kernel底层状态向framework层上报,framework层接受状态反馈,做出对应处理。
2.framework层向kernel发送命令,并且将处理结果返回给framework。

先看第一种方式,第一种方式主要是接收kernel主动上报的状态变化:比如600的InterfaceChange,601的BandwidthControl,以及一些其他需要主动上报的,这些code对应的状态值都在server/Responsecode.h中,同时,在NetworkMangementService.java的NetdCallbackReceiver的onreceive方法中也对对应上报消息做了对应处理。那么就来看看这一过程吧。

if (!(nm = NetlinkManager::Instance())) {
    ALOGE("Unable to create NetlinkManager");
    exit(1);
};

cl = new CommandListener();
nm->setBroadcaster((SocketListener *) cl);

if (nm->start()) {
    ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));
    exit(1);
}  

按照main函数的顺序,首先实例化了NetlinkManager:

NetlinkManager *NetlinkManager::Instance() {
    if (!sInstance)
        sInstance = new NetlinkManager();
    return sInstance;
}

NetlinkManager::NetlinkManager() {
    mBroadcaster = NULL;
}

就是一个简单的单例设计模式,然后在新建实例的时候将mBroadcaster初始化为null。 后面就是创建CommandListener,调用nm的setBroadcaster为新创建的cl。这样,nm中就拥有了cl的实例,就可以通过cl来向framework层传递信息。

随后调用nm的start方法

int NetlinkManager::start() {
if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
     0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII)) == NULL) {
    return -1;
}

if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE,
                                 RTMGRP_LINK |
                                 RTMGRP_IPV4_IFADDR |
                                 RTMGRP_IPV6_IFADDR |
                                 RTMGRP_IPV6_ROUTE |
                                 (1 << (RTNLGRP_ND_USEROPT - 1)),
     NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {
    return -1;
}

if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG,
    NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY)) == NULL) {
    ALOGE("Unable to open quota2 logging socket");
    // TODO: return -1 once the emulator gets a new kernel.
}

return 0;
}

创建了3个监听线程,根据setupSocket的参数不同可以限定监听socket的监听内核模块时间,分别start,并且返回了handler实例。

NetlinkHandler *NetlinkManager::setupSocket(int *sock, int netlinkFamily,
int groups, int format) {

struct sockaddr_nl nladdr;
int sz = 64 * 1024;
int on = 1;

memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = getpid();
nladdr.nl_groups = groups;
//创建socket
if ((*sock = socket(PF_NETLINK, SOCK_DGRAM, netlinkFamily)) < 0) {
    ALOGE("Unable to create netlink socket: %s", strerror(errno));
    return NULL;
}
//设置socket属性
if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
    ALOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno));
    close(*sock);
    return NULL;
}

if (setsockopt(*sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
    SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));
    close(*sock);
    return NULL;
}

if (bind(*sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
    ALOGE("Unable to bind netlink socket: %s", strerror(errno));
    close(*sock);
    return NULL;
}
//NetlinkHandler的start方法
//NetlinkHandler继承NetlinkListener,继承SocketListener
NetlinkHandler *handler = new NetlinkHandler(this, *sock, format);
if (handler->start()) {
    ALOGE("Unable to start NetlinkHandler: %s", strerror(errno));
    close(*sock);
    return NULL;
}

return handler;
}

创建监听线程大概如此,首先创建socket,设置相关属性,最后调用了NetlinkHandler的start方法,该方法在socketlistener中,

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

int SocketListener::startListener(int backlog) {

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;
    }
    SLOGV("got mSock = %d for %s", mSock, mSocketName);
}

if (mListen && listen(mSock, backlog) < 0) {
    SLOGE("Unable to listen on socket (%s)", strerror(errno));
    return -1;
} else if (!mListen)
    mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));

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;
}

首先进行了一些初始化的判断操作,不赘述,然后判断是tcp还是udp,因为此处是监听kernel上报信息,所以是udp,随后进行了pthread_create操作,同时也调用了SocketListener的threadStart方法

void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast<SocketListener *>(obj);

me->runListener();
pthread_exit(NULL);
return NULL;
}