| 547 | } |
| 548 | |
| 549 | static bool readProcessStats(int pid, ProcessInfo* info) { |
| 550 | char path[64]; |
| 551 | snprintf(path, sizeof(path), "/proc/%d/stat", pid); |
| 552 | |
| 553 | int fd = open(path, O_RDONLY); |
| 554 | if (fd == -1) return false; |
| 555 | |
| 556 | char buffer[4096]; |
| 557 | size_t len = 0; |
| 558 | |
| 559 | ssize_t r; |
| 560 | while (r = read(fd, buffer + len, sizeof(buffer) - 1 - len)) { |
| 561 | if (r > 0) { |
| 562 | len += (size_t)r; |
| 563 | if (len == sizeof(buffer) - 1) break; |
| 564 | } else { |
| 565 | if (errno == EINTR) continue; |
| 566 | close(fd); |
| 567 | return false; |
| 568 | } |
| 569 | } |
| 570 | close(fd); |
| 571 | |
| 572 | if (len == 0) return false; |
| 573 | buffer[len] = '\0'; |
| 574 | |
| 575 | int parsed_pid, ppid; |
| 576 | char comm[COMM_LEN] = {0}; |
| 577 | char state; |
| 578 | u64 minflt, majflt, utime, stime; |
| 579 | u64 starttime; |
| 580 | u64 vsize, rss; |
| 581 | int threads; |
| 582 | int parsed = |
| 583 | sscanf(buffer, |
| 584 | "%d " /* 1 pid */ |
| 585 | "(%15[^)]) " /* 2 comm (read until ')') */ |
| 586 | "%c %d " /* 3 state, 4 ppid */ |
| 587 | "%*d %*d %*d %*d %*u " /* 5-9 skip */ |
| 588 | "%llu %*u %llu %*u " /* 10-13 minflt,-,majflt,- */ |
| 589 | "%llu %llu " /* 14-15 utime, stime */ |
| 590 | "%*d %*d %*d %*d " /* 16-19 skip */ |
| 591 | "%d " /* 20 threads */ |
| 592 | "%*d " /* 21 skip */ |
| 593 | "%llu " /* 22 starttime */ |
| 594 | "%llu " /* 23 vsize */ |
| 595 | "%llu", /* 24 rss */ |
| 596 | &parsed_pid, comm, &state, &ppid, &minflt, &majflt, &utime, &stime, &threads, &starttime, &vsize, &rss); |
| 597 | |
| 598 | if (parsed < 12) return false; |
| 599 | |
| 600 | memcpy(info->name, comm, COMM_LEN); |
| 601 | info->pid = parsed_pid; |
| 602 | info->ppid = ppid; |
| 603 | info->state = (unsigned char)state; |
| 604 | info->minor_faults = minflt; |
| 605 | info->major_faults = majflt; |
| 606 | info->cpu_user = (float)utime / OS::clock_ticks_per_sec; |