muduo源码解析13-processinfo命名空间
processinfo命名空间
作用:
看不懂... 好多函数连见都没见过,这里就当是看个眼熟了,以后用得着可以过来找找看。
参考:https://blog.csdn.net/MoonWisher_liang/article/details/107332128
这个processinfo命名空间里面主要是实现了一些关于读取进程信息的函数
linux提供了一个虚拟文件系统放在/proc目录下,包含了各种用于展示内核信息的文件
允许进程通过常规I/O读取.
在/proc下保存的文件/目录是由内核在进程访问此类信息动态创建的
一个进程对应/proc下的一个子目录,就是/proc/PID
而/proc/PID下面有:fd子目录负责文件描述符,task子目录下还有子目录TID,包含线程信息
头文件:
#ifndef PROCESSINFO_H #define PROCESSINFO_H //#include"base/stringpiece.h" 又来?继续自己用std::string实现 #include"base/types.h" #include"base/timestamp.h" #include<vector> #include<sys/types.h> namespace mymuduo { namespace processinfo { pid_t pid(); //返回进程pid string pidString(); //返回pid的字符串形式 uid_t uid(); //返回userID string username(); //返回userID字符串 uid_t euid(); // timestamp startTime(); //返回进程开始时间 int clockTicksPerSecond(); int pageSize(); bool isDebugBuild(); string hostname(); //主机名 string procname(); string procname(const string& stat); //自己改一下 //read /proc/self/status string procStatus(); //进程状态 //read /proc/self/stat string procStat(); //read /proc/self/task/stat string threadStat(); //线程状态 //readlink /proc/self/exe string exePath(); int openedFiles(); //进程打开的文件数目 int maxOpenFiles(); //进程最多打开的文件数目 struct CpuTime { double userSeconds; double systemSeconds; CpuTime():userSeconds(0.0),systemSeconds(0.0){} double total() const {return userSeconds+systemSeconds;} }; CpuTime cpuTime(); //CPU时间信息 int numThreads(); //进程中的线程数目 std::vector<pid_t> threads(); //各个线程ID }//namespace processinfo }//namespace mymuduo #endif // PROCESSINFO_H
源文件:
#include "processinfo.h" #include"base/currentthread.h" #include"base/fileutil.h" #include<algorithm> #include<assert.h> #include<dirent.h> #include<pwd.h> #include<stdio.h> #include<unistd.h> #include<sys/resource.h> #include<sys/times.h> namespace mymuduo { namespace detail { //__thread 声明的全局变量每个线程都拥有一份,相互独立 //这里表示一个线程打开的文件数目 __thread int t_numOpenedFiles=0; //dirent.h是POSIX.1标准定义的unix类目录操作的头文件, //包含了许多UNIX系统服务的函数原型,例如opendir函数、readdir函数. int fdDirFilter(const struct dirent* d) { //如果dirent.d_name[0]不为空,说明有文件 if(::isdigit(d->d_name[0])) ++t_numOpenedFiles; return 0; } __thread std::vector<pid_t>* t_pids=NULL; //把每个线程的ID都存入到t_pids中 int taskDirFilter(const struct dirent* d) { if (::isdigit(d->d_name[0])) t_pids->push_back(atoi(d->d_name)); return 0; } int scanDir(const char* dirpath,int (*filter)(const struct dirent*)) { struct dirent** namelist=NULL; int result = ::scandir(dirpath,&namelist,filter,alphasort); assert(namelist==NULL); return result; } timestamp g_startTime = timestamp::now(); // assume those won't change during the life time of a process. int g_clockTicks = static_cast<int>(::sysconf(_SC_CLK_TCK)); int g_pageSize = static_cast<int>(::sysconf(_SC_PAGE_SIZE)); }//namespace detail }//namespace mymuduo using namespace mymuduo; using namespace mymuduo::detail; //进程ID pid_t processinfo::pid() { return ::getpid(); } //进程ID字符串 string processinfo::pidString() { char buf[32]; snprintf(buf, sizeof buf, "%d", pid()); return buf; } //userID uid_t processinfo::uid() { return ::getuid(); } //user名字 string processinfo::username() { struct passwd pwd; struct passwd* result = NULL; char buf[8192]; const char* name = "unknownuser"; getpwuid_r(uid(), &pwd, buf, sizeof buf, &result); if (result) { name = pwd.pw_name; } return name; } uid_t processinfo::euid() { return ::geteuid(); } //进程启动时间 timestamp processinfo::startTime() { return g_startTime; } int processinfo::clockTicksPerSecond() { return g_clockTicks; } int processinfo::pageSize() { return g_pageSize; } bool processinfo::isDebugBuild() { #ifdef NDEBUG return false; #else return true; #endif } string processinfo::hostname() { // HOST_NAME_MAX 64 // _POSIX_HOST_NAME_MAX 255 char buf[256]; if (::gethostname(buf, sizeof buf) == 0) { buf[sizeof(buf)-1] = '\0'; return buf; } else { return "unknownhost"; } } string processinfo::procname() { return procname(procStat()); } string processinfo::procname(const string& stat) { string name; size_t lp = stat.find('('); size_t rp = stat.rfind(')'); if (lp != string::npos && rp != string::npos && lp < rp) { name=std::string(stat.data()+lp+1,static_cast<int>(rp-lp-1)); } return name; } string processinfo::procStatus() { string result; fileutil::readFile(string("/proc/self/status"), 65536, &result); return result; } string processinfo::procStat() { string result; fileutil::readFile(string("/proc/self/stat"), 65536, &result); return result; } string processinfo::threadStat() { char buf[64]; snprintf(buf, sizeof buf, "/proc/self/task/%d/stat", currentthread::tid()); string result; fileutil::readFile(string(buf), 65536, &result); return result; } string processinfo::exePath() { string result; char buf[1024]; ssize_t n = ::readlink("/proc/self/exe", buf, sizeof buf); if (n > 0) { result.assign(buf, n); } return result; } int processinfo::openedFiles() { t_numOpenedFiles = 0; scanDir("/proc/self/fd", fdDirFilter); return t_numOpenedFiles; } int processinfo::maxOpenFiles() { struct rlimit rl; if (::getrlimit(RLIMIT_NOFILE, &rl)) { return openedFiles(); } else { return static_cast<int>(rl.rlim_cur); } } processinfo::CpuTime processinfo::cpuTime() { processinfo::CpuTime t; struct tms tms; if (::times(&tms) >= 0) { const double hz = static_cast<double>(clockTicksPerSecond()); t.userSeconds = static_cast<double>(tms.tms_utime) / hz; t.systemSeconds = static_cast<double>(tms.tms_stime) / hz; } return t; } int processinfo::numThreads() { int result = 0; string status = procStatus(); size_t pos = status.find("Threads:"); if (pos != string::npos) { result = ::atoi(status.c_str() + pos + 8); } return result; } std::vector<pid_t> processinfo::threads() { std::vector<pid_t> result; t_pids = &result; scanDir("/proc/self/task", taskDirFilter); t_pids = NULL; std::sort(result.begin(), result.end()); return result; }
测试(一些进程信息打印,测试代码跟作者的一样,没有自己改动):
#include"base/processinfo.h" #include<iostream> #define __STDC_FORMAT_MACROS #include <inttypes.h> using namespace std; namespace mymuduo{ namespace currentthread { void cacheTid() { } } } int main() { printf("pid = %d\n", mymuduo::processinfo::pid()); printf("uid = %d\n", mymuduo::processinfo::uid()); printf("euid = %d\n", mymuduo::processinfo::euid()); printf("start time = %s\n", mymuduo::processinfo::startTime().toFormattedString().c_str()); printf("hostname = %s\n", mymuduo::processinfo::hostname().c_str()); printf("opened files = %d\n", mymuduo::processinfo::openedFiles()); printf("threads = %zd\n", mymuduo::processinfo::threads().size()); printf("num threads = %d\n", mymuduo::processinfo::numThreads()); printf("status = %s\n", mymuduo::processinfo::procStatus().c_str()); std::cout<<"over...\n"; }
打印结果(一大堆看不懂的进程信息):
pid = 72087
uid = 1000
euid = 1000
start time = 2020年08月25日 星期2 02:24:26.1598293466
hostname = master
opened files = 4
threads = 1
num threads = 1
status = Name: mymuduo
Umask: 0002
State: R (running)
Tgid: 72087
Ngid: 0
Pid: 72087
PPid: 72086
TracerPid: 72090
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 64
Groups: 4 24 27 30 46 113 128 1000
NStgid: 72087
NSpid: 72087
NSpgid: 72087
NSsid: 72086
VmPeak: 15512 kB
VmSize: 15512 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 1808 kB
VmRSS: 1808 kB
RssAnon: 164 kB
RssFile: 1644 kB
RssShmem: 0 kB
VmData: 312 kB
VmStk: 132 kB
VmExe: 84 kB
VmLib: 4672 kB
VmPTE: 76 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
Threads: 1
SigQ: 0/11386
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000200000
SigCgt: 0000000180000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff
Cpus_allowed_list: 0-127
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 7
nonvoluntary_ctxt_switches: 1
over...