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))
问题
补充
参考
标签:return,socket,int,uevent,module,pthread,libsysutils,false 来源: https://www.cnblogs.com/pyjetson/p/14956253.html