zoukankan      html  css  js  c++  java
  • 读取proc信息的可扩展实现

    需求

    1. 将内存、线程数等信息注册到zk上进行监控

    2. 统计信息,为下一步做负载均衡做准备。

    实现

    本文只解决问题1。

    从网上查询了下,这些信息可以从proc文件系统中获取,如果不知道proc的,可以Google下。

    网上有读取proc信息的lib——libproc,即 procps , 据说htop等实现就是基于它的。

    我下载下来了,include和lib都生成了,好不容易找到一篇教程,结果在

    stackoverflow上,见有人说有内存泄露,需要如下方法做。

    int main(int argc, char** argv)
    {
     // fillarg  used for cmdline
     // fillstat used for cmd
     PROCTAB* proc = openproc(PROC_FILLARG | PROC_FILLSTAT);
    
     while (proc_t* proc_info = readproc(proc, NULL)) {
        // do something
        freeproc(proc_info)
     }
     closeproc(proc);
    }


    于是看proc_t的定义,充满了上世纪的风格,似乎迷失在信息各种信息中了,于是无奈放弃了,直接手撸吧。代码稍后附上,如下是几个关键的技术点

    1. 即然shell 命名可以获取proc信息,在C中,我们可以通过popen建立管道,获取shell命令的输出。

    2. 获取进程号,可以通过 getpid()

    3. sizeof(xx)/sizeof(xx[0]) 可以获取数组的大小。

    4. 设计了ZeroHelper 结构,方便了扩展

    5. offsetof 宏用于获取元素的偏移

    6. 函数指针的应用恰到好处。

    #include <time.h>
    #include <stddef.h>
    #include <string.h>
    #include <stdint.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include<unistd.h>
    struct StatInfo
    {
        time_t   start_time;
        uint32_t duration_sec;
        uint32_t conn_cnt;
        uint32_t pmem_mb;   // peak virtual memory
        uint32_t vmem_mb;   // virtual memory
        uint32_t rmem_mb;   // real memory
        uint32_t thread_cnt;// 线程数
        uint32_t cpu_usage; // cpu
    };
    typedef int (*convert_fn)(const char* str, void* value_ptr);
    struct ZeroHelper {
        const char* key;
        uint32_t key_len;
        uint32_t value_offset;
        convert_fn fn;
    };
    
    int proc_stat_mem_convert(const char* str, void* value_ptr)
    {
        uint32_t* value = (uint32_t*)value_ptr;
        while (*str && isspace(*str))
          ++str;
        *value = atoi(str);
        return 0;
    }
    static const ZeroHelper proc_mem_convert_array[] = {
        {"VmPeak:", sizeof("VmPeak:") - 1, offsetof(StatInfo, pmem_mb), proc_stat_mem_convert},
        {"VmSize:", sizeof("VmSize:") - 1, offsetof(StatInfo, vmem_mb), proc_stat_mem_convert},
        {"VmRSS:", sizeof("VmRSS:") - 1, offsetof(StatInfo, rmem_mb),   proc_stat_mem_convert},
        {"Threads:", sizeof("Threads:") - 1, offsetof(StatInfo, thread_cnt), proc_stat_mem_convert},
    };
    int fresh_memstat_info(pid_t pid, StatInfo* info)
    {
        char proc_cmd [1024];
        snprintf(proc_cmd, sizeof(proc_cmd), "cat /proc/%d/status", pid);
        FILE* fp = popen(proc_cmd, "r");
        char proc_line[1024];
        const ZeroHelper* helper = &(proc_mem_convert_array[0]);
        const int kHelperLen = sizeof(proc_mem_convert_array)/sizeof(proc_mem_convert_array[0]);
        int j = 0;
        while (fgets(proc_line, sizeof(proc_line), fp) != NULL)
        {
            if (j >= kHelperLen)
            {
                break;
            }
            // 忽略 key 头部
            if (strncmp(proc_line,
                        helper->key, helper->key_len) == 0)
            {
                helper->fn(proc_line + helper->key_len,
                           (char*)info + helper->value_offset);
                ++helper;
                ++j;
            }
        }
        pclose(fp);
        return 0;
    }
    int main()
    {
        StatInfo info;
        pid_t pid = getpid();
        fresh_memstat_info(pid, &info);
        printf("%d	%ukB	%ukB	%ukB	%u
    ",
               pid,
               info.pmem_mb, info.vmem_mb,
               info.rmem_mb, info.thread_cnt);
        sleep(1000);
        return 0;
    }
    View Code
  • 相关阅读:
    86. Partition List
    328. Odd Even Linked List
    19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)
    24. Swap Nodes in Pairs
    2. Add Two Numbers(2个链表相加)
    92. Reverse Linked List II(链表部分反转)
    109. Convert Sorted List to Binary Search Tree
    138. Copy List with Random Pointer
    为Unity的新版ugui的Prefab生成预览图
    ArcEngine生成矩形缓冲区
  • 原文地址:https://www.cnblogs.com/westfly/p/4230956.html
Copyright © 2011-2022 走看看