diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c index 43fd88d5..ee542b4d 100644 --- a/freebsd/FreeBSDProcess.c +++ b/freebsd/FreeBSDProcess.c @@ -12,6 +12,7 @@ in the source distribution for its full text. #include "CRT.h" #include +#include #include #include @@ -19,15 +20,22 @@ in the source distribution for its full text. typedef enum FreeBSDProcessFields { // Add platform-specific fields here, with ids >= 100 - LAST_PROCESSFIELD = 100, + JID = 100, + JAIL = 101, + LAST_PROCESSFIELD = 102, } FreeBSDProcessField; + typedef struct FreeBSDProcess_ { Process super; + int kernel; + int jid; + char* jname; } FreeBSDProcess; + #ifndef Process_isKernelThread -#define Process_isKernelThread(_process) (_process->pgrp == 0) +#define Process_isKernelThread(_process) (_process->kernel == 1) #endif #ifndef Process_isUserlandThread @@ -72,10 +80,13 @@ ProcessFieldData Process_fields[] = { [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, [TGID] = { .name = "TGID", .title = " TGID ", .description = "Thread group ID (i.e. process ID)", .flags = 0, }, + [JID] = { .name = "JID", .title = " JID ", .description = "Jail prison ID", .flags = 0, }, + [JAIL] = { .name = "JAIL", .title = "JAIL ", .description = "Jail prison name", .flags = 0, }, [LAST_PROCESSFIELD] = { .name = "*** report bug! ***", .title = NULL, .description = NULL, .flags = 0, }, }; ProcessPidColumn Process_pidColumns[] = { + { .id = JID, .label = "JID" }, { .id = PID, .label = "PID" }, { .id = PPID, .label = "PPID" }, { .id = TPGID, .label = "TPGID" }, @@ -95,16 +106,26 @@ FreeBSDProcess* FreeBSDProcess_new(Settings* settings) { void Process_delete(Object* cast) { FreeBSDProcess* this = (FreeBSDProcess*) cast; Process_done((Process*)cast); + free(this->jname); free(this); } void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField field) { - //FreeBSDProcess* fp = (FreeBSDProcess*) this; + FreeBSDProcess* fp = (FreeBSDProcess*) this; char buffer[256]; buffer[255] = '\0'; int attr = CRT_colors[DEFAULT_COLOR]; - //int n = sizeof(buffer) - 1; + int n = sizeof(buffer) - 1; switch (field) { // add FreeBSD-specific fields here + case JID: snprintf(buffer, n, Process_pidFormat, fp->jid); break; + case JAIL:{ + snprintf(buffer, n, "%-11s ", fp->jname); break; + if (buffer[11] != '\0') { + buffer[11] = ' '; + buffer[12] = '\0'; + } + break; + } default: Process_writeField(this, str, field); return; @@ -124,11 +145,20 @@ long FreeBSDProcess_compare(const void* v1, const void* v2) { } switch (settings->sortKey) { // add FreeBSD-specific fields here + case JID: + return (p1->jid - p2->jid); + case JAIL: + return strcmp(p1->jname ? p1->jname : "", p2->jname ? p2->jname : ""); default: return Process_compare(v1, v2); } } bool Process_isThread(Process* this) { - return (Process_isKernelThread(this)); + FreeBSDProcess* fp = (FreeBSDProcess*) this; + + if (fp->kernel == 1 ) + return 1; + else + return (Process_isUserlandThread(this)); } diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index cc51a7cd..54ae7607 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -20,6 +20,12 @@ in the source distribution for its full text. /*{ #include +#include +#include +#include + +#define JAIL_ERRMSGLEN 1024 +char jail_errmsg[JAIL_ERRMSGLEN]; typedef struct CPUData_ { unsigned long long int totalTime; @@ -58,13 +64,13 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui fpl->cpus[i].totalTime = 1; fpl->cpus[i].totalPeriod = 1; } - + size_t len; len = 4; sysctlnametomib("vm.stats.vm.v_wire_count", MIB_vm_stats_vm_v_wire_count, &len); len = 4; sysctlnametomib("vm.stats.vm.v_cache_count", MIB_vm_stats_vm_v_cache_count, &len); len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); - pageSizeKb = PAGE_SIZE_KB; - + pageSizeKb = PAGE_SIZE_KB; + fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL); assert(fpl->kd); @@ -74,14 +80,14 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui void ProcessList_delete(ProcessList* this) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this; if (fpl->kd) kvm_close(fpl->kd); - + ProcessList_done(this); free(this); } static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { const FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl; - + size_t len = sizeof(pl->totalMem); sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0); pl->totalMem /= 1024; @@ -90,7 +96,7 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { pl->freeMem = pl->totalMem - pl->usedMem; sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0); pl->cachedMem *= pageSizeKb; - + struct kvm_swap swap[16]; int nswap = kvm_getswapinfo(fpl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0); pl->totalSwap = 0; @@ -101,7 +107,7 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) { } pl->totalSwap *= pageSizeKb; pl->usedSwap *= pageSizeKb; - + pl->sharedMem = 0; // currently unused pl->buffersMem = 0; // not exposed to userspace } @@ -131,27 +137,75 @@ char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in 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]) + snprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s", strerror(errno)); + return NULL; + } else if (jid == kproc->ki_jid) { + jname = strdup(jnamebuf); + if (jname == NULL) + strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); + return jname; + } else { + return NULL; + } + } else { + jnamebuf[0]='-'; + jnamebuf[1]='\0'; + jname = strdup(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); - + int count = 0; struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_ALL, 0, &count); - + for (int i = 0; i < count; i++) { struct kinfo_proc* kproc = &kprocs[i]; - + bool preExisting = false; Process* proc = ProcessList_getProcess(this, kproc->ki_pid, &preExisting, (Process_New) FreeBSDProcess_new); FreeBSDProcess* fp = (FreeBSDProcess*) proc; - proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(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; @@ -163,6 +217,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { 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 (settings->updateProcessNames) { free(proc->comm); @@ -174,8 +229,12 @@ void ProcessList_goThroughEntries(ProcessList* this) { proc->m_resident = kproc->ki_rssize; // * pageSizeKb; proc->nlwp = kproc->ki_numthreads; proc->time = (kproc->ki_runtime + 5000) / 10000; + proc->priority = kproc->ki_pri.pri_level - PZERO; - if (kproc->ki_pri.pri_class == PRI_TIMESHARE) { + + if (strcmp("intr", kproc->ki_comm) == 0 && kproc->ki_flag & P_SYSTEM) { + proc->nice = 0; //@etosan: freebsd 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); @@ -183,6 +242,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { 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; @@ -194,10 +254,10 @@ void ProcessList_goThroughEntries(ProcessList* this) { default: proc->state = '?'; } - if (Process_isKernelThread(proc)) { + if (Process_isKernelThread(fp)) { this->kernelThreads++; } - + this->totalTasks++; if (proc->state == 'R') this->runningTasks++;