使用logcat命令增加logd白名单 黑名单

来源:互联网 发布:权限系统数据库设计 编辑:程序博客网 时间:2024/06/06 16:54
Logd的白名单和黑名单我们在之前的logd中分析过了,这里的白名单和黑名单只是在logd丢失log时使用。logd丢失log会先删除黑名单的log,然后删除普通log。最后还不够的话再删除白名单的log。

这个命令对调试还是很有用 但本质原因还是cpu调度不够 加上log太多导致丢失。

命令使用

我们先看下logcat的help,注意下面-p(小写)代表获取白名单和黑名单,而-P(大写)代表设置白名单和黑名单。注意-P后面有单引号的

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. -p              print prune white and ~black list. Service is specified as  
  2.                 UID, UID/PID or /PID. Weighed for quicker pruning if prefix  
  3.                 with ~, otherwise weighed for longevity if unadorned. All  
  4.                 other pruning activity is oldest first. Special case ~!  
  5.                 represents an automatic quicker pruning for the noisiest  
  6.                 UID as determined by the current statistics.  
  7. -P '<list> ...' set prune white and ~black list, using same format as  
  8.                 printed above. Must be quoted.  
设置uid1000为白名单 2002为黑名单
[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. logcat -P '1000 ~2002'  

使用logcat -p查询

[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. root@lte26007:/ # logcat -p  
  2. 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 在CODE上查看代码片派生到我的代码片
  1. case 'P':  
  2.     setPruneList = optarg;  
  3. break;  
  4. ......  
  5. if (setPruneList) {  
  6.     size_t len = strlen(setPruneList);  
  7.     /*extra 32 bytes are needed by  android_logger_set_prune_list */  
  8.     size_t bLen = len + 32;  
  9.     char *buf = NULL;  
  10.     if (asprintf(&buf, "%-*s", (int)(bLen - 1), setPruneList) > 0) {  
  11.         buf[len] = '\0';  
  12.         if (android_logger_set_prune_list(logger_list, buf, bLen)) {  
  13.             logcat_panic(false"failed to set the prune list");  
  14.         }  
  15.         free(buf);  
  16.     } else {  
  17.         logcat_panic(false"failed to set the prune list (alloc)");  
  18.     }  
  19. }  

android_logger_set_prune_list函数就是往logd发送 setPruneList命令

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. int android_logger_set_prune_list(struct logger_list *logger_list __unused,  
  2.                                   char *buf, size_t len)  
  3. {  
  4.     const char cmd[] = "setPruneList ";  
  5.     const size_t cmdlen = sizeof(cmd) - 1;  
  6.   
  7.     if (strlen(buf) > (len - cmdlen)) {  
  8.         return -ENOMEM; /* KISS */  
  9.     }  
  10.     memmove(buf + cmdlen, buf, len - cmdlen);  
  11.     buf[len - 1] = '\0';  
  12.     memcpy(buf, cmd, cmdlen);  
  13.   
  14.     return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));  
  15. }  

send_log_msg就是获取logd的socket,往其write。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static ssize_t send_log_msg(struct logger *logger,  
  2.                             const char *msg, char *buf, size_t buf_size)  
  3. {  
  4.     ssize_t ret;  
  5.     size_t len;  
  6.     char *cp;  
  7.     int errno_save = 0;  
  8.     int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,  
  9.                                    SOCK_STREAM);  
  10.     if (sock < 0) {  
  11.         return sock;  
  12.     }  
  13.   
  14.     if (msg) {  
  15.         snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);  
  16.     }  
  17.   
  18.     len = strlen(buf) + 1;  
  19.     ret = TEMP_FAILURE_RETRY(write(sock, buf, len));  
  20.     if (ret <= 0) {  
  21.         goto done;  
  22.     }  
  23.   
  24.     len = buf_size;  
  25.     cp = buf;  
  26.     while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {  
  27.         struct pollfd p;  
  28.   
  29.         if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {  
  30.             break;  
  31.         }  
  32.   
  33.         len -= ret;  
  34.         cp += ret;  
  35.   
  36.         memset(&p, 0, sizeof(p));  
  37.         p.fd = sock;  
  38.         p.events = POLLIN;  
  39.   
  40.         /* Give other side 20ms to refill pipe */  
  41.         ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));  
  42.   
  43.         if (ret <= 0) {  
  44.             break;  
  45.         }  
  46.   
  47.         if (!(p.revents & POLLIN)) {  
  48.             ret = 0;  
  49.             break;  
  50.         }  
  51.     }  
  52.   
  53.     if (ret >= 0) {  
  54.         ret += buf_size - len;  
  55.     }  
  56.   
  57. done:  
  58.     if ((ret == -1) && errno) {  
  59.         errno_save = errno;  
  60.     }  
  61.     close(sock);  
  62.     if (errno_save) {  
  63.         errno = errno_save;  
  64.     }  
  65.     return ret;  
  66. }  


