libsysutils_module

目录

概述

源码解析

1. NetlinkListener模块-处理socket消息的

1.1 NetlinkListener构造函数

NetlinkListener::NetlinkListener(int socket) :
                            SocketListener(socket, false) {
    mFormat = NETLINK_FORMAT_ASCII;// 代表UEvent消息的内容为ASCII字符串
}

1.2 onDataAvailable-处理数据

bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
    int socket = cli->getSocket();
    ssize_t count;
    uid_t uid = -1;

    bool require_group = true;
    if (mFormat == NETLINK_FORMAT_BINARY_UNICAST) {
        require_group = false;
    }
// 接收socket消息
    count = TEMP_FAILURE_RETRY(uevent_kernel_recv(socket,
            mBuffer, sizeof(mBuffer), require_group, &uid));
    if (count < 0) {
        SLOGE("recvmsg failed (%s)", strerror(errno));
        return false;
    }
// 解析uevent信息
    NetlinkEvent *evt = new NetlinkEvent();
    // buffer为uevent信息,count为信息大小,mFormat为NETLINK_FORMAT_ASCII
    if (evt->decode(mBuffer, count, mFormat)) {
        onEvent(evt);
    } else if (mFormat != NETLINK_FORMAT_BINARY) {
        // Don't complain if parseBinaryNetlinkMessage returns false. That can
        // just mean that the buffer contained no messages we're interested in.
        SLOGE("Error decoding NetlinkEvent");
    }

    delete evt;
    return true;
}

2. SocketListener模块-管理socketclient的

2.1 SocketListener构造函数

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

2.2 init-初始化SocketListener

void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
    mListen = listen;	// false
    mSocketName = socketName;	// nul
    mSock = socketFd;	// uevent socket fd
    mUseCmdNum = useCmdNum;	// false
    // 线程安全赋值mClientsLock为null
    pthread_mutex_init(&mClientsLock, nullptr);
}

2.3 startListener-启动socket线程

int SocketListener::startListener() {
    return startListener(4);
}// backlog是访问者最大为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);
        fcntl(mSock, F_SETFD, FD_CLOEXEC);
    }

    if (mListen && listen(mSock, backlog) < 0) {
        SLOGE("Unable to listen on socket (%s)", strerror(errno));
        return -1;
    } else if (!mListen)// 监听者为null,所以需要建立一个socketclient来监听
        mClients[mSock] = new SocketClient(mSock, false, mUseCmdNum);
// 创建管道,mCtrlPipe[0]为读端,mCtrlPipe[1]为写端
    if (pipe2(mCtrlPipe, O_CLOEXEC)) {
        SLOGE("pipe failed (%s)", strerror(errno));
        return -1;
    }
// 创建线程
    if (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)) {
        SLOGE("pthread_create (%s)", strerror(errno));
        return -1;
    }

    return 0;
}

2.4 threadStart-线程运行的函数

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

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

