From 3449cf3356c129c91b7dd97d73548888abeb82eb Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Sun, 14 Jan 2018 19:17:52 -0200 Subject: [PATCH] FreeBSD: reorganize process reading loop --- freebsd/FreeBSDProcess.c | 205 ++++++++++++++++++++++++++++++----- freebsd/FreeBSDProcess.h | 35 +++--- freebsd/FreeBSDProcessList.c | 176 +----------------------------- freebsd/FreeBSDProcessList.h | 7 -- 4 files changed, 206 insertions(+), 217 deletions(-) diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c index f81fadf..3ce2c56 100644 --- a/freebsd/FreeBSDProcess.c +++ b/freebsd/FreeBSDProcess.c @@ -8,6 +8,7 @@ in the source distribution for its full text. #include "Process.h" #include "ProcessList.h" #include "FreeBSDProcess.h" +#include "FreeBSDProcessList.h" #include "Platform.h" #include "CRT.h" @@ -18,6 +19,15 @@ in the source distribution for its full text. /*{ +#include +#include +#include +#include +#include + +#define JAIL_ERRMSGLEN 1024 +char jail_errmsg[JAIL_ERRMSGLEN]; + typedef enum FreeBSDProcessFields { // Add platform-specific fields here, with ids >= 100 JID = 100, @@ -25,7 +35,6 @@ typedef enum FreeBSDProcessFields { LAST_PROCESSFIELD = 102, } FreeBSDProcessField; - typedef struct FreeBSDProcess_ { Process super; int kernel; @@ -33,25 +42,19 @@ typedef struct FreeBSDProcess_ { char* jname; } FreeBSDProcess; - -#ifndef Process_isKernelThread -#define Process_isKernelThread(_process) (_process->kernel == 1) -#endif - -#ifndef Process_isUserlandThread -#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) -#endif +typedef struct FreeBSDProcessScanData_ { + int pageSizeKb; + int kernelFScale; + struct kinfo_proc* kproc; +} FreeBSDProcessScanData; }*/ -ProcessClass FreeBSDProcess_class = { - .super = { - .extends = Class(Process), - .display = Process_display, - .delete = Process_delete, - .compare = FreeBSDProcess_compare - }, - .writeField = (Process_WriteField) FreeBSDProcess_writeField, +ObjectClass FreeBSDProcess_class = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = FreeBSDProcess_compare }; ProcessFieldData Process_fields[] = { @@ -96,11 +99,11 @@ ProcessPidColumn Process_pidColumns[] = { { .id = 0, .label = NULL }, }; -FreeBSDProcess* FreeBSDProcess_new(Settings* settings) { +Process* Process_new(Settings* settings) { FreeBSDProcess* this = xCalloc(1, sizeof(FreeBSDProcess)); Object_setClass(this, Class(FreeBSDProcess)); Process_init(&this->super, settings); - return this; + return (Process*) this; } void Process_delete(Object* cast) { @@ -110,7 +113,7 @@ void Process_delete(Object* cast) { free(this); } -void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField field) { +void Process_writeField(Process* this, RichString* str, ProcessField field) { FreeBSDProcess* fp = (FreeBSDProcess*) this; char buffer[256]; buffer[255] = '\0'; int attr = CRT_colors[DEFAULT_COLOR]; @@ -127,7 +130,7 @@ void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField fiel break; } default: - Process_writeField(this, str, field); + Process_defaultWriteField(this, str, field); return; } RichString_append(str, attr, buffer); @@ -154,11 +157,159 @@ long FreeBSDProcess_compare(const void* v1, const void* v2) { } } -bool Process_isThread(Process* this) { - FreeBSDProcess* fp = (FreeBSDProcess*) this; +char* FreeBSDProcess_readJailName(struct kinfo_proc* kproc) { + int jid; + struct iovec jiov[6]; + char* jname; + char jnamebuf[MAXHOSTNAMELEN]; + + if (kproc->ki_jid != 0 ){ + memset(jnamebuf, 0, sizeof(jnamebuf)); + *(const void **)&jiov[0].iov_base = "jid"; + jiov[0].iov_len = sizeof("jid"); + jiov[1].iov_base = &kproc->ki_jid; + jiov[1].iov_len = sizeof(kproc->ki_jid); + *(const void **)&jiov[2].iov_base = "name"; + jiov[2].iov_len = sizeof("name"); + jiov[3].iov_base = jnamebuf; + jiov[3].iov_len = sizeof(jnamebuf); + *(const void **)&jiov[4].iov_base = "errmsg"; + jiov[4].iov_len = sizeof("errmsg"); + jiov[5].iov_base = jail_errmsg; + jiov[5].iov_len = JAIL_ERRMSGLEN; + jail_errmsg[0] = 0; + jid = jail_get(jiov, 6, 0); + if (jid < 0) { + if (!jail_errmsg[0]) + xSnprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s", strerror(errno)); + return NULL; + } else if (jid == kproc->ki_jid) { + jname = xStrdup(jnamebuf); + if (jname == NULL) + strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); + return jname; + } else { + return NULL; + } + } else { + jnamebuf[0]='-'; + jnamebuf[1]='\0'; + jname = xStrdup(jnamebuf); + } + return jname; +} + +char* FreeBSDProcess_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) { + char** argv = kvm_getargv(kd, kproc, 0); + if (!argv) { + return xStrdup(kproc->ki_comm); + } + int len = 0; + for (int i = 0; argv[i]; i++) { + len += strlen(argv[i]) + 1; + } + char* comm = xMalloc(len); + char* at = comm; + *basenameEnd = 0; + for (int i = 0; argv[i]; i++) { + at = stpcpy(at, argv[i]); + if (!*basenameEnd) { + *basenameEnd = at - comm; + } + *at = ' '; + at++; + } + at--; + *at = '\0'; + return comm; +} - if (fp->kernel == 1 ) - return 1; - else - return (Process_isUserlandThread(this)); +bool Process_update(Process* proc, bool isNew, ProcessList* pl, ProcessScanData* psd) { + FreeBSDProcess* fp = (FreeBSDProcess*) proc; + FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; + FreeBSDProcessScanData* fpsd = (FreeBSDProcessScanData*) psd; + + struct kinfo_proc* kproc = ((FreeBSDProcessScanData*)psd)->kproc; + + if (isNew) { + fp->jid = kproc->ki_jid; + proc->pid = kproc->ki_pid; + if ( ! ((kproc->ki_pid == 0) || (kproc->ki_pid == 1) ) && kproc->ki_flag & P_SYSTEM) + fp->kernel = 1; + else + fp->kernel = 0; + proc->ppid = kproc->ki_ppid; + proc->tpgid = kproc->ki_tpgid; + proc->tgid = kproc->ki_pid; + proc->session = kproc->ki_sid; + proc->tty_nr = kproc->ki_tdev; + proc->pgrp = kproc->ki_pgid; + proc->st_uid = kproc->ki_uid; + proc->starttime_ctime = kproc->ki_start.tv_sec; + proc->comm = FreeBSDProcess_readProcessName(fpl->kd, kproc, &proc->basenameOffset); + fp->jname = FreeBSDProcess_readJailName(kproc); + proc->threadFlags = ((fp->kernel == 1) ? PROCESS_KERNEL_THREAD : 0) + | ((proc->pid != proc->tgid) ? PROCESS_USERLAND_THREAD : 0); + } else { + if(fp->jid != kproc->ki_jid) { + // process can enter jail anytime + fp->jid = kproc->ki_jid; + free(fp->jname); + fp->jname = FreeBSDProcess_readJailName(kproc); + } + if (proc->ppid != kproc->ki_ppid) { + // if there are reapers in the system, process can get reparented anytime + proc->ppid = kproc->ki_ppid; + } + if(proc->st_uid != kproc->ki_uid) { + // some processes change users (eg. to lower privs) + proc->st_uid = kproc->ki_uid; + } + if (proc->settings->updateProcessNames) { + free(proc->comm); + proc->comm = FreeBSDProcess_readProcessName(fpl->kd, kproc, &proc->basenameOffset); + } + } + + // from FreeBSD source /src/usr.bin/top/machine.c + proc->m_size = kproc->ki_size / 1024 / fpsd->pageSizeKb; + proc->m_resident = kproc->ki_rssize; + proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(pl->totalMem) * 100.0; + proc->nlwp = kproc->ki_numthreads; + proc->time = (kproc->ki_runtime + 5000) / 10000; + + proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)fpsd->kernelFScale); + proc->percent_mem = 100.0 * (proc->m_resident * PAGE_SIZE_KB) / (double)(pl->totalMem); + +// if (proc->percent_cpu > 0.1) { +// // system idle process should own all CPU time left regardless of CPU count +// if ( strcmp("idle", kproc->ki_comm) == 0 ) { +// isIdleProcess = true; +// } +// } + + proc->priority = kproc->ki_pri.pri_level - PZERO; + + if (strcmp("intr", kproc->ki_comm) == 0 && kproc->ki_flag & P_SYSTEM) { + proc->nice = 0; //@etosan: intr kernel process (not thread) has weird nice value + } else if (kproc->ki_pri.pri_class == PRI_TIMESHARE) { + proc->nice = kproc->ki_nice - NZERO; + } else if (PRI_IS_REALTIME(kproc->ki_pri.pri_class)) { + proc->nice = PRIO_MIN - 1 - (PRI_MAX_REALTIME - kproc->ki_pri.pri_level); + } else { + proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE; + } + + switch (kproc->ki_stat) { + case SIDL: proc->state = 'I'; break; + case SRUN: proc->state = 'R'; break; + case SSLEEP: proc->state = 'S'; break; + case SSTOP: proc->state = 'T'; break; + case SZOMB: proc->state = 'Z'; break; + case SWAIT: proc->state = 'D'; break; + case SLOCK: proc->state = 'L'; break; + default: proc->state = '?'; + } + + return proc; } diff --git a/freebsd/FreeBSDProcess.h b/freebsd/FreeBSDProcess.h index 23d298a..c1a1c99 100644 --- a/freebsd/FreeBSDProcess.h +++ b/freebsd/FreeBSDProcess.h @@ -10,6 +10,15 @@ in the source distribution for its full text. */ +#include +#include +#include +#include +#include + +#define JAIL_ERRMSGLEN 1024 +char jail_errmsg[JAIL_ERRMSGLEN]; + typedef enum FreeBSDProcessFields { // Add platform-specific fields here, with ids >= 100 JID = 100, @@ -17,7 +26,6 @@ typedef enum FreeBSDProcessFields { LAST_PROCESSFIELD = 102, } FreeBSDProcessField; - typedef struct FreeBSDProcess_ { Process super; int kernel; @@ -25,30 +33,31 @@ typedef struct FreeBSDProcess_ { char* jname; } FreeBSDProcess; +typedef struct FreeBSDProcessScanData_ { + int pageSizeKb; + int kernelFScale; + struct kinfo_proc* kproc; +} FreeBSDProcessScanData; -#ifndef Process_isKernelThread -#define Process_isKernelThread(_process) (_process->kernel == 1) -#endif -#ifndef Process_isUserlandThread -#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) -#endif - - -extern ProcessClass FreeBSDProcess_class; +extern ObjectClass FreeBSDProcess_class; extern ProcessFieldData Process_fields[]; extern ProcessPidColumn Process_pidColumns[]; -FreeBSDProcess* FreeBSDProcess_new(Settings* settings); +Process* Process_new(Settings* settings); void Process_delete(Object* cast); -void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField field); +void Process_writeField(Process* this, RichString* str, ProcessField field); long FreeBSDProcess_compare(const void* v1, const void* v2); -bool Process_isThread(Process* this); +char* FreeBSDProcess_readJailName(struct kinfo_proc* kproc); + +char* FreeBSDProcess_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd); + +bool Process_update(Process* proc, bool isNew, ProcessList* pl, ProcessScanData* psd); #endif diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 9fef324..85cdc5f 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -27,9 +27,6 @@ in the source distribution for its full text. #include #include -#define JAIL_ERRMSGLEN 1024 -char jail_errmsg[JAIL_ERRMSGLEN]; - typedef struct CPUData_ { double userPercent; @@ -349,183 +346,22 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->sharedMem = 0; // currently unused } -char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) { - char** argv = kvm_getargv(kd, kproc, 0); - if (!argv) { - return xStrdup(kproc->ki_comm); - } - int len = 0; - for (int i = 0; argv[i]; i++) { - len += strlen(argv[i]) + 1; - } - char* comm = xMalloc(len); - char* at = comm; - *basenameEnd = 0; - for (int i = 0; argv[i]; i++) { - at = stpcpy(at, argv[i]); - if (!*basenameEnd) { - *basenameEnd = at - comm; - } - *at = ' '; - at++; - } - at--; - *at = '\0'; - return comm; -} - -char* FreeBSDProcessList_readJailName(struct kinfo_proc* kproc) { - int jid; - struct iovec jiov[6]; - char* jname; - char jnamebuf[MAXHOSTNAMELEN]; - - if (kproc->ki_jid != 0 ){ - memset(jnamebuf, 0, sizeof(jnamebuf)); - *(const void **)&jiov[0].iov_base = "jid"; - jiov[0].iov_len = sizeof("jid"); - jiov[1].iov_base = &kproc->ki_jid; - jiov[1].iov_len = sizeof(kproc->ki_jid); - *(const void **)&jiov[2].iov_base = "name"; - jiov[2].iov_len = sizeof("name"); - jiov[3].iov_base = jnamebuf; - jiov[3].iov_len = sizeof(jnamebuf); - *(const void **)&jiov[4].iov_base = "errmsg"; - jiov[4].iov_len = sizeof("errmsg"); - jiov[5].iov_base = jail_errmsg; - jiov[5].iov_len = JAIL_ERRMSGLEN; - jail_errmsg[0] = 0; - jid = jail_get(jiov, 6, 0); - if (jid < 0) { - if (!jail_errmsg[0]) - xSnprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s", strerror(errno)); - return NULL; - } else if (jid == kproc->ki_jid) { - jname = xStrdup(jnamebuf); - if (jname == NULL) - strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); - return jname; - } else { - return NULL; - } - } else { - jnamebuf[0]='-'; - jnamebuf[1]='\0'; - jname = xStrdup(jnamebuf); - } - return jname; -} - void ProcessList_goThroughEntries(ProcessList* this) { FreeBSDProcessList* fpl = (FreeBSDProcessList*) this; - Settings* settings = this->settings; - bool hideKernelThreads = settings->hideKernelThreads; - bool hideUserlandThreads = settings->hideUserlandThreads; FreeBSDProcessList_scanMemoryInfo(this); FreeBSDProcessList_scanCPUTime(this); - int cpus = this->cpuCount; int count = 0; struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_PROC, 0, &count); + FreeBSDProcessScanData psd; + psd.pageSizeKb = pageSizeKb; + psd.kernelFScale = kernelFScale; + for (int i = 0; i < count; i++) { struct kinfo_proc* kproc = &kprocs[i]; - bool preExisting = false; - bool isIdleProcess = false; - Process* proc = ProcessList_getProcess(this, kproc->ki_pid, &preExisting, (Process_New) FreeBSDProcess_new); - FreeBSDProcess* fp = (FreeBSDProcess*) proc; - - proc->show = ! ((hideKernelThreads && Process_isKernelThread(fp)) || (hideUserlandThreads && Process_isUserlandThread(proc))); - - if (!preExisting) { - fp->jid = kproc->ki_jid; - proc->pid = kproc->ki_pid; - if ( ! ((kproc->ki_pid == 0) || (kproc->ki_pid == 1) ) && kproc->ki_flag & P_SYSTEM) - fp->kernel = 1; - else - fp->kernel = 0; - proc->ppid = kproc->ki_ppid; - proc->tpgid = kproc->ki_tpgid; - proc->tgid = kproc->ki_pid; - proc->session = kproc->ki_sid; - proc->tty_nr = kproc->ki_tdev; - proc->pgrp = kproc->ki_pgid; - proc->st_uid = kproc->ki_uid; - proc->starttime_ctime = kproc->ki_start.tv_sec; - proc->user = UsersTable_getRef(this->usersTable, proc->st_uid); - ProcessList_add((ProcessList*)this, proc); - proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset); - fp->jname = FreeBSDProcessList_readJailName(kproc); - } else { - if(fp->jid != kproc->ki_jid) { - // process can enter jail anytime - fp->jid = kproc->ki_jid; - free(fp->jname); - fp->jname = FreeBSDProcessList_readJailName(kproc); - } - if (proc->ppid != kproc->ki_ppid) { - // if there are reapers in the system, process can get reparented anytime - proc->ppid = kproc->ki_ppid; - } - if(proc->st_uid != kproc->ki_uid) { - // some processes change users (eg. to lower privs) - proc->st_uid = kproc->ki_uid; - proc->user = UsersTable_getRef(this->usersTable, proc->st_uid); - } - if (settings->updateProcessNames) { - free(proc->comm); - proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset); - } - } - - // from FreeBSD source /src/usr.bin/top/machine.c - proc->m_size = kproc->ki_size / 1024 / pageSizeKb; - proc->m_resident = kproc->ki_rssize; - proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0; - proc->nlwp = kproc->ki_numthreads; - proc->time = (kproc->ki_runtime + 5000) / 10000; - - proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale); - proc->percent_mem = 100.0 * (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem); - - if (proc->percent_cpu > 0.1) { - // system idle process should own all CPU time left regardless of CPU count - if ( strcmp("idle", kproc->ki_comm) == 0 ) { - isIdleProcess = true; - } - } - - proc->priority = kproc->ki_pri.pri_level - PZERO; - - if (strcmp("intr", kproc->ki_comm) == 0 && kproc->ki_flag & P_SYSTEM) { - proc->nice = 0; //@etosan: intr kernel process (not thread) has weird nice value - } else if (kproc->ki_pri.pri_class == PRI_TIMESHARE) { - proc->nice = kproc->ki_nice - NZERO; - } else if (PRI_IS_REALTIME(kproc->ki_pri.pri_class)) { - proc->nice = PRIO_MIN - 1 - (PRI_MAX_REALTIME - kproc->ki_pri.pri_level); - } else { - proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE; - } - - switch (kproc->ki_stat) { - case SIDL: proc->state = 'I'; break; - case SRUN: proc->state = 'R'; break; - case SSLEEP: proc->state = 'S'; break; - case SSTOP: proc->state = 'T'; break; - case SZOMB: proc->state = 'Z'; break; - case SWAIT: proc->state = 'D'; break; - case SLOCK: proc->state = 'L'; break; - default: proc->state = '?'; - } - - if (Process_isKernelThread(fp)) { - this->kernelThreads++; - } - - this->totalTasks++; - if (proc->state == 'R') - this->runningTasks++; - proc->updated = true; + psd.kproc = kproc; + ProcessList_scanProcess(this, kproc->ki_pid, (ProcessScanData*) &psd); } } diff --git a/freebsd/FreeBSDProcessList.h b/freebsd/FreeBSDProcessList.h index af343fb..b7cc3b3 100644 --- a/freebsd/FreeBSDProcessList.h +++ b/freebsd/FreeBSDProcessList.h @@ -16,9 +16,6 @@ in the source distribution for its full text. #include #include -#define JAIL_ERRMSGLEN 1024 -char jail_errmsg[JAIL_ERRMSGLEN]; - typedef struct CPUData_ { double userPercent; @@ -59,10 +56,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui void ProcessList_delete(ProcessList* this); -char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd); - -char* FreeBSDProcessList_readJailName(struct kinfo_proc* kproc); - void ProcessList_goThroughEntries(ProcessList* this); #endif -- GitLab