2.2 logd

我们再来看看logd的代码处理

2.2.1 设置白黑名单

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,  
  2.                                          int argc, char **argv) {  
  3.     setname();  
  4.     if (!clientHasLogCredentials(cli)) {  
  5.         cli->sendMsg("Permission Denied");  
  6.         return 0;  
  7.     }  
  8.   
  9.     char *cp = NULL;  
  10.     for (int i = 1; i < argc; ++i) {  
  11.         char *p = cp;  
  12.         if (p) {  
  13.             cp = NULL;  
  14.             asprintf(&cp, "%s %s", p, argv[i]);  
  15.             free(p);  
  16.         } else {  
  17.             asprintf(&cp, "%s", argv[i]);  
  18.         }  
  19.     }  
  20.   
  21.     int ret = mBuf.initPrune(cp);  
  22.     free(cp);  
  23.   
  24.     if (ret) {  
  25.         cli->sendMsg("Invalid");  
  26.         return 0;  
  27.     }  
  28.   
  29.     cli->sendMsg("success");  
  30.   
  31.     return 0;  
  32. }  

这里主要调用了LogBuffer的initPrune函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. int initPrune(char *cp) { return mPrune.init(cp); }  

而这个函数又是调用了PruneList的init函数,我们来看下这个函数。首先就是把白黑名单清除,然后根据传入的字符串首个字母是~或者!就是这部分是黑名单,否则就是白名单。然后处理其uid、pid最后加入到list中(这里的list要么是mNaughty要么是mNice)

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. int PruneList::init(char *str) {  
  2.     mWorstUidEnabled = true;  
  3.     PruneCollection::iterator it;  
  4.     for (it = mNice.begin(); it != mNice.end();) {//清空白名单  
  5.         it = mNice.erase(it);  
  6.     }  
  7.     for (it = mNaughty.begin(); it != mNaughty.end();) {//清空黑名单  
  8.         it = mNaughty.erase(it);  
  9.     }  
  10.   
  11.     if (!str) {  
  12.         return 0;  
  13.     }  
  14.   
  15.     mWorstUidEnabled = false;  
  16.   
  17.     for(; *str; ++str) {  
  18.         if (isspace(*str)) {  
  19.             continue;  
  20.         }  
  21.   
  22.         PruneCollection *list;  
  23.         if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented  
  24.             ++str;  
  25.             // special case, translates to worst UID at priority in blacklist  
  26.             if (*str == '!') {  
  27.                 mWorstUidEnabled = true;  
  28.                 ++str;  
  29.                 if (!*str) {  
  30.                     break;  
  31.                 }  
  32.                 if (!isspace(*str)) {  
  33.                     return 1;  
  34.                 }  
  35.                 continue;  
  36.             }  
  37.             if (!*str) {  
  38.                 return 1;  
  39.             }  
  40.             list = &mNaughty;//有~或者!开头的代表这次是黑名单  
  41.         } else {  
  42.             list = &mNice;//否则就是白名单  
  43.         }  
  44.   
  45.         uid_t uid = Prune::uid_all;  
  46.         if (isdigit(*str)) {//uid  
  47.             uid = 0;  
  48.             do {  
  49.                 uid = uid * 10 + *str++ - '0';  
  50.             } while (isdigit(*str));  
  51.         }  
  52.   
  53.         pid_t pid = Prune::pid_all;  
  54.         if (*str == '/') {//有/代表pid  
  55.             ++str;  
  56.             if (isdigit(*str)) {  
  57.                 pid = 0;  
  58.                 do {  
  59.                     pid = pid * 10 + *str++ - '0';  
  60.                 } while (isdigit(*str));  
  61.             }  
  62.         }  
  63.   
  64.         if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {  
  65.             return 1;  
  66.         }  
  67.   
  68.         if (*str && !isspace(*str)) {  
  69.             return 1;  
  70.         }  
  71.   
  72.         // insert sequentially into list  
  73.         PruneCollection::iterator it = list->begin();  
  74.         while (it != list->end()) {  
  75.             Prune &p = *it;  
  76.             int m = uid - p.mUid;  
  77.             if (m == 0) {  
  78.                 if (p.mPid == p.pid_all) {  
  79.                     break;  
  80.                 }  
  81.                 if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {  
  82.                     it = list->erase(it);  
  83.                     continue;  
  84.                 }  
  85.                 m = pid - p.mPid;  
  86.             }  
  87.             if (m <= 0) {  
  88.                 if (m < 0) {  
  89.                     list->insert(it, Prune(uid,pid));  
  90.                 }  
  91.                 break;  
  92.             }  
  93.             ++it;  
  94.         }  
  95.         if (it == list->end()) {  
  96.             list->push_back(Prune(uid,pid));//放入list,这里的list要么是白名单要么是黑名单  
  97.         }  
  98.         if (!*str) {  
  99.             break;  
  100.         }  
  101.     }  
  102.   
  103.     return 0;  
  104. }  