void SocketListener::runListener() {
    while (true) {
        std::vector<pollfd> fds;

        pthread_mutex_lock(&mClientsLock);
        fds.reserve(2 + mClients.size());
        // 这个pipe用来控制socketlistener的,关闭,以及删除socketclient
        fds.push_back({.fd = mCtrlPipe[0], .events = POLLIN});
        if (mListen) fds.push_back({.fd = mSock, .events = POLLIN});
        for (auto pair : mClients) {
            // NB: calling out to an other object with mClientsLock held (safe)
            const int fd = pair.second->getSocket();
            if (fd != pair.first) SLOGE("fd mismatch: %d != %d", fd, pair.first);
            // 把uevent的socket放进去了
            fds.push_back({.fd = fd, .events = POLLIN});
        }
        pthread_mutex_unlock(&mClientsLock);

        SLOGV("mListen=%d, mSocketName=%s", mListen, mSocketName);
        // 监听uevent事件
        int rc = TEMP_FAILURE_RETRY(poll(fds.data(), fds.size(), -1));
        if (rc < 0) {
            SLOGE("poll failed (%s) mListen=%d", strerror(errno), mListen);
            sleep(1);
            continue;
        }
// 这个是读mCtrlPipe的
        if (fds[0].revents & (POLLIN | POLLERR)) {
            char c = CtrlPipe_Shutdown;
            TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1));
            if (c == CtrlPipe_Shutdown) {
                // 这个break是直接退出了while(true)循环了,相当于退出线程了
                break;
            }
            // 如果是CtrlPipe_Wakeup,就跳过下面执行的
            continue;
        }// mListen相关,mListen为false
        if (mListen && (fds[1].revents & (POLLIN | POLLERR))) {
            int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC));
            if (c < 0) {
                SLOGE("accept failed (%s)", strerror(errno));
                sleep(1);
                continue;
            }
            pthread_mutex_lock(&mClientsLock);
            mClients[c] = new SocketClient(c, true, mUseCmdNum);
            pthread_mutex_unlock(&mClientsLock);
        }

        // Add all active clients to the pending list first, so we can release
        // the lock before invoking the callbacks.
        std::vector<SocketClient*> pending;
        pthread_mutex_lock(&mClientsLock);
        const int size = fds.size();
        for (int i = mListen ? 2 : 1; i < size; ++i) {
            const struct pollfd& p = fds[i];
            // 这里是读uevent的socket的
            if (p.revents & (POLLIN | POLLERR)) {
                auto it = mClients.find(p.fd);
                if (it == mClients.end()) {
                    SLOGE("fd vanished: %d", p.fd);
                    continue;
                }
                SocketClient* c = it->second;
                pending.push_back(c);
                // 加一个引用计数
                c->incRef();
            }
        }
        pthread_mutex_unlock(&mClientsLock);

        for (SocketClient* c : pending) {
            // Process it, if false is returned, remove from the map
            SLOGV("processing fd %d", c->getSocket());
            // 这里执行回调onDataAvailable
            if (!onDataAvailable(c)) {
                release(c, false);	// 失败了,就release的时候,会decref,就删除socketclient了
            }
            // 用完之后,减少一个引用计数,成对出现
            c->decRef();
        }
    }
}

2.5 release-释放socketclients

bool SocketListener::release(SocketClient* c, bool wakeup) {
    bool ret = false;
    /* if our sockets are connection-based, remove and destroy it */
    // mListen为false,没有释放socketclient
    if (mListen && c) {
        /* Remove the client from our map */
        SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
        pthread_mutex_lock(&mClientsLock);
        ret = (mClients.erase(c->getSocket()) != 0);
        pthread_mutex_unlock(&mClientsLock);
        if (ret) {
            ret = c->decRef();
            if (wakeup) {
                char b = CtrlPipe_Wakeup;
                TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &b, 1));
            }
        }
    }
    return ret;
}

3. SocketClient模块-存储socket fd,负责socket通信的,主要是发信息的函数

3.1 SocketClient构造函数

SocketClient::SocketClient(int socket, bool owned, bool useCmdNum) {
    init(socket, owned, useCmdNum);
}
void SocketClient::init(int socket, bool owned, bool useCmdNum) {
    mSocket = socket;	// socket fd
    mSocketOwned = owned;	// false
    mUseCmdNum = useCmdNum;	// null
    pthread_mutex_init(&mWriteMutex, nullptr);
    pthread_mutex_init(&mRefCountMutex, nullptr);
    mPid = -1;
    mUid = -1;
    mGid = -1;
    mRefCount = 1;
    mCmdNum = 0;

    struct ucred creds;
    socklen_t szCreds = sizeof(creds);
    memset(&creds, 0, szCreds);

    int err = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
    if (err == 0) {
        // 获取其pid和uid和gid
        mPid = creds.pid;
        mUid = creds.uid;
        mGid = creds.gid;
    }
}

3.2 incRef-加引用计数

