使用logcat命令增加logd白名单 黑名单
2017-03-15 11:29
309 查看
Logd的白名单和黑名单我们在之前的logd中分析过了,这里的白名单和黑名单只是在logd丢失log时使用。logd丢失log会先删除黑名单的log,然后删除普通log。最后还不够的话再删除白名单的log。
这个命令对调试还是很有用 但本质原因还是cpu调度不够 加上log太多导致丢失。
命令使用
我们先看下logcat的help,注意下面-p(小写)代表获取白名单和黑名单,而-P(大写)代表设置白名单和黑名单。注意-P后面有单引号的
[html]
view plain
copy
-p print prune white and ~black list. Service is specified as
UID, UID/PID or /PID. Weighed for quicker pruning if prefix
with ~, otherwise weighed for longevity if unadorned. All
other pruning activity is oldest first. Special case ~!
represents an automatic quicker pruning for the noisiest
UID as determined by the current statistics.
-P '<list> ...' set prune white and ~black list, using same format as
printed above. Must be quoted.
设置uid1000为白名单 2002为黑名单
[html]
view plain
copy
logcat -P '1000 ~2002'
使用logcat -p查询
[html]
view plain
copy
root@lte26007:/ # logcat -p
1000 ~2002
当然我们也可以用pid
只用uid:
logcat –P uid
只用Pid:
logcat –P /pid
都用uid+pid:
logcat –P uid/pid
[cpp]
view plain
copy
case 'P':
setPruneList = optarg;
break;
......
if (setPruneList) {
size_t len = strlen(setPruneList);
/*extra 32 bytes are needed by android_logger_set_prune_list */
size_t bLen = len + 32;
char *buf = NULL;
if (asprintf(&buf, "%-*s", (int)(bLen - 1), setPruneList) > 0) {
buf[len] = '\0';
if (android_logger_set_prune_list(logger_list, buf, bLen)) {
logcat_panic(false, "failed to set the prune list");
}
free(buf);
} else {
logcat_panic(false, "failed to set the prune list (alloc)");
}
}
android_logger_set_prune_list函数就是往logd发送 setPruneList命令
[cpp]
view plain
copy
int android_logger_set_prune_list(struct logger_list *logger_list __unused,
char *buf, size_t len)
{
const char cmd[] = "setPruneList ";
const size_t cmdlen = sizeof(cmd) - 1;
if (strlen(buf) > (len - cmdlen)) {
return -ENOMEM; /* KISS */
}
memmove(buf + cmdlen, buf, len - cmdlen);
buf[len - 1] = '\0';
memcpy(buf, cmd, cmdlen);
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
}
send_log_msg就是获取logd的socket,往其write。
[cpp]
view plain
copy
static ssize_t send_log_msg(struct logger *logger,
const char *msg, char *buf, size_t buf_size)
{
ssize_t ret;
size_t len;
char *cp;
int errno_save = 0;
int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (sock < 0) {
return sock;
}
if (msg) {
snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
}
len = strlen(buf) + 1;
ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
if (ret <= 0) {
goto done;
}
len = buf_size;
cp = buf;
while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
struct pollfd p;
if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
break;
}
len -= ret;
cp += ret;
memset(&p, 0, sizeof(p));
p.fd = sock;
p.events = POLLIN;
/* Give other side 20ms to refill pipe */
ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
if (ret <= 0) {
break;
}
if (!(p.revents & POLLIN)) {
ret = 0;
break;
}
}
if (ret >= 0) {
ret += buf_size - len;
}
done:
if ((ret == -1) && errno) {
errno_save = errno;
}
close(sock);
if (errno_save) {
errno = errno_save;
}
return ret;
}
2.2 logd
我们再来看看logd的代码处理
view plain
copy
int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
setname();
if (!clientHasLogCredentials(cli)) {
cli->sendMsg("Permission Denied");
return 0;
}
char *cp = NULL;
for (int i = 1; i < argc; ++i) {
char *p = cp;
if (p) {
cp = NULL;
asprintf(&cp, "%s %s", p, argv[i]);
free(p);
} else {
asprintf(&cp, "%s", argv[i]);
}
}
int ret = mBuf.initPrune(cp);
free(cp);
if (ret) {
cli->sendMsg("Invalid");
return 0;
}
cli->sendMsg("success");
return 0;
}
这里主要调用了LogBuffer的initPrune函数
[cpp]
view plain
copy
int initPrune(char *cp) { return mPrune.init(cp); }
而这个函数又是调用了PruneList的init函数,我们来看下这个函数。首先就是把白黑名单清除,然后根据传入的字符串首个字母是~或者!就是这部分是黑名单,否则就是白名单。然后处理其uid、pid最后加入到list中(这里的list要么是mNaughty要么是mNice)
[cpp]
view plain
copy
int PruneList::init(char *str) {
mWorstUidEnabled = true;
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end();) {//清空白名单
it = mNice.erase(it);
}
for (it = mNaughty.begin(); it != mNaughty.end();) {//清空黑名单
it = mNaughty.erase(it);
}
if (!str) {
return 0;
}
mWorstUidEnabled = false;
for(; *str; ++str) {
if (isspace(*str)) {
continue;
}
PruneCollection *list;
if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
++str;
// special case, translates to worst UID at priority in blacklist
if (*str == '!') {
mWorstUidEnabled = true;
++str;
if (!*str) {
break;
}
if (!isspace(*str)) {
return 1;
}
continue;
}
if (!*str) {
return 1;
}
list = &mNaughty;//有~或者!开头的代表这次是黑名单
} else {
list = &mNice;//否则就是白名单
}
uid_t uid = Prune::uid_all;
if (isdigit(*str)) {//uid
uid = 0;
do {
uid = uid * 10 + *str++ - '0';
} while (isdigit(*str));
}
pid_t pid = Prune::pid_all;
if (*str == '/') {//有/代表pid
++str;
if (isdigit(*str)) {
pid = 0;
do {
pid = pid * 10 + *str++ - '0';
} while (isdigit(*str));
}
}
if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
return 1;
}
if (*str && !isspace(*str)) {
return 1;
}
// insert sequentially into list
PruneCollection::iterator it = list->begin();
while (it != list->end()) {
Prune &p = *it;
int m = uid - p.mUid;
if (m == 0) {
if (p.mPid == p.pid_all) {
break;
}
if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
it = list->erase(it);
continue;
}
m = pid - p.mPid;
}
if (m <= 0) {
if (m < 0) {
list->insert(it, Prune(uid,pid));
}
break;
}
++it;
}
if (it == list->end()) {
list->push_back(Prune(uid,pid));//放入list,这里的list要么是白名单要么是黑名单
}
if (!*str) {
break;
}
}
return 0;
}
而最后判断是白名单还是黑名单就是通过下面的函数,最终还是看mNaughty和mNice列表是否有符合的。
[cpp]
view plain
copy
bool PruneList::naughty(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
if (!(*it).cmp(element)) {
return true;
}
}
return false;
}
bool PruneList::nice(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
if (!(*it).cmp(element)) {
return true;
}
}
return false;
}
获取白黑名单logcat的代码就不看了,最终到如下函数,也就是把mNice和mNaughty的获取传给logcat再显示出来
[cpp]
view plain
copy
void PruneList::format(char **strp) {
if (*strp) {
free(*strp);
*strp = NULL;
}
static const char nice_format[] = " %s";
const char *fmt = nice_format + 1;
android::String8 string;
if (mWorstUidEnabled) {
string.setTo("~!");
fmt = nice_format;
}
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
char *a = NULL;
(*it).format(&a);
string.appendFormat(fmt, a);
fmt = nice_format;
free(a);
}
static const char naughty_format[] = " ~%s";
fmt = naughty_format + (*fmt != ' ');
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
char *a = NULL;
(*it).format(&a);
string.appendFormat(fmt, a);
fmt = naughty_format;
free(a);
}
*strp = strdup(string.string());
}
这个命令对调试还是很有用 但本质原因还是cpu调度不够 加上log太多导致丢失。
命令使用
我们先看下logcat的help,注意下面-p(小写)代表获取白名单和黑名单,而-P(大写)代表设置白名单和黑名单。注意-P后面有单引号的[html]
view plain
copy
-p print prune white and ~black list. Service is specified as
UID, UID/PID or /PID. Weighed for quicker pruning if prefix
with ~, otherwise weighed for longevity if unadorned. All
other pruning activity is oldest first. Special case ~!
represents an automatic quicker pruning for the noisiest
UID as determined by the current statistics.
-P '<list> ...' set prune white and ~black list, using same format as
printed above. Must be quoted.
设置uid1000为白名单 2002为黑名单
[html]
view plain
copy
logcat -P '1000 ~2002'
使用logcat -p查询
[html]
view plain
copy
root@lte26007:/ # logcat -p
1000 ~2002
当然我们也可以用pid
只用uid:
logcat –P uid
只用Pid:
logcat –P /pid
都用uid+pid:
logcat –P uid/pid
二、代码
2.1 logcat
logcat处理当是P命令,把字符串放到setPruneList,最后调用android_logger_set_prune_list函数[cpp]
view plain
copy
case 'P':
setPruneList = optarg;
break;
......
if (setPruneList) {
size_t len = strlen(setPruneList);
/*extra 32 bytes are needed by android_logger_set_prune_list */
size_t bLen = len + 32;
char *buf = NULL;
if (asprintf(&buf, "%-*s", (int)(bLen - 1), setPruneList) > 0) {
buf[len] = '\0';
if (android_logger_set_prune_list(logger_list, buf, bLen)) {
logcat_panic(false, "failed to set the prune list");
}
free(buf);
} else {
logcat_panic(false, "failed to set the prune list (alloc)");
}
}
android_logger_set_prune_list函数就是往logd发送 setPruneList命令
[cpp]
view plain
copy
int android_logger_set_prune_list(struct logger_list *logger_list __unused,
char *buf, size_t len)
{
const char cmd[] = "setPruneList ";
const size_t cmdlen = sizeof(cmd) - 1;
if (strlen(buf) > (len - cmdlen)) {
return -ENOMEM; /* KISS */
}
memmove(buf + cmdlen, buf, len - cmdlen);
buf[len - 1] = '\0';
memcpy(buf, cmd, cmdlen);
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
}
send_log_msg就是获取logd的socket,往其write。
[cpp]
view plain
copy
static ssize_t send_log_msg(struct logger *logger,
const char *msg, char *buf, size_t buf_size)
{
ssize_t ret;
size_t len;
char *cp;
int errno_save = 0;
int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (sock < 0) {
return sock;
}
if (msg) {
snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
}
len = strlen(buf) + 1;
ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
if (ret <= 0) {
goto done;
}
len = buf_size;
cp = buf;
while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
struct pollfd p;
if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
break;
}
len -= ret;
cp += ret;
memset(&p, 0, sizeof(p));
p.fd = sock;
p.events = POLLIN;
/* Give other side 20ms to refill pipe */
ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
if (ret <= 0) {
break;
}
if (!(p.revents & POLLIN)) {
ret = 0;
break;
}
}
if (ret >= 0) {
ret += buf_size - len;
}
done:
if ((ret == -1) && errno) {
errno_save = errno;
}
close(sock);
if (errno_save) {
errno = errno_save;
}
return ret;
}
2.2 logd
我们再来看看logd的代码处理2.2.1 设置白黑名单
[cpp]view plain
copy
int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
int argc, char **argv) {
setname();
if (!clientHasLogCredentials(cli)) {
cli->sendMsg("Permission Denied");
return 0;
}
char *cp = NULL;
for (int i = 1; i < argc; ++i) {
char *p = cp;
if (p) {
cp = NULL;
asprintf(&cp, "%s %s", p, argv[i]);
free(p);
} else {
asprintf(&cp, "%s", argv[i]);
}
}
int ret = mBuf.initPrune(cp);
free(cp);
if (ret) {
cli->sendMsg("Invalid");
return 0;
}
cli->sendMsg("success");
return 0;
}
这里主要调用了LogBuffer的initPrune函数
[cpp]
view plain
copy
int initPrune(char *cp) { return mPrune.init(cp); }
而这个函数又是调用了PruneList的init函数,我们来看下这个函数。首先就是把白黑名单清除,然后根据传入的字符串首个字母是~或者!就是这部分是黑名单,否则就是白名单。然后处理其uid、pid最后加入到list中(这里的list要么是mNaughty要么是mNice)
[cpp]
view plain
copy
int PruneList::init(char *str) {
mWorstUidEnabled = true;
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end();) {//清空白名单
it = mNice.erase(it);
}
for (it = mNaughty.begin(); it != mNaughty.end();) {//清空黑名单
it = mNaughty.erase(it);
}
if (!str) {
return 0;
}
mWorstUidEnabled = false;
for(; *str; ++str) {
if (isspace(*str)) {
continue;
}
PruneCollection *list;
if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
++str;
// special case, translates to worst UID at priority in blacklist
if (*str == '!') {
mWorstUidEnabled = true;
++str;
if (!*str) {
break;
}
if (!isspace(*str)) {
return 1;
}
continue;
}
if (!*str) {
return 1;
}
list = &mNaughty;//有~或者!开头的代表这次是黑名单
} else {
list = &mNice;//否则就是白名单
}
uid_t uid = Prune::uid_all;
if (isdigit(*str)) {//uid
uid = 0;
do {
uid = uid * 10 + *str++ - '0';
} while (isdigit(*str));
}
pid_t pid = Prune::pid_all;
if (*str == '/') {//有/代表pid
++str;
if (isdigit(*str)) {
pid = 0;
do {
pid = pid * 10 + *str++ - '0';
} while (isdigit(*str));
}
}
if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
return 1;
}
if (*str && !isspace(*str)) {
return 1;
}
// insert sequentially into list
PruneCollection::iterator it = list->begin();
while (it != list->end()) {
Prune &p = *it;
int m = uid - p.mUid;
if (m == 0) {
if (p.mPid == p.pid_all) {
break;
}
if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
it = list->erase(it);
continue;
}
m = pid - p.mPid;
}
if (m <= 0) {
if (m < 0) {
list->insert(it, Prune(uid,pid));
}
break;
}
++it;
}
if (it == list->end()) {
list->push_back(Prune(uid,pid));//放入list,这里的list要么是白名单要么是黑名单
}
if (!*str) {
break;
}
}
return 0;
}
而最后判断是白名单还是黑名单就是通过下面的函数,最终还是看mNaughty和mNice列表是否有符合的。
[cpp]
view plain
copy
bool PruneList::naughty(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
if (!(*it).cmp(element)) {
return true;
}
}
return false;
}
bool PruneList::nice(LogBufferElement *element) {
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
if (!(*it).cmp(element)) {
return true;
}
}
return false;
}
2.2 获取白黑名单
获取白黑名单logcat的代码就不看了,最终到如下函数,也就是把mNice和mNaughty的获取传给logcat再显示出来[cpp]
view plain
copy
void PruneList::format(char **strp) {
if (*strp) {
free(*strp);
*strp = NULL;
}
static const char nice_format[] = " %s";
const char *fmt = nice_format + 1;
android::String8 string;
if (mWorstUidEnabled) {
string.setTo("~!");
fmt = nice_format;
}
PruneCollection::iterator it;
for (it = mNice.begin(); it != mNice.end(); ++it) {
char *a = NULL;
(*it).format(&a);
string.appendFormat(fmt, a);
fmt = nice_format;
free(a);
}
static const char naughty_format[] = " ~%s";
fmt = naughty_format + (*fmt != ' ');
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
char *a = NULL;
(*it).format(&a);
string.appendFormat(fmt, a);
fmt = naughty_format;
free(a);
}
*strp = strdup(string.string());
}
相关文章推荐
- 使用logcat命令增加logd白名单 黑名单
- adb常用命令和logcat使用
- 使用logcat命令
- 使用命令将logcat中的内容输出到文本文件中(防止滑屏看不到错误信息)
- adb logcat [option] [filter-specs]命令参数以及使用说明
- 为DB2 新增加的用户不能直接使用db2命令的解决办法
- 使用命令将logcat中的内容输出到文本文件中
- mac上使用github命令提交代码实例(一)增加文件
- 使用 logcat 命令打印内核信息
- Android NDK 开发中 adb logcat 命令的使用
- 使用命令将logcat中的内容输出到文本文件中
- adb常用命令和logcat使用
- adb常用命令和logcat使用
- adb常用命令和logcat使用
- Android中log及logcat命令的使用
- adb常用命令和logcat使用
- 使用命令将logcat中的内容输出到文本文件中
- logcat命令使用方法和查看android系统日志缓冲区内容的方法
- 使用logcat命令
- logcat 命令使用方法