而最后判断是白名单还是黑名单就是通过下面的函数,最终还是看mNaughty和mNice列表是否有符合的。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. bool PruneList::naughty(LogBufferElement *element) {  
  2.     PruneCollection::iterator it;  
  3.     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {  
  4.         if (!(*it).cmp(element)) {  
  5.             return true;  
  6.         }  
  7.     }  
  8.     return false;  
  9. }  
  10.   
  11. bool PruneList::nice(LogBufferElement *element) {  
  12.     PruneCollection::iterator it;  
  13.     for (it = mNice.begin(); it != mNice.end(); ++it) {  
  14.         if (!(*it).cmp(element)) {  
  15.             return true;  
  16.         }  
  17.     }  
  18.     return false;  
  19. }  



2.2 获取白黑名单

获取白黑名单logcat的代码就不看了,最终到如下函数,也就是把mNice和mNaughty的获取传给logcat再显示出来

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void PruneList::format(char **strp) {  
  2.     if (*strp) {  
  3.         free(*strp);  
  4.         *strp = NULL;  
  5.     }  
  6.   
  7.     static const char nice_format[] = " %s";  
  8.     const char *fmt = nice_format + 1;  
  9.   
  10.     android::String8 string;  
  11.   
  12.     if (mWorstUidEnabled) {  
  13.         string.setTo("~!");  
  14.         fmt = nice_format;  
  15.     }  
  16.   
  17.     PruneCollection::iterator it;  
  18.   
  19.     for (it = mNice.begin(); it != mNice.end(); ++it) {  
  20.         char *a = NULL;  
  21.         (*it).format(&a);  
  22.   
  23.         string.appendFormat(fmt, a);  
  24.         fmt = nice_format;  
  25.   
  26.         free(a);  
  27.     }  
  28.   
  29.     static const char naughty_format[] = " ~%s";  
  30.     fmt = naughty_format + (*fmt != ' ');  
  31.     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {  
  32.         char *a = NULL;  
  33.         (*it).format(&a);  
  34.   
  35.         string.appendFormat(fmt, a);  
  36.         fmt = naughty_format;  
  37.   
  38.         free(a);  
  39.     }  
  40.   
  41.     *strp = strdup(string.string());  

0 0