File indexing completed on 2024-04-28 05:31:39
0001 /* 0002 SPDX-FileCopyrightText: 2007 Manolo Valdes <nolis71cu@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "process.h" 0008 #include "processes_local_p.h" 0009 0010 #include <KLocalizedString> 0011 0012 #include <QSet> 0013 0014 #include <sys/param.h> 0015 #include <sys/resource.h> 0016 #include <sys/sysctl.h> 0017 #include <sys/types.h> 0018 #include <sys/user.h> 0019 #if defined(__DragonFly__) 0020 #include <err.h> 0021 #include <sys/resourcevar.h> 0022 #endif 0023 #include <signal.h> 0024 #include <stdlib.h> 0025 #include <unistd.h> 0026 0027 namespace KSysGuard 0028 { 0029 class ProcessesLocal::Private 0030 { 0031 public: 0032 Private() 0033 { 0034 ; 0035 } 0036 ~Private() 0037 { 0038 ; 0039 } 0040 inline bool readProc(long pid, struct kinfo_proc *p); 0041 inline void readProcStatus(struct kinfo_proc *p, Process *process); 0042 inline void readProcStat(struct kinfo_proc *p, Process *process); 0043 inline void readProcStatm(struct kinfo_proc *p, Process *process); 0044 inline bool readProcCmdline(long pid, Process *process); 0045 }; 0046 0047 bool ProcessesLocal::Private::readProc(long pid, struct kinfo_proc *p) 0048 { 0049 int mib[4]; 0050 size_t len; 0051 0052 mib[0] = CTL_KERN; 0053 mib[1] = KERN_PROC; 0054 mib[2] = KERN_PROC_PID; 0055 mib[3] = pid; 0056 0057 len = sizeof(struct kinfo_proc); 0058 if (sysctl(mib, 4, p, &len, NULL, 0) == -1 || !len) { 0059 return false; 0060 } 0061 return true; 0062 } 0063 0064 void ProcessesLocal::Private::readProcStatus(struct kinfo_proc *p, Process *process) 0065 { 0066 process->setUid(0); 0067 process->setGid(0); 0068 process->setTracerpid(-1); 0069 0070 #if defined(__FreeBSD__) && __FreeBSD_version >= 500015 0071 process->setUid(p->ki_uid); 0072 process->setGid(p->ki_pgid); 0073 process->setName(QString(p->ki_comm ? p->ki_comm : "????")); 0074 #elif defined(__DragonFly__) && __DragonFly_version >= 190000 0075 process->setUid(p->kp_uid); 0076 process->setGid(p->kp_pgid); 0077 process->setName(QString(p->kp_comm ? p->kp_comm : "????")); 0078 #else 0079 process->setUid(p->kp_eproc.e_ucred.cr_uid); 0080 process->setGid(p->kp_eproc.e_pgid); 0081 #endif 0082 } 0083 0084 void ProcessesLocal::Private::readProcStat(struct kinfo_proc *p, Process *ps) 0085 { 0086 int status; 0087 struct rusage pru; 0088 #if defined(__FreeBSD__) && __FreeBSD_version >= 500015 0089 ps->setUserTime(p->ki_runtime / 10000); 0090 ps->setNiceLevel(p->ki_nice); 0091 ps->setVmSize(p->ki_size); 0092 ps->setVmRSS(p->ki_rssize * getpagesize()); 0093 status = p->ki_stat; 0094 #elif defined(__DragonFly__) && __DragonFly_version >= 190000 0095 if (!getrusage(p->kp_pid, &pru)) { 0096 errx(1, "failed to get rusage info"); 0097 } 0098 ps->setUserTime(pru.ru_utime.tv_usec / 1000); /*p_runtime / 1000*/ 0099 ps->setNiceLevel(p->kp_nice); 0100 ps->setVmSize(p->kp_vm_map_size); 0101 ps->setVmRSS(p->kp_vm_rssize * getpagesize()); 0102 status = p->kp_stat; 0103 #else 0104 ps->setUserTime(p->kp_proc.p_rtime.tv_sec * 100 + p->kp_proc.p_rtime.tv_usec / 100); 0105 ps->setNiceLevel(p->kp_proc.p_nice); 0106 ps->setVmSize(p->kp_eproc.e_vm.vm_map.size); 0107 ps->setVmRSS(p->kp_eproc.e_vm.vm_rssize * getpagesize()); 0108 status = p->kp_proc.p_stat; 0109 #endif 0110 ps->setSysTime(0); 0111 0112 // "idle","run","sleep","stop","zombie" 0113 switch (status) { 0114 case '0': 0115 ps->setStatus(Process::DiskSleep); 0116 break; 0117 case '1': 0118 ps->setStatus(Process::Running); 0119 break; 0120 case '2': 0121 ps->setStatus(Process::Sleeping); 0122 break; 0123 case '3': 0124 ps->setStatus(Process::Stopped); 0125 break; 0126 case '4': 0127 ps->setStatus(Process::Zombie); 0128 break; 0129 default: 0130 ps->setStatus(Process::OtherStatus); 0131 break; 0132 } 0133 } 0134 0135 void ProcessesLocal::Private::readProcStatm(struct kinfo_proc *p, Process *process) 0136 { 0137 // TODO 0138 0139 // unsigned long shared; 0140 // process->setVmURSS(process->vmRSS - (shared * sysconf(_SC_PAGESIZE) / 1024)); 0141 } 0142 0143 bool ProcessesLocal::Private::readProcCmdline(long pid, Process *process) 0144 { 0145 int mib[4]; 0146 struct kinfo_proc p; 0147 size_t buflen = 256; 0148 char buf[256]; 0149 0150 mib[0] = CTL_KERN; 0151 mib[1] = KERN_PROC; 0152 mib[2] = KERN_PROC_ARGS; 0153 mib[3] = pid; 0154 0155 if (sysctl(mib, 4, buf, &buflen, NULL, 0) == -1 || !buflen) { 0156 return false; 0157 } 0158 QString command = QString(buf); 0159 0160 // cmdline separates parameters with the NULL character 0161 command.replace('\0', ' '); 0162 process->setCommand(command.trimmed()); 0163 0164 return true; 0165 } 0166 0167 ProcessesLocal::ProcessesLocal() 0168 : d(new Private()) 0169 { 0170 } 0171 0172 long ProcessesLocal::getParentPid(long pid) 0173 { 0174 Q_ASSERT(pid != 0); 0175 long long ppid = -1; 0176 struct kinfo_proc p; 0177 if (d->readProc(pid, &p)) { 0178 #if defined(__FreeBSD__) && __FreeBSD_version >= 500015 0179 ppid = p.ki_ppid; 0180 #elif defined(__DragonFly__) && __DragonFly_version >= 190000 0181 ppid = p.kp_ppid; 0182 #else 0183 ppid = p.kp_eproc.e_ppid; 0184 #endif 0185 } 0186 return ppid; 0187 } 0188 0189 bool ProcessesLocal::updateProcessInfo(long pid, Process *process) 0190 { 0191 struct kinfo_proc p; 0192 if (!d->readProc(pid, &p)) { 0193 return false; 0194 } 0195 d->readProcStat(&p, process); 0196 d->readProcStatus(&p, process); 0197 d->readProcStatm(&p, process); 0198 if (!d->readProcCmdline(pid, process)) { 0199 return false; 0200 } 0201 0202 return true; 0203 } 0204 0205 QSet<long> ProcessesLocal::getAllPids() 0206 { 0207 QSet<long> pids; 0208 int mib[3]; 0209 size_t len; 0210 size_t num; 0211 struct kinfo_proc *p; 0212 0213 mib[0] = CTL_KERN; 0214 mib[1] = KERN_PROC; 0215 mib[2] = KERN_PROC_ALL; 0216 sysctl(mib, 3, NULL, &len, NULL, 0); 0217 p = (kinfo_proc *)malloc(len); 0218 sysctl(mib, 3, p, &len, NULL, 0); 0219 0220 for (num = 0; num < len / sizeof(struct kinfo_proc); num++) { 0221 #if defined(__FreeBSD__) && __FreeBSD_version >= 500015 0222 pids.insert(p[num].ki_pid); 0223 #elif defined(__DragonFly__) && __DragonFly_version >= 190000 0224 pids.insert(p[num].kp_pid); 0225 #else 0226 pids.insert(p[num].kp_proc.p_pid); 0227 #endif 0228 } 0229 free(p); 0230 return pids; 0231 } 0232 0233 Processes::Error ProcessesLocal::sendSignal(long pid, int sig) 0234 { 0235 if (kill((pid_t)pid, sig)) { 0236 // Kill failed 0237 return Processes::Unknown; 0238 } 0239 return Processes::NoError; 0240 } 0241 0242 Processes::Error ProcessesLocal::setNiceness(long pid, int priority) 0243 { 0244 if (setpriority(PRIO_PROCESS, pid, priority)) { 0245 // set niceness failed 0246 return Processes::Unknown; 0247 } 0248 return Processes::NoError; 0249 } 0250 0251 Processes::Error ProcessesLocal::setScheduler(long pid, int priorityClass, int priority) 0252 { 0253 if (priorityClass == KSysGuard::Process::Other || priorityClass == KSysGuard::Process::Batch) { 0254 priority = 0; 0255 } 0256 if (pid <= 0) { 0257 return Processes::InvalidPid; // check the parameters 0258 } 0259 return Processes::NotSupported; 0260 } 0261 0262 Processes::Error ProcessesLocal::setIoNiceness(long pid, int priorityClass, int priority) 0263 { 0264 return Processes::NotSupported; // Not yet supported 0265 } 0266 0267 bool ProcessesLocal::supportsIoNiceness() 0268 { 0269 return false; 0270 } 0271 0272 long long ProcessesLocal::totalPhysicalMemory() 0273 { 0274 static int physmem_mib[] = {CTL_HW, HW_PHYSMEM}; 0275 /* get the page size with "getpagesize" and calculate pageshift from 0276 * it */ 0277 int pagesize = ::getpagesize(); 0278 int pageshift = 0; 0279 while (pagesize > 1) { 0280 pageshift++; 0281 pagesize >>= 1; 0282 } 0283 size_t Total = 0; 0284 size_t size = sizeof(Total); 0285 sysctl(physmem_mib, 2, &Total, &size, NULL, 0); 0286 return Total /= 1024; 0287 } 0288 0289 long int KSysGuard::ProcessesLocal::numberProcessorCores() 0290 { 0291 int mib[2]; 0292 int ncpu; 0293 size_t len; 0294 0295 mib[0] = CTL_HW; 0296 mib[1] = HW_NCPU; 0297 len = sizeof(ncpu); 0298 0299 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1 || !len) { 0300 return 1; 0301 } 0302 return len; 0303 } 0304 ProcessesLocal::~ProcessesLocal() 0305 { 0306 delete d; 0307 } 0308 0309 }