void SocketClient::incRef() {
    pthread_mutex_lock(&mRefCountMutex);
    // 初始值是1
    mRefCount++;
    pthread_mutex_unlock(&mRefCountMutex);
}

3.3 decRef-减少引用计数

bool SocketClient::decRef() {
    bool deleteSelf = false;
    pthread_mutex_lock(&mRefCountMutex);
    mRefCount--;
    // 为0就释放自身
    if (mRefCount == 0) {
        deleteSelf = true;
    } else if (mRefCount < 0) {
        SLOGE("SocketClient refcount went negative!");
    }
    pthread_mutex_unlock(&mRefCountMutex);
    if (deleteSelf) {
        delete this;
    }
    return deleteSelf;
}

4. NetlinkEvent模块-解析uevent事件的

4.1 NetlinkEvent构造函数

NetlinkEvent::NetlinkEvent() {
    mAction = Action::kUnknown;
    memset(mParams, 0, sizeof(mParams));
    mPath = nullptr;
    mSubsystem = nullptr;
}

4.2 decode-解析uevent事件的

bool NetlinkEvent::decode(char *buffer, int size, int format) {
    if (format == NetlinkListener::NETLINK_FORMAT_BINARY
            || format == NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST) {
        return parseBinaryNetlinkMessage(buffer, size);
    } else {// buffer为uevent信息,count为信息大小,mFormat为NETLINK_FORMAT_ASCII
        return parseAsciiNetlinkMessage(buffer, size);
    }
}

4.3 parseAsciiNetlinkMessage-解析uevent事件

bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) {
    const char *s = buffer;
    const char *end;
    int param_idx = 0;
    int first = 1;

    if (size == 0)
        return false;

    /* Ensure the buffer is zero-terminated, the code below depends on this */
    buffer[size-1] = '\0';

    end = s + size;
    while (s < end) {
        if (first) {
            // uevent事件:change@/devices/platform/soc@2900000/6000000.disp
            const char *p;
            /* buffer is 0-terminated, no need to check p < end */
            // 第一次,找@的位置
            for (p = s; *p != '@'; p++) {
                if (!*p) { /* no '@', should not happen */
                    return false;
                }
            }// mPath = /devices/platform/soc@2900000/6000000.disp
            mPath = strdup(p+1);
            first = 0;
        } else {
            const char* a;
            if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != nullptr) {
                // 看action是什么
                if (!strcmp(a, "add"))
                    mAction = Action::kAdd;
                else if (!strcmp(a, "remove"))
                    mAction = Action::kRemove;
                else if (!strcmp(a, "change"))
                    mAction = Action::kChange;
                // SEQNUM数字
            } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != nullptr) {
                if (!ParseInt(a, &mSeq)) {
                    SLOGE("NetlinkEvent::parseAsciiNetlinkMessage: failed to parse SEQNUM=%s", a);
                }
            } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != nullptr) {
                mSubsystem = strdup(a);
            } else if (param_idx < NL_PARAMS_MAX) {
                mParams[param_idx++] = strdup(s);
            }
        }
        // uevent事件是一行一行的,跳到下一行
        s += strlen(s) + 1;
    }
    return true;
}

4.4 HAS_CONST_PREFIX-看有没有prefix

static const char*
    // 有prefixlen长度的
has_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen)
{
    if ((end - str) >= (ptrdiff_t)prefixlen &&
        (prefixlen == 0 || !memcmp(str, prefix, prefixlen))) {
        return str + prefixlen;
    } else {
        return nullptr;
    }
}

/* Same as strlen(x) for constant string literals ONLY */
#define CONST_STRLEN(x)  (sizeof(x)-1)

/* Convenience macro to call has_prefix with a constant string literal  */
#define HAS_CONST_PREFIX(str,end,prefix)  has_prefix((str),(end),prefix,CONST_STRLEN(prefix))

问题

补充

参考

上一篇:C线程池


下一篇:pthread_mutex 引起的 core dump + 学习 gdb