sysinfo/common/system.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::collections::{HashMap, HashSet};
4use std::ffi::{OsStr, OsString};
5use std::fmt;
6use std::path::Path;
7use std::process::ExitStatus;
8use std::str::FromStr;
9
10use crate::common::impl_get_set::impl_get_set;
11use crate::common::DiskUsage;
12use crate::{CpuInner, Gid, MotherboardInner, ProcessInner, ProductInner, SystemInner, Uid};
13
14/// Type containing system's information such as processes, memory and CPU.
15///
16/// ⚠️ On newer Android versions, there are restrictions on which system information
17/// a non-system application has access to. So CPU information might not be available.
18///
19/// ```
20/// use sysinfo::System;
21///
22/// if sysinfo::IS_SUPPORTED_SYSTEM {
23/// println!("System: {:?}", System::new_all());
24/// } else {
25/// println!("This OS isn't supported (yet?).");
26/// }
27/// ```
28pub struct System {
29 pub(crate) inner: SystemInner,
30}
31
32impl Default for System {
33 fn default() -> System {
34 System::new()
35 }
36}
37
38impl System {
39 /// Creates a new [`System`] instance with nothing loaded.
40 ///
41 /// Use one of the refresh methods (like [`refresh_all`]) to update its internal information.
42 ///
43 /// [`System`]: crate::System
44 /// [`refresh_all`]: #method.refresh_all
45 ///
46 /// ```no_run
47 /// use sysinfo::System;
48 ///
49 /// let s = System::new();
50 /// ```
51 pub fn new() -> Self {
52 Self::new_with_specifics(RefreshKind::nothing())
53 }
54
55 /// Creates a new [`System`] instance with everything loaded.
56 ///
57 /// It is an equivalent of [`System::new_with_specifics`]`(`[`RefreshKind::everything`]`())`.
58 ///
59 /// [`System`]: crate::System
60 ///
61 /// ```no_run
62 /// use sysinfo::System;
63 ///
64 /// let s = System::new_all();
65 /// ```
66 pub fn new_all() -> Self {
67 Self::new_with_specifics(RefreshKind::everything())
68 }
69
70 /// Creates a new [`System`] instance and refresh the data corresponding to the
71 /// given [`RefreshKind`].
72 ///
73 /// [`System`]: crate::System
74 ///
75 /// ```
76 /// use sysinfo::{ProcessRefreshKind, RefreshKind, System};
77 ///
78 /// // We want to only refresh processes.
79 /// let mut system = System::new_with_specifics(
80 /// RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()),
81 /// );
82 ///
83 /// # if sysinfo::IS_SUPPORTED_SYSTEM && !cfg!(feature = "apple-sandbox") {
84 /// assert!(!system.processes().is_empty());
85 /// # }
86 /// ```
87 pub fn new_with_specifics(refreshes: RefreshKind) -> Self {
88 let mut s = Self {
89 inner: SystemInner::new(),
90 };
91 s.refresh_specifics(refreshes);
92 s
93 }
94
95 /// Refreshes according to the given [`RefreshKind`]. It calls the corresponding
96 /// "refresh_" methods.
97 ///
98 /// It will remove dead processes if [`RefreshKind::processes`] returns `Some`.
99 /// If you want to keep dead processes, use [`System::refresh_processes_specifics`]
100 /// directly.
101 ///
102 /// ```
103 /// use sysinfo::{ProcessRefreshKind, RefreshKind, System};
104 ///
105 /// let mut s = System::new_all();
106 ///
107 /// // Let's just update processes:
108 /// s.refresh_specifics(
109 /// RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()),
110 /// );
111 /// ```
112 pub fn refresh_specifics(&mut self, refreshes: RefreshKind) {
113 if let Some(kind) = refreshes.memory() {
114 self.refresh_memory_specifics(kind);
115 }
116 if let Some(kind) = refreshes.cpu() {
117 self.refresh_cpu_specifics(kind);
118 }
119 if let Some(kind) = refreshes.processes() {
120 self.refresh_processes_specifics(ProcessesToUpdate::All, true, kind);
121 }
122 }
123
124 /// Refreshes all system and processes information.
125 ///
126 /// It is the same as calling `system.refresh_specifics(RefreshKind::everything())`.
127 ///
128 /// Don't forget to take a look at [`ProcessRefreshKind::everything`] method to see what it
129 /// will update for processes more in details.
130 ///
131 /// It will remove dead processes. If you want to keep dead processes, use
132 /// [`System::refresh_processes_specifics`] directly.
133 ///
134 /// ```no_run
135 /// use sysinfo::System;
136 ///
137 /// let mut s = System::new();
138 /// s.refresh_all();
139 /// ```
140 pub fn refresh_all(&mut self) {
141 self.refresh_specifics(RefreshKind::everything());
142 }
143
144 /// Refreshes RAM and SWAP usage.
145 ///
146 /// It is the same as calling `system.refresh_memory_specifics(MemoryRefreshKind::everything())`.
147 ///
148 /// If you don't want to refresh both, take a look at [`System::refresh_memory_specifics`].
149 ///
150 /// ```no_run
151 /// use sysinfo::System;
152 ///
153 /// let mut s = System::new();
154 /// s.refresh_memory();
155 /// ```
156 pub fn refresh_memory(&mut self) {
157 self.refresh_memory_specifics(MemoryRefreshKind::everything())
158 }
159
160 /// Refreshes system memory specific information.
161 ///
162 /// ```no_run
163 /// use sysinfo::{MemoryRefreshKind, System};
164 ///
165 /// let mut s = System::new();
166 /// s.refresh_memory_specifics(MemoryRefreshKind::nothing().with_ram());
167 /// ```
168 pub fn refresh_memory_specifics(&mut self, refresh_kind: MemoryRefreshKind) {
169 self.inner.refresh_memory_specifics(refresh_kind)
170 }
171
172 /// Refreshes CPUs usage.
173 ///
174 /// ⚠️ Please note that the result will very likely be inaccurate at the first call.
175 /// You need to call this method at least twice (with a bit of time between each call, like
176 /// 200 ms, take a look at [`MINIMUM_CPU_UPDATE_INTERVAL`] for more information)
177 /// to get accurate value as it uses previous results to compute the next value.
178 ///
179 /// Calling this method is the same as calling
180 /// `system.refresh_cpu_specifics(CpuRefreshKind::nothing().with_cpu_usage())`.
181 ///
182 /// ```no_run
183 /// use sysinfo::System;
184 ///
185 /// let mut s = System::new_all();
186 /// // Wait a bit because CPU usage is based on diff.
187 /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
188 /// // Refresh CPUs again.
189 /// s.refresh_cpu_usage();
190 /// ```
191 ///
192 /// [`MINIMUM_CPU_UPDATE_INTERVAL`]: crate::MINIMUM_CPU_UPDATE_INTERVAL
193 pub fn refresh_cpu_usage(&mut self) {
194 self.refresh_cpu_specifics(CpuRefreshKind::nothing().with_cpu_usage())
195 }
196
197 /// Refreshes CPUs frequency information.
198 ///
199 /// Calling this method is the same as calling
200 /// `system.refresh_cpu_specifics(CpuRefreshKind::nothing().with_frequency())`.
201 ///
202 /// ```no_run
203 /// use sysinfo::System;
204 ///
205 /// let mut s = System::new_all();
206 /// s.refresh_cpu_frequency();
207 /// ```
208 pub fn refresh_cpu_frequency(&mut self) {
209 self.refresh_cpu_specifics(CpuRefreshKind::nothing().with_frequency())
210 }
211
212 /// Refreshes the list of CPU.
213 ///
214 /// Normally, this should almost never be needed as it's pretty rare for a computer
215 /// to add a CPU while running, but it's possible on some computers which shutdown
216 /// CPU if the load is low enough.
217 ///
218 /// The `refresh_kind` argument tells what information you want to be retrieved
219 /// for each CPU.
220 ///
221 /// ```no_run
222 /// use sysinfo::{CpuRefreshKind, System};
223 ///
224 /// let mut s = System::new_all();
225 /// // We already have the list of CPU filled, but we want to recompute it
226 /// // in case new CPUs were added.
227 /// s.refresh_cpu_list(CpuRefreshKind::everything());
228 /// ```
229 pub fn refresh_cpu_list(&mut self, refresh_kind: CpuRefreshKind) {
230 self.inner.refresh_cpu_list(refresh_kind);
231 }
232
233 /// Refreshes all information related to CPUs information.
234 ///
235 /// If you only want the CPU usage, use [`System::refresh_cpu_usage`] instead.
236 ///
237 /// ⚠️ Please note that the result will be inaccurate at the first call.
238 /// You need to call this method at least twice (with a bit of time between each call, like
239 /// 200 ms, take a look at [`MINIMUM_CPU_UPDATE_INTERVAL`] for more information)
240 /// to get accurate value as it uses previous results to compute the next value.
241 ///
242 /// Calling this method is the same as calling
243 /// `system.refresh_cpu_specifics(CpuRefreshKind::everything())`.
244 ///
245 /// ```no_run
246 /// use sysinfo::System;
247 ///
248 /// let mut s = System::new_all();
249 /// s.refresh_cpu_all();
250 /// ```
251 ///
252 /// [`MINIMUM_CPU_UPDATE_INTERVAL`]: crate::MINIMUM_CPU_UPDATE_INTERVAL
253 pub fn refresh_cpu_all(&mut self) {
254 self.refresh_cpu_specifics(CpuRefreshKind::everything())
255 }
256
257 /// Refreshes CPUs specific information.
258 ///
259 /// ```no_run
260 /// use sysinfo::{System, CpuRefreshKind};
261 ///
262 /// let mut s = System::new_all();
263 /// s.refresh_cpu_specifics(CpuRefreshKind::everything());
264 /// ```
265 pub fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind) {
266 self.inner.refresh_cpu_specifics(refresh_kind)
267 }
268
269 /// Gets all processes and updates their information, along with all the tasks each process has.
270 ///
271 /// It does the same as:
272 ///
273 /// ```no_run
274 /// # use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System, UpdateKind};
275 /// # let mut system = System::new();
276 /// system.refresh_processes_specifics(
277 /// ProcessesToUpdate::All,
278 /// true,
279 /// ProcessRefreshKind::nothing()
280 /// .with_memory()
281 /// .with_cpu()
282 /// .with_disk_usage()
283 /// .with_exe(UpdateKind::OnlyIfNotSet)
284 /// );
285 /// ```
286 ///
287 /// ⚠️ `remove_dead_processes` works as follows: if an updated process is dead, then it is
288 /// removed. So if you refresh pids 1, 2 and 3. If 2 and 7 are dead, only 2 will be removed
289 /// since 7 is not part of the update.
290 ///
291 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
292 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
293 ///
294 /// ⚠️ On Linux, if you dont need the tasks of each process, you can use
295 /// `refresh_processes_specifics` with `ProcessRefreshKind::everything().without_tasks()`.
296 /// Refreshesing all processes and their tasks can be quite expensive. For more information
297 /// see [`ProcessRefreshKind`].
298 ///
299 /// Example:
300 ///
301 /// ```no_run
302 /// use sysinfo::{ProcessesToUpdate, System};
303 ///
304 /// let mut s = System::new_all();
305 /// s.refresh_processes(ProcessesToUpdate::All, true);
306 /// ```
307 pub fn refresh_processes(
308 &mut self,
309 processes_to_update: ProcessesToUpdate<'_>,
310 remove_dead_processes: bool,
311 ) -> usize {
312 self.refresh_processes_specifics(
313 processes_to_update,
314 remove_dead_processes,
315 ProcessRefreshKind::nothing()
316 .with_memory()
317 .with_cpu()
318 .with_disk_usage()
319 .with_exe(UpdateKind::OnlyIfNotSet)
320 .with_tasks(),
321 )
322 }
323
324 /// Gets all processes and updates the specified information.
325 ///
326 /// Returns the number of updated processes.
327 ///
328 /// ⚠️ `remove_dead_processes` works as follows: if an updated process is dead, then it is
329 /// removed. So if you refresh pids 1, 2 and 3. If 2 and 7 are dead, only 2 will be removed
330 /// since 7 is not part of the update.
331 ///
332 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
333 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
334 ///
335 /// ```no_run
336 /// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System};
337 ///
338 /// let mut s = System::new_all();
339 /// s.refresh_processes_specifics(
340 /// ProcessesToUpdate::All,
341 /// true,
342 /// ProcessRefreshKind::everything(),
343 /// );
344 /// ```
345 pub fn refresh_processes_specifics(
346 &mut self,
347 processes_to_update: ProcessesToUpdate<'_>,
348 remove_dead_processes: bool,
349 refresh_kind: ProcessRefreshKind,
350 ) -> usize {
351 fn update_and_remove(pid: &Pid, processes: &mut HashMap<Pid, Process>) {
352 let updated = if let Some(proc) = processes.get_mut(pid) {
353 proc.inner.switch_updated()
354 } else {
355 return;
356 };
357 if !updated {
358 processes.remove(pid);
359 }
360 }
361 fn update(pid: &Pid, processes: &mut HashMap<Pid, Process>) {
362 if let Some(proc) = processes.get_mut(pid) {
363 if !proc.inner.switch_updated() {
364 proc.inner.set_nonexistent();
365 }
366 }
367 }
368
369 let nb_updated = self
370 .inner
371 .refresh_processes_specifics(processes_to_update, refresh_kind);
372 let processes = self.inner.processes_mut();
373 match processes_to_update {
374 ProcessesToUpdate::All => {
375 if remove_dead_processes {
376 processes.retain(|_, v| v.inner.switch_updated());
377 } else {
378 for proc in processes.values_mut() {
379 proc.inner.switch_updated();
380 }
381 }
382 }
383 ProcessesToUpdate::Some(pids) => {
384 let call = if remove_dead_processes {
385 update_and_remove
386 } else {
387 update
388 };
389 for pid in pids {
390 call(pid, processes);
391 }
392 }
393 }
394 nb_updated
395 }
396
397 /// Returns the process list.
398 ///
399 /// ```no_run
400 /// use sysinfo::System;
401 ///
402 /// let s = System::new_all();
403 /// for (pid, process) in s.processes() {
404 /// println!("{} {:?}", pid, process.name());
405 /// }
406 /// ```
407 pub fn processes(&self) -> &HashMap<Pid, Process> {
408 self.inner.processes()
409 }
410
411 /// Returns the process corresponding to the given `pid` or `None` if no such process exists.
412 ///
413 /// ```no_run
414 /// use sysinfo::{Pid, System};
415 ///
416 /// let s = System::new_all();
417 /// if let Some(process) = s.process(Pid::from(1337)) {
418 /// println!("{:?}", process.name());
419 /// }
420 /// ```
421 pub fn process(&self, pid: Pid) -> Option<&Process> {
422 self.inner.process(pid)
423 }
424
425 /// Returns an iterator of process containing the given `name`.
426 ///
427 /// If you want only the processes with exactly the given `name`, take a look at
428 /// [`System::processes_by_exact_name`].
429 ///
430 /// **⚠️ Important ⚠️**
431 ///
432 /// On **Linux**, there are two things to know about processes' name:
433 /// 1. It is limited to 15 characters.
434 /// 2. It is not always the exe name.
435 ///
436 /// ```no_run
437 /// use sysinfo::System;
438 ///
439 /// let s = System::new_all();
440 /// for process in s.processes_by_name("htop".as_ref()) {
441 /// println!("{} {:?}", process.pid(), process.name());
442 /// }
443 /// ```
444 pub fn processes_by_name<'a: 'b, 'b>(
445 &'a self,
446 name: &'b OsStr,
447 ) -> impl Iterator<Item = &'a Process> + 'b {
448 let finder = memchr::memmem::Finder::new(name.as_encoded_bytes());
449 self.processes()
450 .values()
451 .filter(move |val: &&Process| finder.find(val.name().as_encoded_bytes()).is_some())
452 }
453
454 /// Returns an iterator of processes with exactly the given `name`.
455 ///
456 /// If you instead want the processes containing `name`, take a look at
457 /// [`System::processes_by_name`].
458 ///
459 /// **⚠️ Important ⚠️**
460 ///
461 /// On **Linux**, there are two things to know about processes' name:
462 /// 1. It is limited to 15 characters.
463 /// 2. It is not always the exe name.
464 ///
465 /// ```no_run
466 /// use sysinfo::System;
467 ///
468 /// let s = System::new_all();
469 /// for process in s.processes_by_exact_name("htop".as_ref()) {
470 /// println!("{} {:?}", process.pid(), process.name());
471 /// }
472 /// ```
473 pub fn processes_by_exact_name<'a: 'b, 'b>(
474 &'a self,
475 name: &'b OsStr,
476 ) -> impl Iterator<Item = &'a Process> + 'b {
477 self.processes()
478 .values()
479 .filter(move |val: &&Process| val.name() == name)
480 }
481
482 /// Returns "global" CPUs usage (aka the addition of all the CPUs).
483 ///
484 /// To have up-to-date information, you need to call [`System::refresh_cpu_specifics`] or
485 /// [`System::refresh_specifics`] with `cpu` enabled.
486 ///
487 /// ```no_run
488 /// use sysinfo::{CpuRefreshKind, RefreshKind, System};
489 ///
490 /// let mut s = System::new_with_specifics(
491 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
492 /// );
493 /// // Wait a bit because CPU usage is based on diff.
494 /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
495 /// // Refresh CPUs again to get actual value.
496 /// s.refresh_cpu_usage();
497 /// println!("{}%", s.global_cpu_usage());
498 /// ```
499 pub fn global_cpu_usage(&self) -> f32 {
500 self.inner.global_cpu_usage()
501 }
502
503 /// Returns the list of the CPUs.
504 ///
505 /// By default, the list of CPUs is empty until you call [`System::refresh_cpu_specifics`] or
506 /// [`System::refresh_specifics`] with `cpu` enabled.
507 ///
508 /// ```no_run
509 /// use sysinfo::{CpuRefreshKind, RefreshKind, System};
510 ///
511 /// let mut s = System::new_with_specifics(
512 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
513 /// );
514 /// // Wait a bit because CPU usage is based on diff.
515 /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
516 /// // Refresh CPUs again to get actual value.
517 /// s.refresh_cpu_usage();
518 /// for cpu in s.cpus() {
519 /// println!("{}%", cpu.cpu_usage());
520 /// }
521 /// ```
522 pub fn cpus(&self) -> &[Cpu] {
523 self.inner.cpus()
524 }
525
526 /// Returns the RAM size in bytes.
527 ///
528 /// ```no_run
529 /// use sysinfo::System;
530 ///
531 /// let s = System::new_all();
532 /// println!("{} bytes", s.total_memory());
533 /// ```
534 ///
535 /// On Linux, if you want to see this information with the limit of your cgroup, take a look
536 /// at [`cgroup_limits`](System::cgroup_limits).
537 pub fn total_memory(&self) -> u64 {
538 self.inner.total_memory()
539 }
540
541 /// Returns the amount of free RAM in bytes.
542 ///
543 /// Generally, "free" memory refers to unallocated memory whereas "available" memory refers to
544 /// memory that is available for (re)use.
545 ///
546 /// Side note: Windows doesn't report "free" memory so this method returns the same value
547 /// as [`available_memory`](System::available_memory).
548 ///
549 /// ```no_run
550 /// use sysinfo::System;
551 ///
552 /// let s = System::new_all();
553 /// println!("{} bytes", s.free_memory());
554 /// ```
555 pub fn free_memory(&self) -> u64 {
556 self.inner.free_memory()
557 }
558
559 /// Returns the amount of available RAM in bytes.
560 ///
561 /// Generally, "free" memory refers to unallocated memory whereas "available" memory refers to
562 /// memory that is available for (re)use.
563 ///
564 /// ⚠️ Windows and FreeBSD don't report "available" memory so [`System::free_memory`]
565 /// returns the same value as this method.
566 ///
567 /// ```no_run
568 /// use sysinfo::System;
569 ///
570 /// let s = System::new_all();
571 /// println!("{} bytes", s.available_memory());
572 /// ```
573 pub fn available_memory(&self) -> u64 {
574 self.inner.available_memory()
575 }
576
577 /// Returns the amount of used RAM in bytes.
578 ///
579 /// ```no_run
580 /// use sysinfo::System;
581 ///
582 /// let s = System::new_all();
583 /// println!("{} bytes", s.used_memory());
584 /// ```
585 pub fn used_memory(&self) -> u64 {
586 self.inner.used_memory()
587 }
588
589 /// Returns the SWAP size in bytes.
590 ///
591 /// ```no_run
592 /// use sysinfo::System;
593 ///
594 /// let s = System::new_all();
595 /// println!("{} bytes", s.total_swap());
596 /// ```
597 pub fn total_swap(&self) -> u64 {
598 self.inner.total_swap()
599 }
600
601 /// Returns the amount of free SWAP in bytes.
602 ///
603 /// ```no_run
604 /// use sysinfo::System;
605 ///
606 /// let s = System::new_all();
607 /// println!("{} bytes", s.free_swap());
608 /// ```
609 pub fn free_swap(&self) -> u64 {
610 self.inner.free_swap()
611 }
612
613 /// Returns the amount of used SWAP in bytes.
614 ///
615 /// ```no_run
616 /// use sysinfo::System;
617 ///
618 /// let s = System::new_all();
619 /// println!("{} bytes", s.used_swap());
620 /// ```
621 pub fn used_swap(&self) -> u64 {
622 self.inner.used_swap()
623 }
624
625 /// Retrieves the limits for the current cgroup (if any), otherwise it returns `None`.
626 ///
627 /// This information is computed every time the method is called.
628 ///
629 /// ⚠️ You need to have run [`refresh_memory`](System::refresh_memory) at least once before
630 /// calling this method.
631 ///
632 /// ⚠️ This method is only implemented for Linux. It always returns `None` for all other
633 /// systems.
634 ///
635 /// ```no_run
636 /// use sysinfo::System;
637 ///
638 /// let s = System::new_all();
639 /// println!("limits: {:?}", s.cgroup_limits());
640 /// ```
641 pub fn cgroup_limits(&self) -> Option<CGroupLimits> {
642 self.inner.cgroup_limits()
643 }
644
645 /// Returns system uptime (in seconds).
646 ///
647 /// **Important**: this information is computed every time this function is called.
648 ///
649 /// ```no_run
650 /// use sysinfo::System;
651 ///
652 /// println!("System running since {} seconds", System::uptime());
653 /// ```
654 pub fn uptime() -> u64 {
655 SystemInner::uptime()
656 }
657
658 /// Returns the time (in seconds) when the system booted since UNIX epoch.
659 ///
660 /// **Important**: this information is computed every time this function is called.
661 ///
662 /// ```no_run
663 /// use sysinfo::System;
664 ///
665 /// println!("System booted at {} seconds", System::boot_time());
666 /// ```
667 pub fn boot_time() -> u64 {
668 SystemInner::boot_time()
669 }
670
671 /// Returns the system load average value.
672 ///
673 /// **Important**: this information is computed every time this function is called.
674 ///
675 /// ⚠️ This is currently not working on **Windows**.
676 ///
677 /// ```no_run
678 /// use sysinfo::System;
679 ///
680 /// let load_avg = System::load_average();
681 /// println!(
682 /// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%",
683 /// load_avg.one,
684 /// load_avg.five,
685 /// load_avg.fifteen,
686 /// );
687 /// ```
688 pub fn load_average() -> LoadAvg {
689 SystemInner::load_average()
690 }
691
692 /// Returns the system name.
693 ///
694 /// | example platform | value of `System::name()` |
695 /// |---|---|
696 /// | linux laptop | "Ubuntu" |
697 /// | android phone | "Pixel 9 Pro" |
698 /// | apple laptop | "Darwin" |
699 /// | windows server | "Windows" |
700 ///
701 /// **Important**: this information is computed every time this function is called.
702 ///
703 /// ```no_run
704 /// use sysinfo::System;
705 ///
706 /// println!("OS: {:?}", System::name());
707 /// ```
708 pub fn name() -> Option<String> {
709 SystemInner::name()
710 }
711
712 /// Returns the system's kernel version.
713 ///
714 /// | example platform | value of `System::kernel_version()` |
715 /// |---|---|
716 /// | linux laptop | "6.8.0-48-generic" |
717 /// | android phone | "6.1.84-android14-11" |
718 /// | apple laptop | "24.1.0" |
719 /// | windows server | "20348" |
720 ///
721 /// **Important**: this information is computed every time this function is called.
722 ///
723 /// ```no_run
724 /// use sysinfo::System;
725 ///
726 /// println!("kernel version: {:?}", System::kernel_version());
727 /// ```
728 pub fn kernel_version() -> Option<String> {
729 SystemInner::kernel_version()
730 }
731
732 /// Returns the system version (e.g. for macOS this will return 15.1 rather than the kernel
733 /// version).
734 ///
735 /// | example platform | value of `System::os_version()` |
736 /// |---|---|
737 /// | linux laptop | "24.04" |
738 /// | android phone | "15" |
739 /// | apple laptop | "15.1.1" |
740 /// | windows server | "10 (20348)" |
741 ///
742 /// **Important**: this information is computed every time this function is called.
743 ///
744 /// ```no_run
745 /// use sysinfo::System;
746 ///
747 /// println!("OS version: {:?}", System::os_version());
748 /// ```
749 pub fn os_version() -> Option<String> {
750 SystemInner::os_version()
751 }
752
753 /// Returns the system long os version.
754 ///
755 /// | example platform | value of `System::long_os_version()` |
756 /// |---|---|
757 /// | linux laptop | "Linux (Ubuntu 24.04)" |
758 /// | android phone | "Android 15 on Pixel 9 Pro" |
759 /// | apple laptop | "macOS 15.1.1 Sequoia" |
760 /// | windows server | "Windows Server 2022 Datacenter" |
761 ///
762 /// **Important**: this information is computed every time this function is called.
763 ///
764 /// ```no_run
765 /// use sysinfo::System;
766 ///
767 /// println!("Long OS Version: {:?}", System::long_os_version());
768 /// ```
769 pub fn long_os_version() -> Option<String> {
770 SystemInner::long_os_version()
771 }
772
773 /// Returns the distribution id as defined by os-release,
774 /// or [`std::env::consts::OS`].
775 ///
776 /// See also
777 /// - <https://www.freedesktop.org/software/systemd/man/os-release.html#ID=>
778 /// - <https://doc.rust-lang.org/std/env/consts/constant.OS.html>
779 ///
780 /// | example platform | value of `System::distribution_id()` |
781 /// |---|---|
782 /// | linux laptop | "ubuntu" |
783 /// | android phone | "android" |
784 /// | apple laptop | "macos" |
785 /// | windows server | "windows" |
786 ///
787 /// **Important**: this information is computed every time this function is called.
788 ///
789 /// ```no_run
790 /// use sysinfo::System;
791 ///
792 /// println!("Distribution ID: {:?}", System::distribution_id());
793 /// ```
794 pub fn distribution_id() -> String {
795 SystemInner::distribution_id()
796 }
797
798 /// Returns the distribution ids of operating systems that are closely
799 /// related to the local operating system in regards to packaging and
800 /// programming interfaces, for example listing one or more OS identifiers
801 /// the local OS is a derivative from.
802 ///
803 /// See also
804 /// - <https://www.freedesktop.org/software/systemd/man/latest/os-release.html#ID_LIKE=>
805 ///
806 /// | example platform | value of `System::distribution_id_like()` |
807 /// |---|---|
808 /// | android phone | [] |
809 /// | archlinux laptop | [] |
810 /// | centos server | ["rhel", "fedora"] |
811 /// | ubuntu laptop | ["debian"] |
812 /// | windows laptop | [] |
813 ///
814 /// **Important**: this information is computed every time this function is called.
815 ///
816 /// ```no_run
817 /// use sysinfo::System;
818 ///
819 /// println!("Distribution ID_LIKE: {:?}", System::distribution_id_like());
820 /// ```
821 pub fn distribution_id_like() -> Vec<String> {
822 SystemInner::distribution_id_like()
823 }
824
825 /// Provides kernel version following this string format:
826 ///
827 /// | Platform | Result |
828 /// |-|-|
829 /// | Windows | Windows OS Build 20348.2227 |
830 /// | Linux | Linux 6.12.13-200.fc41.x86_64 |
831 /// | Android | Android 612.13-200 |
832 /// | MacOS | Darwin 21.6.0 |
833 /// | FreeBSD | FreeBSD 199506 |
834 ///
835 /// If any of the information is not available, it will be replaced with "unknown".
836 ///
837 /// **Important**: this information is computed every time this function is called.
838 ///
839 /// ```no_run
840 /// use sysinfo::System;
841 ///
842 /// println!("Kernel long version: {}", System::kernel_long_version());
843 /// ```
844 ///
845 /// [distribution_id]: System::distribution_id
846 /// [kernel_version]: System::kernel_version
847 pub fn kernel_long_version() -> String {
848 let kernel_version = match System::kernel_version() {
849 None => "unknown".to_string(),
850 Some(s) => s,
851 };
852 let kernel_name = SystemInner::kernel_name().unwrap_or("Unknown");
853 if cfg!(windows) {
854 format!("{kernel_name} OS Build {kernel_version}")
855 } else {
856 format!("{kernel_name} {kernel_version}")
857 }
858 }
859
860 /// Returns the system hostname based off DNS.
861 ///
862 /// **Important**: this information is computed every time this function is called.
863 ///
864 /// ```no_run
865 /// use sysinfo::System;
866 ///
867 /// println!("Hostname: {:?}", System::host_name());
868 /// ```
869 pub fn host_name() -> Option<String> {
870 SystemInner::host_name()
871 }
872
873 /// Returns the CPU architecture (eg. x86, amd64, aarch64, ...).
874 ///
875 /// **Important**: this information is computed every time this function is called.
876 ///
877 /// ```no_run
878 /// use sysinfo::System;
879 ///
880 /// println!("CPU Architecture: {:?}", System::cpu_arch());
881 /// ```
882 pub fn cpu_arch() -> String {
883 SystemInner::cpu_arch().unwrap_or_else(|| std::env::consts::ARCH.to_owned())
884 }
885
886 /// Returns the number of physical cores on the CPU or `None` if it couldn't get it.
887 ///
888 /// In case there are multiple CPUs, it will combine the physical core count of all the CPUs.
889 ///
890 /// **Important**: this information is computed every time this function is called.
891 ///
892 /// ```no_run
893 /// use sysinfo::System;
894 ///
895 /// let s = System::new();
896 /// println!("{:?}", System::physical_core_count());
897 /// ```
898 pub fn physical_core_count() -> Option<usize> {
899 SystemInner::physical_core_count()
900 }
901
902 /// Returns the (default) maximum number of open files for a process.
903 ///
904 /// Returns `None` if it failed retrieving the information or if the current system is not
905 /// supported.
906 ///
907 /// **Important**: this information is computed every time this function is called.
908 ///
909 /// ```no_run
910 /// use sysinfo::System;
911 ///
912 /// println!("Max open files: {:?}", System::open_files_limit());
913 /// ```
914 pub fn open_files_limit() -> Option<usize> {
915 SystemInner::open_files_limit()
916 }
917}
918
919/// This type allows to retrieve motherboard-related information.
920///
921/// ```
922/// use sysinfo::Motherboard;
923///
924/// if let Some(m) = Motherboard::new() {
925/// println!("{m:?}");
926/// }
927/// ```
928pub struct Motherboard {
929 pub(crate) inner: MotherboardInner,
930}
931
932impl Motherboard {
933 /// Creates a new instance of the `Motherboard` type.
934 ///
935 /// ```
936 /// use sysinfo::Motherboard;
937 ///
938 /// if let Some(m) = Motherboard::new() {
939 /// println!("{m:?}");
940 /// }
941 /// ```
942 pub fn new() -> Option<Self> {
943 Some(Self {
944 inner: MotherboardInner::new()?,
945 })
946 }
947
948 /// Returns the motherboard name.
949 ///
950 /// This corresponds to the model identifier assigned by the motherboard's
951 /// manufacturer (e.g. "20BE0061MC").
952 /// This information isn't available on ARM-based macOS systems.
953 ///
954 /// **Important**: this information is computed every time this function is called.
955 ///
956 /// ```no_run
957 /// use sysinfo::Motherboard;
958 ///
959 /// if let Some(m) = Motherboard::new() {
960 /// println!("Motherboard name: {:?}", m.name());
961 /// }
962 /// ```
963 pub fn name(&self) -> Option<String> {
964 self.inner.name()
965 }
966
967 /// Returns the motherboard vendor name.
968 ///
969 /// This corresponds to the name of the motherboard's manufacturer (e.g. "LENOVO").
970 ///
971 /// **Important**: this information is computed every time this function is called.
972 ///
973 /// ```no_run
974 /// use sysinfo::Motherboard;
975 ///
976 /// if let Some(m) = Motherboard::new() {
977 /// println!("Motherboard vendor: {:?}", m.vendor_name());
978 /// }
979 /// ```
980 pub fn vendor_name(&self) -> Option<String> {
981 self.inner.vendor_name()
982 }
983
984 /// Returns the motherboard version.
985 ///
986 /// This corresponds to the version or model number assigned by the motherboard's
987 /// manufacturer (e.g. "0B98401 Pro").
988 /// This information isn't available on ARM-based macOS systems.
989 ///
990 /// **Important**: this information is computed every time this function is called.
991 ///
992 /// ```no_run
993 /// use sysinfo::Motherboard;
994 ///
995 /// if let Some(m) = Motherboard::new() {
996 /// println!("Motherboard version: {:?}", m.version());
997 /// }
998 /// ```
999 pub fn version(&self) -> Option<String> {
1000 self.inner.version()
1001 }
1002
1003 /// Returns the motherboard serial number.
1004 ///
1005 /// This corresponds to the serial number assigned by the motherboard's
1006 /// manufacturer (e.g. "W1KS427111E").
1007 ///
1008 /// **Important**: this information is computed every time this function is called.
1009 ///
1010 /// ```no_run
1011 /// use sysinfo::Motherboard;
1012 ///
1013 /// if let Some(m) = Motherboard::new() {
1014 /// println!("Motherboard serial number: {:?}", m.serial_number());
1015 /// }
1016 /// ```
1017 pub fn serial_number(&self) -> Option<String> {
1018 self.inner.serial_number()
1019 }
1020
1021 /// Returns the motherboard asset tag.
1022 ///
1023 /// This corresponds to the identifier assigned by the motherboard's
1024 /// manufacturer to track the physical device for inventory purposes.
1025 ///
1026 /// **Important**: this information is computed every time this function is called.
1027 ///
1028 /// ⚠️ Not supported on macOS/iOS.
1029 ///
1030 /// ```no_run
1031 /// use sysinfo::Motherboard;
1032 ///
1033 /// if let Some(m) = Motherboard::new() {
1034 /// println!("Motherboard asset tag: {:?}", m.asset_tag());
1035 /// }
1036 /// ```
1037 pub fn asset_tag(&self) -> Option<String> {
1038 self.inner.asset_tag()
1039 }
1040}
1041
1042/// This type allows to retrieve product-related information.
1043///
1044/// ```
1045/// use sysinfo::Product;
1046///
1047/// println!("{:?}", Product);
1048/// ```
1049pub struct Product;
1050
1051impl Product {
1052 /// Returns the product name.
1053 ///
1054 /// This corresponds to the product name assigned by the hardware
1055 /// manufacturer (e.g. "20AN").
1056 ///
1057 /// **Important**: this information is computed every time this function is called.
1058 ///
1059 /// ```no_run
1060 /// use sysinfo::Product;
1061 ///
1062 /// println!("Product name: {:?}", Product::name());
1063 /// ```
1064 pub fn name() -> Option<String> {
1065 ProductInner::name()
1066 }
1067
1068 /// Returns the product family identifier.
1069 ///
1070 /// This corresponds to the product family assigned by the hardware
1071 /// manufacturer (e.g. "T440p").
1072 ///
1073 /// **Important**: this information is computed every time this function is called.
1074 ///
1075 /// ```no_run
1076 /// use sysinfo::Product;
1077 ///
1078 /// println!("Product family: {:?}", Product::family());
1079 /// ```
1080 pub fn family() -> Option<String> {
1081 ProductInner::family()
1082 }
1083
1084 /// Returns the product serial number.
1085 ///
1086 /// This corresponds to the serial identifier assigned by the hardware
1087 /// manufacturer (e.g. "W1KS427111E").
1088 ///
1089 /// **Important**: this information is computed every time this function is called.
1090 ///
1091 /// ```no_run
1092 /// use sysinfo::Product;
1093 ///
1094 /// println!("Product serial: {:?}", Product::serial_number());
1095 /// ```
1096 pub fn serial_number() -> Option<String> {
1097 ProductInner::serial_number()
1098 }
1099
1100 /// Returns the product Stock Keeping Unit (SKU).
1101 ///
1102 /// This corresponds to the Stock Keeping Unit assigned by the hardware
1103 /// manufacturer (e.g. "LENOVO_MT_20AN") which identifies a specific
1104 /// model or configuration.
1105 ///
1106 /// **Important**: this information is computed every time this function is called.
1107 ///
1108 /// ⚠️ Not supported on macOS/iOS.
1109 ///
1110 /// ```no_run
1111 /// use sysinfo::Product;
1112 ///
1113 /// println!("Product sku: {:?}", Product::stock_keeping_unit());
1114 /// ```
1115 #[doc(alias = "sku")]
1116 pub fn stock_keeping_unit() -> Option<String> {
1117 ProductInner::stock_keeping_unit()
1118 }
1119
1120 /// Returns the product UUID.
1121 ///
1122 /// This corresponds to the unique identifier assigned by the hardware
1123 /// manufacturer (e.g. "407488fe-960a-43b5-a265-8fd0e9200b8f") which uniquely
1124 /// identifies the physical system.
1125 ///
1126 /// **Important**: this information is computed every time this function is called.
1127 ///
1128 /// ```no_run
1129 /// use sysinfo::Product;
1130 ///
1131 /// println!("Product UUID: {:?}", Product::uuid());
1132 /// ```
1133 pub fn uuid() -> Option<String> {
1134 ProductInner::uuid()
1135 }
1136
1137 /// Returns the product version.
1138 ///
1139 /// This corresponds to the version assigned by the hardware
1140 /// manufacturer (e.g. "Lenovo ThinkPad T440p") which identifies
1141 /// the specific version or revision of the product.
1142 ///
1143 /// **Important**: this information is computed every time this function is called.
1144 ///
1145 /// ```no_run
1146 /// use sysinfo::Product;
1147 ///
1148 /// println!("Product version: {:?}", Product::version());
1149 /// ```
1150 pub fn version() -> Option<String> {
1151 ProductInner::version()
1152 }
1153
1154 /// Returns the product vendor name.
1155 ///
1156 /// This corresponds to the vendor name assigned by the hardware
1157 /// manufacturer (e.g. "LENOVO").
1158 ///
1159 /// **Important**: this information is computed every time this function is called.
1160 ///
1161 /// ```no_run
1162 /// use sysinfo::Product;
1163 ///
1164 /// println!("Vendor name: {:?}", Product::vendor_name());
1165 /// ```
1166 pub fn vendor_name() -> Option<String> {
1167 ProductInner::vendor_name()
1168 }
1169}
1170
1171/// A struct representing system load average value.
1172///
1173/// It is returned by [`System::load_average`][crate::System::load_average].
1174///
1175/// ```no_run
1176/// use sysinfo::System;
1177///
1178/// let load_avg = System::load_average();
1179/// println!(
1180/// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%",
1181/// load_avg.one,
1182/// load_avg.five,
1183/// load_avg.fifteen,
1184/// );
1185/// ```
1186#[repr(C)]
1187#[derive(Default, Debug, Clone)]
1188pub struct LoadAvg {
1189 /// Average load within one minute.
1190 pub one: f64,
1191 /// Average load within five minutes.
1192 pub five: f64,
1193 /// Average load within fifteen minutes.
1194 pub fifteen: f64,
1195}
1196
1197/// An enum representing signals on UNIX-like systems.
1198///
1199/// On non-unix systems, this enum is mostly useless and is only there to keep coherency between
1200/// the different OSes.
1201///
1202/// If you want the list of the supported signals on the current system, use
1203/// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1204#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
1205#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1206pub enum Signal {
1207 /// Hangup detected on controlling terminal or death of controlling process.
1208 Hangup,
1209 /// Interrupt from keyboard.
1210 Interrupt,
1211 /// Quit from keyboard.
1212 Quit,
1213 /// Illegal instruction.
1214 Illegal,
1215 /// Trace/breakpoint trap.
1216 Trap,
1217 /// Abort signal from C abort function.
1218 Abort,
1219 /// IOT trap. A synonym for SIGABRT.
1220 IOT,
1221 /// Bus error (bad memory access).
1222 Bus,
1223 /// Floating point exception.
1224 FloatingPointException,
1225 /// Kill signal.
1226 Kill,
1227 /// User-defined signal 1.
1228 User1,
1229 /// Invalid memory reference.
1230 Segv,
1231 /// User-defined signal 2.
1232 User2,
1233 /// Broken pipe: write to pipe with no readers.
1234 Pipe,
1235 /// Timer signal from C alarm function.
1236 Alarm,
1237 /// Termination signal.
1238 Term,
1239 /// Child stopped or terminated.
1240 Child,
1241 /// Continue if stopped.
1242 Continue,
1243 /// Stop process.
1244 Stop,
1245 /// Stop typed at terminal.
1246 TSTP,
1247 /// Terminal input for background process.
1248 TTIN,
1249 /// Terminal output for background process.
1250 TTOU,
1251 /// Urgent condition on socket.
1252 Urgent,
1253 /// CPU time limit exceeded.
1254 XCPU,
1255 /// File size limit exceeded.
1256 XFSZ,
1257 /// Virtual alarm clock.
1258 VirtualAlarm,
1259 /// Profiling time expired.
1260 Profiling,
1261 /// Windows resize signal.
1262 Winch,
1263 /// I/O now possible.
1264 IO,
1265 /// Pollable event (Sys V). Synonym for IO
1266 Poll,
1267 /// Power failure (System V).
1268 ///
1269 /// Doesn't exist on apple systems so will be ignored.
1270 Power,
1271 /// Bad argument to routine (SVr4).
1272 Sys,
1273}
1274
1275impl std::fmt::Display for Signal {
1276 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1277 let s = match *self {
1278 Self::Hangup => "Hangup",
1279 Self::Interrupt => "Interrupt",
1280 Self::Quit => "Quit",
1281 Self::Illegal => "Illegal",
1282 Self::Trap => "Trap",
1283 Self::Abort => "Abort",
1284 Self::IOT => "IOT",
1285 Self::Bus => "Bus",
1286 Self::FloatingPointException => "FloatingPointException",
1287 Self::Kill => "Kill",
1288 Self::User1 => "User1",
1289 Self::Segv => "Segv",
1290 Self::User2 => "User2",
1291 Self::Pipe => "Pipe",
1292 Self::Alarm => "Alarm",
1293 Self::Term => "Term",
1294 Self::Child => "Child",
1295 Self::Continue => "Continue",
1296 Self::Stop => "Stop",
1297 Self::TSTP => "TSTP",
1298 Self::TTIN => "TTIN",
1299 Self::TTOU => "TTOU",
1300 Self::Urgent => "Urgent",
1301 Self::XCPU => "XCPU",
1302 Self::XFSZ => "XFSZ",
1303 Self::VirtualAlarm => "VirtualAlarm",
1304 Self::Profiling => "Profiling",
1305 Self::Winch => "Winch",
1306 Self::IO => "IO",
1307 Self::Poll => "Poll",
1308 Self::Power => "Power",
1309 Self::Sys => "Sys",
1310 };
1311 f.write_str(s)
1312 }
1313}
1314
1315/// Contains memory limits for the current process.
1316#[derive(Default, Debug, Clone)]
1317pub struct CGroupLimits {
1318 /// Total memory (in bytes) for the current cgroup.
1319 pub total_memory: u64,
1320 /// Free memory (in bytes) for the current cgroup.
1321 pub free_memory: u64,
1322 /// Free swap (in bytes) for the current cgroup.
1323 pub free_swap: u64,
1324 /// Resident Set Size (RSS) (in bytes) for the current cgroup.
1325 pub rss: u64,
1326}
1327
1328/// Enum describing the different status of a process.
1329#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
1330#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1331pub enum ProcessStatus {
1332 /// ## Linux
1333 ///
1334 /// Idle kernel thread.
1335 ///
1336 /// ## macOs/FreeBSD
1337 ///
1338 /// Process being created by fork.
1339 ///
1340 /// ## Other OS
1341 ///
1342 /// Not available.
1343 Idle,
1344 /// Running.
1345 Run,
1346 /// ## Linux
1347 ///
1348 /// Sleeping in an interruptible waiting.
1349 ///
1350 /// ## macOS/FreeBSD
1351 ///
1352 /// Sleeping on an address.
1353 ///
1354 /// ## Other OS
1355 ///
1356 /// Not available.
1357 Sleep,
1358 /// ## Linux
1359 ///
1360 /// Stopped (on a signal) or (before Linux 2.6.33) trace stopped.
1361 ///
1362 /// ## macOS/FreeBSD
1363 ///
1364 /// Process debugging or suspension.
1365 ///
1366 /// ## Other OS
1367 ///
1368 /// Not available.
1369 Stop,
1370 /// ## Linux/FreeBSD/macOS
1371 ///
1372 /// Zombie process. Terminated but not reaped by its parent.
1373 ///
1374 /// ## Other OS
1375 ///
1376 /// Not available.
1377 Zombie,
1378 /// ## Linux
1379 ///
1380 /// Tracing stop (Linux 2.6.33 onward). Stopped by debugger during the tracing.
1381 ///
1382 /// ## Other OS
1383 ///
1384 /// Not available.
1385 Tracing,
1386 /// ## Linux
1387 ///
1388 /// Dead/uninterruptible sleep (usually IO).
1389 ///
1390 /// ## FreeBSD
1391 ///
1392 /// A process should never end up in this state.
1393 ///
1394 /// ## Other OS
1395 ///
1396 /// Not available.
1397 Dead,
1398 /// ## Linux
1399 ///
1400 /// Wakekill (Linux 2.6.33 to 3.13 only).
1401 ///
1402 /// ## Other OS
1403 ///
1404 /// Not available.
1405 Wakekill,
1406 /// ## Linux
1407 ///
1408 /// Waking (Linux 2.6.33 to 3.13 only).
1409 ///
1410 /// ## Other OS
1411 ///
1412 /// Not available.
1413 Waking,
1414 /// ## Linux
1415 ///
1416 /// Parked (Linux 3.9 to 3.13 only).
1417 ///
1418 /// ## macOS
1419 ///
1420 /// Halted at a clean point.
1421 ///
1422 /// ## Other OS
1423 ///
1424 /// Not available.
1425 Parked,
1426 /// ## FreeBSD
1427 ///
1428 /// Blocked on a lock.
1429 ///
1430 /// ## Other OS
1431 ///
1432 /// Not available.
1433 LockBlocked,
1434 /// ## Linux
1435 ///
1436 /// Waiting in uninterruptible disk sleep.
1437 ///
1438 /// ## Other OS
1439 ///
1440 /// Not available.
1441 UninterruptibleDiskSleep,
1442 /// Unknown.
1443 Unknown(u32),
1444}
1445
1446/// Enum describing the different kind of threads.
1447#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1448#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1449pub enum ThreadKind {
1450 /// Kernel thread.
1451 Kernel,
1452 /// User thread.
1453 Userland,
1454}
1455
1456/// Enum describing possible [`Process::kill_and_wait`] errors.
1457#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1458#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1459pub enum KillError {
1460 /// This signal doesn't exist on this platform.
1461 SignalDoesNotExist,
1462 /// The signal failed to be sent to the target process.
1463 FailedToSendSignal,
1464}
1465
1466/// Struct containing information of a process.
1467///
1468/// ## iOS
1469///
1470/// This information cannot be retrieved on iOS due to sandboxing.
1471///
1472/// ## Apple app store
1473///
1474/// If you are building a macOS Apple app store, it won't be able
1475/// to retrieve this information.
1476///
1477/// ```no_run
1478/// use sysinfo::{Pid, System};
1479///
1480/// let s = System::new_all();
1481/// if let Some(process) = s.process(Pid::from(1337)) {
1482/// println!("{:?}", process.name());
1483/// }
1484/// ```
1485pub struct Process {
1486 pub(crate) inner: ProcessInner,
1487}
1488
1489impl Process {
1490 /// Sends [`Signal::Kill`] to the process (which is the only signal supported on all supported
1491 /// platforms by this crate).
1492 ///
1493 /// Returns `true` if the signal was sent successfully. If you want to wait for this process
1494 /// to end, you can use [`Process::wait`] or directly [`Process::kill_and_wait`].
1495 ///
1496 /// ⚠️ Even if this function returns `true`, it doesn't necessarily mean that the process will
1497 /// be killed. It just means that the signal was sent successfully.
1498 ///
1499 /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1500 /// levels than the current process for example.
1501 ///
1502 /// If you want to use another signal, take a look at [`Process::kill_with`].
1503 ///
1504 /// To get the list of the supported signals on this system, use
1505 /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1506 ///
1507 /// ```no_run
1508 /// use sysinfo::{Pid, System};
1509 ///
1510 /// let s = System::new_all();
1511 /// if let Some(process) = s.process(Pid::from(1337)) {
1512 /// process.kill();
1513 /// }
1514 /// ```
1515 pub fn kill(&self) -> bool {
1516 self.kill_with(Signal::Kill).unwrap_or(false)
1517 }
1518
1519 /// Sends the given `signal` to the process. If the signal doesn't exist on this platform,
1520 /// it'll do nothing and will return `None`. Otherwise it'll return `Some(bool)`. The boolean
1521 /// value will depend on whether or not the signal was sent successfully.
1522 ///
1523 /// If you just want to kill the process, use [`Process::kill`] directly. If you want to wait
1524 /// for this process to end, you can use [`Process::wait`] or [`Process::kill_with_and_wait`].
1525 ///
1526 /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1527 /// levels than the current process for example.
1528 ///
1529 /// To get the list of the supported signals on this system, use
1530 /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1531 ///
1532 /// ```no_run
1533 /// use sysinfo::{Pid, Signal, System};
1534 ///
1535 /// let s = System::new_all();
1536 /// if let Some(process) = s.process(Pid::from(1337)) {
1537 /// if process.kill_with(Signal::Kill).is_none() {
1538 /// println!("This signal isn't supported on this platform");
1539 /// }
1540 /// }
1541 /// ```
1542 pub fn kill_with(&self, signal: Signal) -> Option<bool> {
1543 self.inner.kill_with(signal)
1544 }
1545
1546 /// Sends [`Signal::Kill`] to the process then waits for its termination.
1547 ///
1548 /// Internally, this method is calling [`Process::kill`] then [`Process::wait`].
1549 ///
1550 /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1551 /// levels than the current process for example. In this case, this method could enter an
1552 /// infinite loop.
1553 ///
1554 /// ```no_run
1555 /// use sysinfo::{Pid, System};
1556 ///
1557 /// let s = System::new_all();
1558 /// if let Some(process) = s.process(Pid::from(1337)) {
1559 /// if let Err(error) = process.kill_and_wait() {
1560 /// println!("`kill_and_wait` failed: {error:?}");
1561 /// }
1562 /// }
1563 /// ```
1564 pub fn kill_and_wait(&self) -> Result<Option<ExitStatus>, KillError> {
1565 self.kill_with_and_wait(Signal::Kill)
1566 }
1567
1568 /// Sends the given `signal` to the process.then waits for its termination.
1569 ///
1570 /// Internally, this method is calling [`Process::kill_with`] then [`Process::wait`].
1571 ///
1572 /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1573 /// levels than the current process for example. In this case, this method could enter an
1574 /// infinite loop.
1575 ///
1576 /// To get the list of the supported signals on this system, use
1577 /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1578 ///
1579 /// ```no_run
1580 /// use sysinfo::{Pid, System};
1581 ///
1582 /// let s = System::new_all();
1583 /// if let Some(process) = s.process(Pid::from(1337)) {
1584 /// if let Err(error) = process.kill_and_wait() {
1585 /// println!("`kill_and_wait` failed: {error:?}");
1586 /// }
1587 /// }
1588 /// ```
1589 pub fn kill_with_and_wait(&self, signal: Signal) -> Result<Option<ExitStatus>, KillError> {
1590 match self.inner.kill_with(signal) {
1591 Some(sent) => {
1592 if !sent {
1593 return Err(KillError::FailedToSendSignal);
1594 }
1595 }
1596 None => return Err(KillError::SignalDoesNotExist),
1597 }
1598
1599 Ok(self.inner.wait())
1600 }
1601
1602 /// Waits for process termination and returns its [`ExitStatus`] if it could be retrieved,
1603 /// returns `None` otherwise. It means that as long as the process is alive, this method will
1604 /// not return.
1605 ///
1606 /// ⚠️ On **macOS** and **FreeBSD**, if the process died and a new one took its PID, unless
1607 /// you refreshed, it will wait for the new process to end.
1608 ///
1609 /// On **Windows**, as long as we have a (internal) handle, we can always retrieve the exit
1610 /// status.
1611 ///
1612 /// On **Linux**/**Android**, we check that the start time of the PID we're waiting is the same
1613 /// as the current process'. If not it means the process died and a new one got its PID.
1614 ///
1615 /// ```no_run
1616 /// use sysinfo::{Pid, System};
1617 ///
1618 /// let mut s = System::new_all();
1619 ///
1620 /// if let Some(process) = s.process(Pid::from(1337)) {
1621 /// println!("Waiting for pid 1337");
1622 /// let exit_status = process.wait();
1623 /// println!("Pid 1337 exited with: {exit_status:?}");
1624 /// }
1625 /// ```
1626 pub fn wait(&self) -> Option<ExitStatus> {
1627 self.inner.wait()
1628 }
1629
1630 /// Returns the name of the process.
1631 ///
1632 /// **⚠️ Important ⚠️**
1633 ///
1634 /// On **Linux**, there are two things to know about processes' name:
1635 /// 1. It is limited to 15 characters.
1636 /// 2. It is not always the exe name.
1637 ///
1638 /// If you are looking for a specific process, unless you know what you are
1639 /// doing, in most cases it's better to use [`Process::exe`] instead (which
1640 /// can be empty sometimes!).
1641 ///
1642 /// ```no_run
1643 /// use sysinfo::{Pid, System};
1644 ///
1645 /// let s = System::new_all();
1646 /// if let Some(process) = s.process(Pid::from(1337)) {
1647 /// println!("{:?}", process.name());
1648 /// }
1649 /// ```
1650 pub fn name(&self) -> &OsStr {
1651 self.inner.name()
1652 }
1653
1654 /// Returns the command line.
1655 ///
1656 /// **⚠️ Important ⚠️**
1657 ///
1658 /// On **Windows**, you might need to use `administrator` privileges when running your program
1659 /// to have access to this information.
1660 ///
1661 /// ```no_run
1662 /// use sysinfo::{Pid, System};
1663 ///
1664 /// let s = System::new_all();
1665 /// if let Some(process) = s.process(Pid::from(1337)) {
1666 /// println!("{:?}", process.cmd());
1667 /// }
1668 /// ```
1669 pub fn cmd(&self) -> &[OsString] {
1670 self.inner.cmd()
1671 }
1672
1673 /// Returns the path to the process.
1674 ///
1675 /// ```no_run
1676 /// use sysinfo::{Pid, System};
1677 ///
1678 /// let s = System::new_all();
1679 /// if let Some(process) = s.process(Pid::from(1337)) {
1680 /// println!("{:?}", process.exe());
1681 /// }
1682 /// ```
1683 ///
1684 /// ### Implementation notes
1685 ///
1686 /// On Linux, this method will return an empty path if there
1687 /// was an error trying to read `/proc/<pid>/exe`. This can
1688 /// happen, for example, if the permission levels or UID namespaces
1689 /// between the caller and target processes are different.
1690 ///
1691 /// It is also the case that `cmd[0]` is _not_ usually a correct
1692 /// replacement for this.
1693 /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html)
1694 /// freely, making this an untrustworthy source of information.
1695 pub fn exe(&self) -> Option<&Path> {
1696 self.inner.exe()
1697 }
1698
1699 /// Returns the PID of the process.
1700 ///
1701 /// ```no_run
1702 /// use sysinfo::{Pid, System};
1703 ///
1704 /// let s = System::new_all();
1705 /// if let Some(process) = s.process(Pid::from(1337)) {
1706 /// println!("{}", process.pid());
1707 /// }
1708 /// ```
1709 pub fn pid(&self) -> Pid {
1710 self.inner.pid()
1711 }
1712
1713 /// Returns the environment variables of the process.
1714 ///
1715 /// ```no_run
1716 /// use sysinfo::{Pid, System};
1717 ///
1718 /// let s = System::new_all();
1719 /// if let Some(process) = s.process(Pid::from(1337)) {
1720 /// println!("{:?}", process.environ());
1721 /// }
1722 /// ```
1723 pub fn environ(&self) -> &[OsString] {
1724 self.inner.environ()
1725 }
1726
1727 /// Returns the current working directory.
1728 ///
1729 /// ```no_run
1730 /// use sysinfo::{Pid, System};
1731 ///
1732 /// let s = System::new_all();
1733 /// if let Some(process) = s.process(Pid::from(1337)) {
1734 /// println!("{:?}", process.cwd());
1735 /// }
1736 /// ```
1737 pub fn cwd(&self) -> Option<&Path> {
1738 self.inner.cwd()
1739 }
1740
1741 /// Returns the path of the root directory.
1742 ///
1743 /// ```no_run
1744 /// use sysinfo::{Pid, System};
1745 ///
1746 /// let s = System::new_all();
1747 /// if let Some(process) = s.process(Pid::from(1337)) {
1748 /// println!("{:?}", process.root());
1749 /// }
1750 /// ```
1751 pub fn root(&self) -> Option<&Path> {
1752 self.inner.root()
1753 }
1754
1755 /// Returns the memory usage (in bytes).
1756 ///
1757 /// This method returns the [size of the resident set], that is, the amount of memory that the
1758 /// process allocated and which is currently mapped in physical RAM. It does not include memory
1759 /// that is swapped out, or, in some operating systems, that has been allocated but never used.
1760 ///
1761 /// Thus, it represents exactly the amount of physical RAM that the process is using at the
1762 /// present time, but it might not be a good indicator of the total memory that the process will
1763 /// be using over its lifetime. For that purpose, you can try and use
1764 /// [`virtual_memory`](Process::virtual_memory).
1765 ///
1766 /// ```no_run
1767 /// use sysinfo::{Pid, System};
1768 ///
1769 /// let s = System::new_all();
1770 /// if let Some(process) = s.process(Pid::from(1337)) {
1771 /// println!("{} bytes", process.memory());
1772 /// }
1773 /// ```
1774 ///
1775 /// [size of the resident set]: https://en.wikipedia.org/wiki/Resident_set_size
1776 pub fn memory(&self) -> u64 {
1777 self.inner.memory()
1778 }
1779
1780 /// Returns the virtual memory usage (in bytes).
1781 ///
1782 /// This method returns the [size of virtual memory], that is, the amount of memory that the
1783 /// process can access, whether it is currently mapped in physical RAM or not. It includes
1784 /// physical RAM, allocated but not used regions, swapped-out regions, and even memory
1785 /// associated with [memory-mapped files](https://en.wikipedia.org/wiki/Memory-mapped_file).
1786 ///
1787 /// This value has limitations though. Depending on the operating system and type of process,
1788 /// this value might be a good indicator of the total memory that the process will be using over
1789 /// its lifetime. However, for example, in the version 14 of macOS this value is in the order of
1790 /// the hundreds of gigabytes for every process, and thus not very informative. Moreover, if a
1791 /// process maps into memory a very large file, this value will increase accordingly, even if
1792 /// the process is not actively using the memory.
1793 ///
1794 /// ```no_run
1795 /// use sysinfo::{Pid, System};
1796 ///
1797 /// let s = System::new_all();
1798 /// if let Some(process) = s.process(Pid::from(1337)) {
1799 /// println!("{} bytes", process.virtual_memory());
1800 /// }
1801 /// ```
1802 ///
1803 /// [size of virtual memory]: https://en.wikipedia.org/wiki/Virtual_memory
1804 pub fn virtual_memory(&self) -> u64 {
1805 self.inner.virtual_memory()
1806 }
1807
1808 /// Returns the parent PID.
1809 ///
1810 /// ```no_run
1811 /// use sysinfo::{Pid, System};
1812 ///
1813 /// let s = System::new_all();
1814 /// if let Some(process) = s.process(Pid::from(1337)) {
1815 /// println!("{:?}", process.parent());
1816 /// }
1817 /// ```
1818 pub fn parent(&self) -> Option<Pid> {
1819 self.inner.parent()
1820 }
1821
1822 /// Returns the status of the process.
1823 ///
1824 /// ```no_run
1825 /// use sysinfo::{Pid, System};
1826 ///
1827 /// let s = System::new_all();
1828 /// if let Some(process) = s.process(Pid::from(1337)) {
1829 /// println!("{:?}", process.status());
1830 /// }
1831 /// ```
1832 pub fn status(&self) -> ProcessStatus {
1833 self.inner.status()
1834 }
1835
1836 /// Returns the time where the process was started (in seconds) from epoch.
1837 ///
1838 /// ```no_run
1839 /// use sysinfo::{Pid, System};
1840 ///
1841 /// let s = System::new_all();
1842 /// if let Some(process) = s.process(Pid::from(1337)) {
1843 /// println!("Started at {} seconds", process.start_time());
1844 /// }
1845 /// ```
1846 pub fn start_time(&self) -> u64 {
1847 self.inner.start_time()
1848 }
1849
1850 /// Returns for how much time the process has been running (in seconds).
1851 ///
1852 /// ```no_run
1853 /// use sysinfo::{Pid, System};
1854 ///
1855 /// let s = System::new_all();
1856 /// if let Some(process) = s.process(Pid::from(1337)) {
1857 /// println!("Running since {} seconds", process.run_time());
1858 /// }
1859 /// ```
1860 pub fn run_time(&self) -> u64 {
1861 self.inner.run_time()
1862 }
1863
1864 /// Returns the total CPU usage (in %). Notice that it might be bigger than
1865 /// 100 if run on a multi-core machine.
1866 ///
1867 /// If you want a value between 0% and 100%, divide the returned value by
1868 /// the number of CPUs.
1869 ///
1870 /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed
1871 /// **twice** because CPU usage computation is based on time diff (process
1872 /// time on a given time period divided by total system time on the same
1873 /// time period).
1874 ///
1875 /// ⚠️ If you want accurate CPU usage number, better leave a bit of time
1876 /// between two calls of this method (take a look at
1877 /// [`MINIMUM_CPU_UPDATE_INTERVAL`][crate::MINIMUM_CPU_UPDATE_INTERVAL] for
1878 /// more information).
1879 ///
1880 /// ```no_run
1881 /// use sysinfo::{Pid, ProcessesToUpdate, ProcessRefreshKind, System};
1882 ///
1883 /// let mut s = System::new_all();
1884 /// // Wait a bit because CPU usage is based on diff.
1885 /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
1886 /// // Refresh CPU usage to get actual value.
1887 /// s.refresh_processes_specifics(
1888 /// ProcessesToUpdate::All,
1889 /// true,
1890 /// ProcessRefreshKind::nothing().with_cpu()
1891 /// );
1892 /// if let Some(process) = s.process(Pid::from(1337)) {
1893 /// println!("{}%", process.cpu_usage());
1894 /// }
1895 /// ```
1896 pub fn cpu_usage(&self) -> f32 {
1897 self.inner.cpu_usage()
1898 }
1899
1900 /// Returns the total accumulated CPU usage (in CPU-milliseconds). Note
1901 /// that it might be bigger than the total clock run time of a process if
1902 /// run on a multi-core machine.
1903 ///
1904 /// ```no_run
1905 /// use sysinfo::{Pid, System};
1906 ///
1907 /// let s = System::new_all();
1908 /// if let Some(process) = s.process(Pid::from(1337)) {
1909 /// println!("{}", process.accumulated_cpu_time());
1910 /// }
1911 /// ```
1912 pub fn accumulated_cpu_time(&self) -> u64 {
1913 self.inner.accumulated_cpu_time()
1914 }
1915
1916 /// Returns number of bytes read and written to disk.
1917 ///
1918 /// ⚠️ On Windows, this method actually returns **ALL** I/O read and
1919 /// written bytes.
1920 ///
1921 /// ⚠️ Files might be cached in memory by your OS, meaning that reading/writing them might not
1922 /// increase the `read_bytes`/`written_bytes` values. You can find more information about it
1923 /// in the `proc_pid_io` manual (`man proc_pid_io` on unix platforms).
1924 ///
1925 /// ```no_run
1926 /// use sysinfo::{Pid, System};
1927 ///
1928 /// let s = System::new_all();
1929 /// if let Some(process) = s.process(Pid::from(1337)) {
1930 /// let disk_usage = process.disk_usage();
1931 /// println!("read bytes : new/total => {}/{}",
1932 /// disk_usage.read_bytes,
1933 /// disk_usage.total_read_bytes,
1934 /// );
1935 /// println!("written bytes: new/total => {}/{}",
1936 /// disk_usage.written_bytes,
1937 /// disk_usage.total_written_bytes,
1938 /// );
1939 /// }
1940 /// ```
1941 pub fn disk_usage(&self) -> DiskUsage {
1942 self.inner.disk_usage()
1943 }
1944
1945 /// Returns the ID of the owner user of this process or `None` if this
1946 /// information couldn't be retrieved. If you want to get the [`User`] from
1947 /// it, take a look at [`Users::get_user_by_id`].
1948 ///
1949 /// [`User`]: crate::User
1950 /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1951 ///
1952 /// ```no_run
1953 /// use sysinfo::{Pid, System};
1954 ///
1955 /// let mut s = System::new_all();
1956 ///
1957 /// if let Some(process) = s.process(Pid::from(1337)) {
1958 /// println!("User id for process 1337: {:?}", process.user_id());
1959 /// }
1960 /// ```
1961 pub fn user_id(&self) -> Option<&Uid> {
1962 self.inner.user_id()
1963 }
1964
1965 /// Returns the user ID of the effective owner of this process or `None` if
1966 /// this information couldn't be retrieved. If you want to get the [`User`]
1967 /// from it, take a look at [`Users::get_user_by_id`].
1968 ///
1969 /// If you run something with `sudo`, the real user ID of the launched
1970 /// process will be the ID of the user you are logged in as but effective
1971 /// user ID will be `0` (i-e root).
1972 ///
1973 /// ⚠️ It always returns `None` on Windows.
1974 ///
1975 /// [`User`]: crate::User
1976 /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1977 ///
1978 /// ```no_run
1979 /// use sysinfo::{Pid, System};
1980 ///
1981 /// let mut s = System::new_all();
1982 ///
1983 /// if let Some(process) = s.process(Pid::from(1337)) {
1984 /// println!("User id for process 1337: {:?}", process.effective_user_id());
1985 /// }
1986 /// ```
1987 pub fn effective_user_id(&self) -> Option<&Uid> {
1988 self.inner.effective_user_id()
1989 }
1990
1991 /// Returns the process group ID of the process.
1992 ///
1993 /// ⚠️ It always returns `None` on Windows.
1994 ///
1995 /// ```no_run
1996 /// use sysinfo::{Pid, System};
1997 ///
1998 /// let mut s = System::new_all();
1999 ///
2000 /// if let Some(process) = s.process(Pid::from(1337)) {
2001 /// println!("Group ID for process 1337: {:?}", process.group_id());
2002 /// }
2003 /// ```
2004 pub fn group_id(&self) -> Option<Gid> {
2005 self.inner.group_id()
2006 }
2007
2008 /// Returns the effective group ID of the process.
2009 ///
2010 /// If you run something with `sudo`, the real group ID of the launched
2011 /// process will be the primary group ID you are logged in as but effective
2012 /// group ID will be `0` (i-e root).
2013 ///
2014 /// ⚠️ It always returns `None` on Windows.
2015 ///
2016 /// ```no_run
2017 /// use sysinfo::{Pid, System};
2018 ///
2019 /// let mut s = System::new_all();
2020 ///
2021 /// if let Some(process) = s.process(Pid::from(1337)) {
2022 /// println!("User id for process 1337: {:?}", process.effective_group_id());
2023 /// }
2024 /// ```
2025 pub fn effective_group_id(&self) -> Option<Gid> {
2026 self.inner.effective_group_id()
2027 }
2028
2029 /// Returns the session ID for the current process or `None` if it couldn't
2030 /// be retrieved.
2031 ///
2032 /// ⚠️ This information is computed every time this method is called.
2033 ///
2034 /// ```no_run
2035 /// use sysinfo::{Pid, System};
2036 ///
2037 /// let mut s = System::new_all();
2038 ///
2039 /// if let Some(process) = s.process(Pid::from(1337)) {
2040 /// println!("Session ID for process 1337: {:?}", process.session_id());
2041 /// }
2042 /// ```
2043 pub fn session_id(&self) -> Option<Pid> {
2044 self.inner.session_id()
2045 }
2046
2047 /// Tasks run by this process. If there are none, returns `None`.
2048 ///
2049 /// ⚠️ This method always returns `None` on other platforms than Linux.
2050 ///
2051 /// ```no_run
2052 /// use sysinfo::{Pid, System};
2053 ///
2054 /// let mut s = System::new_all();
2055 ///
2056 /// if let Some(process) = s.process(Pid::from(1337)) {
2057 /// if let Some(tasks) = process.tasks() {
2058 /// println!("Listing tasks for process {:?}", process.pid());
2059 /// for task_pid in tasks {
2060 /// if let Some(task) = s.process(*task_pid) {
2061 /// println!("Task {:?}: {:?}", task.pid(), task.name());
2062 /// }
2063 /// }
2064 /// }
2065 /// }
2066 /// ```
2067 pub fn tasks(&self) -> Option<&HashSet<Pid>> {
2068 cfg_if! {
2069 if #[cfg(all(
2070 any(target_os = "linux", target_os = "android"),
2071 not(feature = "unknown-ci")
2072 ))] {
2073 self.inner.tasks.as_ref()
2074 } else {
2075 None
2076 }
2077 }
2078 }
2079
2080 /// If the process is a thread, it'll return `Some` with the kind of thread it is. Returns
2081 /// `None` otherwise.
2082 ///
2083 /// ⚠️ This method always returns `None` on other platforms than Linux.
2084 ///
2085 /// ```no_run
2086 /// use sysinfo::System;
2087 ///
2088 /// let s = System::new_all();
2089 ///
2090 /// for (_, process) in s.processes() {
2091 /// if let Some(thread_kind) = process.thread_kind() {
2092 /// println!("Process {:?} is a {thread_kind:?} thread", process.pid());
2093 /// }
2094 /// }
2095 /// ```
2096 pub fn thread_kind(&self) -> Option<ThreadKind> {
2097 cfg_if! {
2098 if #[cfg(all(
2099 any(target_os = "linux", target_os = "android"),
2100 not(feature = "unknown-ci")
2101 ))] {
2102 self.inner.thread_kind()
2103 } else {
2104 None
2105 }
2106 }
2107 }
2108
2109 /// Returns `true` if the process doesn't exist anymore but was not yet removed from
2110 /// the processes list because the `remove_dead_processes` argument was set to `false`
2111 /// in methods like [`System::refresh_processes`].
2112 ///
2113 /// ```no_run
2114 /// use sysinfo::{ProcessesToUpdate, System};
2115 ///
2116 /// let mut s = System::new_all();
2117 /// // We set the `remove_dead_processes` to `false`.
2118 /// s.refresh_processes(ProcessesToUpdate::All, false);
2119 ///
2120 /// for (_, process) in s.processes() {
2121 /// println!(
2122 /// "Process {:?} {}",
2123 /// process.pid(),
2124 /// if process.exists() { "exists" } else { "doesn't exist" },
2125 /// );
2126 /// }
2127 /// ```
2128 pub fn exists(&self) -> bool {
2129 self.inner.exists()
2130 }
2131
2132 /// Returns the number of open files in the current process.
2133 ///
2134 /// Returns `None` if it failed retrieving the information or if the current system is not
2135 /// supported.
2136 ///
2137 /// **Important**: this information is computed every time this function is called.
2138 ///
2139 /// ```no_run
2140 /// use sysinfo::System;
2141 ///
2142 /// let s = System::new_all();
2143 ///
2144 /// for (_, process) in s.processes() {
2145 /// println!(
2146 /// "Process {:?} {:?}",
2147 /// process.pid(),
2148 /// process.open_files(),
2149 /// );
2150 /// }
2151 /// ```
2152 pub fn open_files(&self) -> Option<usize> {
2153 self.inner.open_files()
2154 }
2155
2156 /// Returns the maximum number of open files for the current process.
2157 ///
2158 /// Returns `None` if it failed retrieving the information or if the current system is not
2159 /// supported.
2160 ///
2161 /// **Important**: this information is computed every time this function is called.
2162 ///
2163 /// ```no_run
2164 /// use sysinfo::System;
2165 ///
2166 /// let s = System::new_all();
2167 ///
2168 /// for (_, process) in s.processes() {
2169 /// println!(
2170 /// "Process {:?} {:?}",
2171 /// process.pid(),
2172 /// process.open_files_limit(),
2173 /// );
2174 /// }
2175 /// ```
2176 pub fn open_files_limit(&self) -> Option<usize> {
2177 self.inner.open_files_limit()
2178 }
2179}
2180
2181macro_rules! pid_decl {
2182 ($typ:ty) => {
2183 #[doc = include_str!("../../md_doc/pid.md")]
2184 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
2185 #[repr(transparent)]
2186 pub struct Pid(pub(crate) $typ);
2187
2188 impl From<usize> for Pid {
2189 fn from(v: usize) -> Self {
2190 Self(v as _)
2191 }
2192 }
2193 impl From<Pid> for usize {
2194 fn from(v: Pid) -> Self {
2195 v.0 as _
2196 }
2197 }
2198 impl FromStr for Pid {
2199 type Err = <$typ as FromStr>::Err;
2200 fn from_str(s: &str) -> Result<Self, Self::Err> {
2201 Ok(Self(<$typ>::from_str(s)?))
2202 }
2203 }
2204 impl fmt::Display for Pid {
2205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2206 write!(f, "{}", self.0)
2207 }
2208 }
2209 impl Pid {
2210 /// Allows to convert [`Pid`][crate::Pid] into [`u32`].
2211 ///
2212 /// ```
2213 /// use sysinfo::Pid;
2214 ///
2215 /// let pid = Pid::from_u32(0);
2216 /// let value: u32 = pid.as_u32();
2217 /// ```
2218 pub fn as_u32(self) -> u32 {
2219 self.0 as _
2220 }
2221 /// Allows to convert a [`u32`] into [`Pid`][crate::Pid].
2222 ///
2223 /// ```
2224 /// use sysinfo::Pid;
2225 ///
2226 /// let pid = Pid::from_u32(0);
2227 /// ```
2228 pub fn from_u32(v: u32) -> Self {
2229 Self(v as _)
2230 }
2231 }
2232 };
2233}
2234
2235cfg_if! {
2236 if #[cfg(all(
2237 not(feature = "unknown-ci"),
2238 any(
2239 target_os = "freebsd",
2240 target_os = "linux",
2241 target_os = "android",
2242 target_os = "macos",
2243 target_os = "ios",
2244 )
2245 ))] {
2246 use libc::pid_t;
2247
2248 pid_decl!(pid_t);
2249 } else {
2250 pid_decl!(usize);
2251 }
2252}
2253
2254/// This enum allows you to specify when you want the related information to be updated.
2255///
2256/// For example if you only want the [`Process::exe()`] information to be refreshed only if it's not
2257/// already set:
2258///
2259/// ```no_run
2260/// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System, UpdateKind};
2261///
2262/// let mut system = System::new();
2263/// system.refresh_processes_specifics(
2264/// ProcessesToUpdate::All,
2265/// true,
2266/// ProcessRefreshKind::nothing().with_exe(UpdateKind::OnlyIfNotSet),
2267/// );
2268/// ```
2269#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2270pub enum UpdateKind {
2271 /// Never update the related information.
2272 #[default]
2273 Never,
2274 /// Always update the related information.
2275 Always,
2276 /// Only update the related information if it was not already set at least once.
2277 OnlyIfNotSet,
2278}
2279
2280impl UpdateKind {
2281 /// If `self` is `OnlyIfNotSet`, `f` is called and its returned value is returned.
2282 #[allow(dead_code)] // Needed for unsupported targets.
2283 pub(crate) fn needs_update(self, f: impl Fn() -> bool) -> bool {
2284 match self {
2285 Self::Never => false,
2286 Self::Always => true,
2287 Self::OnlyIfNotSet => f(),
2288 }
2289 }
2290}
2291
2292/// This enum allows you to specify if you want all processes to be updated or just
2293/// some of them.
2294///
2295/// Example:
2296///
2297/// ```no_run
2298/// use sysinfo::{ProcessesToUpdate, System, get_current_pid};
2299///
2300/// let mut system = System::new();
2301/// // To refresh all processes:
2302/// system.refresh_processes(ProcessesToUpdate::All, true);
2303///
2304/// // To refresh only the current one:
2305/// system.refresh_processes(
2306/// ProcessesToUpdate::Some(&[get_current_pid().unwrap()]),
2307/// true,
2308/// );
2309/// ```
2310#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2311pub enum ProcessesToUpdate<'a> {
2312 /// To refresh all processes.
2313 All,
2314 /// To refresh only the processes with the listed [`Pid`].
2315 ///
2316 /// [`Pid`]: crate::Pid
2317 Some(&'a [Pid]),
2318}
2319
2320/// Used to determine what you want to refresh specifically on the [`Process`] type.
2321///
2322/// When all refresh are ruled out, a [`Process`] will still retrieve the following information:
2323/// * Process ID ([`Pid`])
2324/// * Parent process ID (on Windows it never changes though)
2325/// * Process name
2326/// * Start time
2327///
2328/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2329/// the information won't be retrieved if the information is accessible without needing
2330/// extra computation.
2331///
2332/// ⚠️ ** Linux Specific ** ⚠️
2333/// When using `ProcessRefreshKind::everything()`, in linux we will fetch all relevant
2334/// information from `/proc/<pid>/` as well as all the information from `/proc/<pid>/task/<tid>/`
2335/// folders. This makes the refresh mechanism a lot slower depending on the number of tasks
2336/// each process has.
2337///
2338/// If you don't care about tasks information, use `ProcessRefreshKind::everything().without_tasks()`
2339/// as much as possible.
2340///
2341/// ```
2342/// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System};
2343///
2344/// let mut system = System::new();
2345///
2346/// // We don't want to update the CPU information.
2347/// system.refresh_processes_specifics(
2348/// ProcessesToUpdate::All,
2349/// true,
2350/// ProcessRefreshKind::everything().without_cpu(),
2351/// );
2352///
2353/// for (_, proc_) in system.processes() {
2354/// // We use a `==` comparison on float only because we know it's set to 0 here.
2355/// assert_eq!(proc_.cpu_usage(), 0.);
2356/// }
2357/// ```
2358///
2359/// [`Process`]: crate::Process
2360#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2361pub struct ProcessRefreshKind {
2362 cpu: bool,
2363 disk_usage: bool,
2364 memory: bool,
2365 user: UpdateKind,
2366 cwd: UpdateKind,
2367 root: UpdateKind,
2368 environ: UpdateKind,
2369 cmd: UpdateKind,
2370 exe: UpdateKind,
2371 tasks: bool,
2372}
2373
2374/// Creates a new `ProcessRefreshKind` with every refresh set to `false`, except for `tasks`.
2375/// By default, we want to list all processes and tasks are considered processes on their own
2376/// in linux so we still fetch them by default. However, the processes information are not
2377/// refreshed.
2378impl Default for ProcessRefreshKind {
2379 fn default() -> Self {
2380 Self {
2381 cpu: false,
2382 disk_usage: false,
2383 memory: false,
2384 user: UpdateKind::default(),
2385 cwd: UpdateKind::default(),
2386 root: UpdateKind::default(),
2387 environ: UpdateKind::default(),
2388 cmd: UpdateKind::default(),
2389 exe: UpdateKind::default(),
2390 tasks: true, // Process by default includes all tasks.
2391 }
2392 }
2393}
2394
2395impl ProcessRefreshKind {
2396 /// Creates a new `ProcessRefreshKind` with every refresh set to `false`, except for `tasks`.
2397 /// By default, we want to list all processes and tasks are considered processes on their own
2398 /// in linux so we still fetch them by default. However, the processes information are not
2399 /// refreshed.
2400 /// ```
2401 /// use sysinfo::{ProcessRefreshKind, UpdateKind};
2402 ///
2403 /// let r = ProcessRefreshKind::nothing();
2404 ///
2405 /// assert_eq!(r.cpu(), false);
2406 /// assert_eq!(r.user(), UpdateKind::Never);
2407 /// ```
2408 pub fn nothing() -> Self {
2409 Self::default()
2410 }
2411
2412 /// Creates a new `ProcessRefreshKind` with every refresh set to `true` or
2413 /// [`UpdateKind::OnlyIfNotSet`].
2414 ///
2415 /// ```
2416 /// use sysinfo::{ProcessRefreshKind, UpdateKind};
2417 ///
2418 /// let r = ProcessRefreshKind::everything();
2419 ///
2420 /// assert_eq!(r.cpu(), true);
2421 /// assert_eq!(r.user(), UpdateKind::OnlyIfNotSet);
2422 /// ```
2423 pub fn everything() -> Self {
2424 Self {
2425 cpu: true,
2426 disk_usage: true,
2427 memory: true,
2428 user: UpdateKind::OnlyIfNotSet,
2429 cwd: UpdateKind::OnlyIfNotSet,
2430 root: UpdateKind::OnlyIfNotSet,
2431 environ: UpdateKind::OnlyIfNotSet,
2432 cmd: UpdateKind::OnlyIfNotSet,
2433 exe: UpdateKind::OnlyIfNotSet,
2434 tasks: true,
2435 }
2436 }
2437
2438 impl_get_set!(
2439 ProcessRefreshKind,
2440 cpu,
2441 with_cpu,
2442 without_cpu,
2443 "\
2444It will retrieve both CPU usage and CPU accumulated time,"
2445 );
2446 impl_get_set!(
2447 ProcessRefreshKind,
2448 disk_usage,
2449 with_disk_usage,
2450 without_disk_usage
2451 );
2452 impl_get_set!(
2453 ProcessRefreshKind,
2454 user,
2455 with_user,
2456 without_user,
2457 UpdateKind,
2458 "\
2459It will retrieve the following information:
2460
2461 * user ID
2462 * user effective ID (if available on the platform)
2463 * user group ID (if available on the platform)
2464 * user effective ID (if available on the platform)"
2465 );
2466 impl_get_set!(ProcessRefreshKind, memory, with_memory, without_memory);
2467 impl_get_set!(ProcessRefreshKind, cwd, with_cwd, without_cwd, UpdateKind);
2468 impl_get_set!(
2469 ProcessRefreshKind,
2470 root,
2471 with_root,
2472 without_root,
2473 UpdateKind
2474 );
2475 impl_get_set!(
2476 ProcessRefreshKind,
2477 environ,
2478 with_environ,
2479 without_environ,
2480 UpdateKind
2481 );
2482 impl_get_set!(ProcessRefreshKind, cmd, with_cmd, without_cmd, UpdateKind);
2483 impl_get_set!(ProcessRefreshKind, exe, with_exe, without_exe, UpdateKind);
2484 impl_get_set!(ProcessRefreshKind, tasks, with_tasks, without_tasks);
2485}
2486
2487/// Used to determine what you want to refresh specifically on the [`Cpu`] type.
2488///
2489/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2490/// the information won't be retrieved if the information is accessible without needing
2491/// extra computation.
2492///
2493/// ```
2494/// use sysinfo::{CpuRefreshKind, System};
2495///
2496/// let mut system = System::new();
2497///
2498/// // We don't want to update all the CPU information.
2499/// system.refresh_cpu_specifics(CpuRefreshKind::everything().without_frequency());
2500///
2501/// for cpu in system.cpus() {
2502/// assert_eq!(cpu.frequency(), 0);
2503/// }
2504/// ```
2505///
2506/// [`Cpu`]: crate::Cpu
2507#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2508pub struct CpuRefreshKind {
2509 cpu_usage: bool,
2510 frequency: bool,
2511}
2512
2513impl CpuRefreshKind {
2514 /// Creates a new `CpuRefreshKind` with every refresh set to `false`.
2515 ///
2516 /// ```
2517 /// use sysinfo::CpuRefreshKind;
2518 ///
2519 /// let r = CpuRefreshKind::nothing();
2520 ///
2521 /// assert_eq!(r.frequency(), false);
2522 /// assert_eq!(r.cpu_usage(), false);
2523 /// ```
2524 pub fn nothing() -> Self {
2525 Self::default()
2526 }
2527
2528 /// Creates a new `CpuRefreshKind` with every refresh set to `true`.
2529 ///
2530 /// ```
2531 /// use sysinfo::CpuRefreshKind;
2532 ///
2533 /// let r = CpuRefreshKind::everything();
2534 ///
2535 /// assert_eq!(r.frequency(), true);
2536 /// assert_eq!(r.cpu_usage(), true);
2537 /// ```
2538 pub fn everything() -> Self {
2539 Self {
2540 cpu_usage: true,
2541 frequency: true,
2542 }
2543 }
2544
2545 impl_get_set!(CpuRefreshKind, cpu_usage, with_cpu_usage, without_cpu_usage);
2546 impl_get_set!(CpuRefreshKind, frequency, with_frequency, without_frequency);
2547}
2548
2549/// Used to determine which memory you want to refresh specifically.
2550///
2551/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2552/// the information won't be retrieved if the information is accessible without needing
2553/// extra computation.
2554///
2555/// ```
2556/// use sysinfo::{MemoryRefreshKind, System};
2557///
2558/// let mut system = System::new();
2559///
2560/// // We don't want to update all memories information.
2561/// system.refresh_memory_specifics(MemoryRefreshKind::nothing().with_ram());
2562///
2563/// println!("total RAM: {}", system.total_memory());
2564/// println!("free RAM: {}", system.free_memory());
2565/// ```
2566#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2567pub struct MemoryRefreshKind {
2568 ram: bool,
2569 swap: bool,
2570}
2571
2572impl MemoryRefreshKind {
2573 /// Creates a new `MemoryRefreshKind` with every refresh set to `false`.
2574 ///
2575 /// ```
2576 /// use sysinfo::MemoryRefreshKind;
2577 ///
2578 /// let r = MemoryRefreshKind::nothing();
2579 ///
2580 /// assert_eq!(r.ram(), false);
2581 /// assert_eq!(r.swap(), false);
2582 /// ```
2583 pub fn nothing() -> Self {
2584 Self::default()
2585 }
2586
2587 /// Creates a new `MemoryRefreshKind` with every refresh set to `true`.
2588 ///
2589 /// ```
2590 /// use sysinfo::MemoryRefreshKind;
2591 ///
2592 /// let r = MemoryRefreshKind::everything();
2593 ///
2594 /// assert_eq!(r.ram(), true);
2595 /// assert_eq!(r.swap(), true);
2596 /// ```
2597 pub fn everything() -> Self {
2598 Self {
2599 ram: true,
2600 swap: true,
2601 }
2602 }
2603
2604 impl_get_set!(MemoryRefreshKind, ram, with_ram, without_ram);
2605 impl_get_set!(MemoryRefreshKind, swap, with_swap, without_swap);
2606}
2607
2608/// Used to determine what you want to refresh specifically on the [`System`][crate::System] type.
2609///
2610/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2611/// the information won't be retrieved if the information is accessible without needing
2612/// extra computation.
2613///
2614/// ```
2615/// use sysinfo::{RefreshKind, System};
2616///
2617/// // We want everything except memory.
2618/// let mut system = System::new_with_specifics(RefreshKind::everything().without_memory());
2619///
2620/// assert_eq!(system.total_memory(), 0);
2621/// # if sysinfo::IS_SUPPORTED_SYSTEM && !cfg!(feature = "apple-sandbox") {
2622/// assert!(system.processes().len() > 0);
2623/// # }
2624/// ```
2625#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2626pub struct RefreshKind {
2627 processes: Option<ProcessRefreshKind>,
2628 memory: Option<MemoryRefreshKind>,
2629 cpu: Option<CpuRefreshKind>,
2630}
2631
2632impl RefreshKind {
2633 /// Creates a new `RefreshKind` with every refresh set to `false`/`None`.
2634 ///
2635 /// ```
2636 /// use sysinfo::RefreshKind;
2637 ///
2638 /// let r = RefreshKind::nothing();
2639 ///
2640 /// assert_eq!(r.processes().is_some(), false);
2641 /// assert_eq!(r.memory().is_some(), false);
2642 /// assert_eq!(r.cpu().is_some(), false);
2643 /// ```
2644 pub fn nothing() -> Self {
2645 Self::default()
2646 }
2647
2648 /// Creates a new `RefreshKind` with every refresh set to `true`/`Some(...)`.
2649 ///
2650 /// ```
2651 /// use sysinfo::RefreshKind;
2652 ///
2653 /// let r = RefreshKind::everything();
2654 ///
2655 /// assert_eq!(r.processes().is_some(), true);
2656 /// assert_eq!(r.memory().is_some(), true);
2657 /// assert_eq!(r.cpu().is_some(), true);
2658 /// ```
2659 pub fn everything() -> Self {
2660 Self {
2661 processes: Some(ProcessRefreshKind::everything()),
2662 memory: Some(MemoryRefreshKind::everything()),
2663 cpu: Some(CpuRefreshKind::everything()),
2664 }
2665 }
2666
2667 impl_get_set!(
2668 RefreshKind,
2669 processes,
2670 with_processes,
2671 without_processes,
2672 ProcessRefreshKind
2673 );
2674 impl_get_set!(
2675 RefreshKind,
2676 memory,
2677 with_memory,
2678 without_memory,
2679 MemoryRefreshKind
2680 );
2681 impl_get_set!(RefreshKind, cpu, with_cpu, without_cpu, CpuRefreshKind);
2682}
2683
2684/// Returns the pid for the current process.
2685///
2686/// `Err` is returned in case the platform isn't supported.
2687///
2688/// ```no_run
2689/// use sysinfo::get_current_pid;
2690///
2691/// match get_current_pid() {
2692/// Ok(pid) => {
2693/// println!("current pid: {}", pid);
2694/// }
2695/// Err(e) => {
2696/// println!("failed to get current pid: {}", e);
2697/// }
2698/// }
2699/// ```
2700#[allow(clippy::unnecessary_wraps)]
2701pub fn get_current_pid() -> Result<Pid, &'static str> {
2702 cfg_if! {
2703 if #[cfg(feature = "unknown-ci")] {
2704 fn inner() -> Result<Pid, &'static str> {
2705 Err("Unknown platform (CI)")
2706 }
2707 } else if #[cfg(any(
2708 target_os = "freebsd",
2709 target_os = "linux",
2710 target_os = "android",
2711 target_os = "macos",
2712 target_os = "ios",
2713 ))] {
2714 fn inner() -> Result<Pid, &'static str> {
2715 unsafe { Ok(Pid(libc::getpid())) }
2716 }
2717 } else if #[cfg(windows)] {
2718 fn inner() -> Result<Pid, &'static str> {
2719 use windows::Win32::System::Threading::GetCurrentProcessId;
2720
2721 unsafe { Ok(Pid(GetCurrentProcessId() as _)) }
2722 }
2723 } else {
2724 fn inner() -> Result<Pid, &'static str> {
2725 Err("Unknown platform")
2726 }
2727 }
2728 }
2729 inner()
2730}
2731
2732/// Contains all the methods of the [`Cpu`][crate::Cpu] struct.
2733///
2734/// ```no_run
2735/// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2736///
2737/// let mut s = System::new_with_specifics(
2738/// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2739/// );
2740///
2741/// // Wait a bit because CPU usage is based on diff.
2742/// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
2743/// // Refresh CPUs again to get actual value.
2744/// s.refresh_cpu_all();
2745///
2746/// for cpu in s.cpus() {
2747/// println!("{}%", cpu.cpu_usage());
2748/// }
2749/// ```
2750pub struct Cpu {
2751 pub(crate) inner: CpuInner,
2752}
2753
2754impl Cpu {
2755 /// Returns this CPU's usage.
2756 ///
2757 /// Note: You'll need to refresh it at least twice (diff between the first and the second is
2758 /// how CPU usage is computed) at first if you want to have a non-zero value.
2759 ///
2760 /// ```no_run
2761 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2762 ///
2763 /// let mut s = System::new_with_specifics(
2764 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2765 /// );
2766 ///
2767 /// // Wait a bit because CPU usage is based on diff.
2768 /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
2769 /// // Refresh CPUs again to get actual value.
2770 /// s.refresh_cpu_all();
2771 ///
2772 /// for cpu in s.cpus() {
2773 /// println!("{}%", cpu.cpu_usage());
2774 /// }
2775 /// ```
2776 pub fn cpu_usage(&self) -> f32 {
2777 self.inner.cpu_usage()
2778 }
2779
2780 /// Returns this CPU's name.
2781 ///
2782 /// ```no_run
2783 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2784 ///
2785 /// let s = System::new_with_specifics(
2786 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2787 /// );
2788 /// for cpu in s.cpus() {
2789 /// println!("{}", cpu.name());
2790 /// }
2791 /// ```
2792 pub fn name(&self) -> &str {
2793 self.inner.name()
2794 }
2795
2796 /// Returns the CPU's vendor id.
2797 ///
2798 /// ```no_run
2799 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2800 ///
2801 /// let s = System::new_with_specifics(
2802 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2803 /// );
2804 /// for cpu in s.cpus() {
2805 /// println!("{}", cpu.vendor_id());
2806 /// }
2807 /// ```
2808 pub fn vendor_id(&self) -> &str {
2809 self.inner.vendor_id()
2810 }
2811
2812 /// Returns the CPU's brand.
2813 ///
2814 /// ```no_run
2815 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2816 ///
2817 /// let s = System::new_with_specifics(
2818 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2819 /// );
2820 /// for cpu in s.cpus() {
2821 /// println!("{}", cpu.brand());
2822 /// }
2823 /// ```
2824 pub fn brand(&self) -> &str {
2825 self.inner.brand()
2826 }
2827
2828 /// Returns the CPU's frequency.
2829 ///
2830 /// ```no_run
2831 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2832 ///
2833 /// let s = System::new_with_specifics(
2834 /// RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2835 /// );
2836 /// for cpu in s.cpus() {
2837 /// println!("{}", cpu.frequency());
2838 /// }
2839 /// ```
2840 pub fn frequency(&self) -> u64 {
2841 self.inner.frequency()
2842 }
2843}
2844
2845#[cfg(test)]
2846mod test {
2847 use crate::*;
2848 use std::str::FromStr;
2849
2850 // In case `Process::updated` is misused, `System::refresh_processes` might remove them
2851 // so this test ensures that it doesn't happen.
2852 #[test]
2853 fn check_refresh_process_update() {
2854 if !IS_SUPPORTED_SYSTEM {
2855 return;
2856 }
2857 let mut s = System::new_all();
2858 let total = s.processes().len() as isize;
2859 s.refresh_processes(ProcessesToUpdate::All, false);
2860 let new_total = s.processes().len() as isize;
2861 // There should be almost no difference in the processes count.
2862 assert!(
2863 (new_total - total).abs() <= 5,
2864 "{} <= 5",
2865 (new_total - total).abs()
2866 );
2867 }
2868
2869 #[test]
2870 fn check_cpu_arch() {
2871 assert!(!System::cpu_arch().is_empty());
2872 }
2873
2874 // Ensure that the CPUs frequency isn't retrieved until we ask for it.
2875 #[test]
2876 fn check_cpu_frequency() {
2877 if !IS_SUPPORTED_SYSTEM {
2878 return;
2879 }
2880 let mut s = System::new();
2881 s.refresh_processes(ProcessesToUpdate::All, false);
2882 for proc_ in s.cpus() {
2883 assert_eq!(proc_.frequency(), 0);
2884 }
2885 s.refresh_cpu_usage();
2886 for proc_ in s.cpus() {
2887 assert_eq!(proc_.frequency(), 0);
2888 }
2889 // In a VM, it'll fail.
2890 if std::env::var("APPLE_CI").is_err() && std::env::var("FREEBSD_CI").is_err() {
2891 s.refresh_cpu_specifics(CpuRefreshKind::everything());
2892 for proc_ in s.cpus() {
2893 assert_ne!(proc_.frequency(), 0);
2894 }
2895 }
2896 }
2897
2898 #[test]
2899 fn check_process_memory_usage() {
2900 let mut s = System::new();
2901 s.refresh_specifics(RefreshKind::everything());
2902
2903 if IS_SUPPORTED_SYSTEM {
2904 // No process should have 0 as memory usage.
2905 #[cfg(not(feature = "apple-sandbox"))]
2906 assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
2907 } else {
2908 // There should be no process, but if there is one, its memory usage should be 0.
2909 assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
2910 }
2911 }
2912
2913 #[test]
2914 fn check_system_implemented_traits() {
2915 fn check<T: Sized + std::fmt::Debug + Default + Send + Sync>(_: T) {}
2916
2917 check(System::new());
2918 }
2919
2920 #[test]
2921 fn check_memory_usage() {
2922 let mut s = System::new();
2923
2924 assert_eq!(s.total_memory(), 0);
2925 assert_eq!(s.free_memory(), 0);
2926 assert_eq!(s.available_memory(), 0);
2927 assert_eq!(s.used_memory(), 0);
2928 assert_eq!(s.total_swap(), 0);
2929 assert_eq!(s.free_swap(), 0);
2930 assert_eq!(s.used_swap(), 0);
2931
2932 s.refresh_memory();
2933 if IS_SUPPORTED_SYSTEM {
2934 assert!(s.total_memory() > 0);
2935 assert!(s.used_memory() > 0);
2936 if s.total_swap() > 0 {
2937 // I think it's pretty safe to assume that there is still some swap left...
2938 assert!(s.free_swap() > 0);
2939 }
2940 } else {
2941 assert_eq!(s.total_memory(), 0);
2942 assert_eq!(s.used_memory(), 0);
2943 assert_eq!(s.total_swap(), 0);
2944 assert_eq!(s.free_swap(), 0);
2945 }
2946 }
2947
2948 #[cfg(target_os = "linux")]
2949 #[test]
2950 fn check_processes_cpu_usage() {
2951 if !IS_SUPPORTED_SYSTEM {
2952 return;
2953 }
2954 let mut s = System::new();
2955
2956 s.refresh_processes(ProcessesToUpdate::All, false);
2957 // All CPU usage will start at zero until the second refresh
2958 assert!(s
2959 .processes()
2960 .iter()
2961 .all(|(_, proc_)| proc_.cpu_usage() == 0.0));
2962
2963 // Wait a bit to update CPU usage values
2964 std::thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
2965 s.refresh_processes(ProcessesToUpdate::All, true);
2966 assert!(s
2967 .processes()
2968 .iter()
2969 .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
2970 && proc_.cpu_usage() <= (s.cpus().len() as f32) * 100.0));
2971 assert!(s
2972 .processes()
2973 .iter()
2974 .any(|(_, proc_)| proc_.cpu_usage() > 0.0));
2975 }
2976
2977 #[test]
2978 fn check_cpu_usage() {
2979 if !IS_SUPPORTED_SYSTEM {
2980 return;
2981 }
2982 let mut s = System::new();
2983 for _ in 0..10 {
2984 s.refresh_cpu_usage();
2985 // Wait a bit to update CPU usage values
2986 std::thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
2987 if s.cpus().iter().any(|c| c.cpu_usage() > 0.0) {
2988 // All good!
2989 return;
2990 }
2991 }
2992 panic!("CPU usage is always zero...");
2993 }
2994
2995 #[test]
2996 fn check_system_info() {
2997 // We don't want to test on unsupported systems.
2998 if IS_SUPPORTED_SYSTEM {
2999 assert!(!System::name()
3000 .expect("Failed to get system name")
3001 .is_empty());
3002
3003 assert!(!System::kernel_version()
3004 .expect("Failed to get kernel version")
3005 .is_empty());
3006
3007 assert!(!System::os_version()
3008 .expect("Failed to get os version")
3009 .is_empty());
3010
3011 assert!(!System::long_os_version()
3012 .expect("Failed to get long OS version")
3013 .is_empty());
3014 }
3015
3016 assert!(!System::distribution_id().is_empty());
3017 }
3018
3019 #[test]
3020 fn check_host_name() {
3021 // We don't want to test on unsupported systems.
3022 if IS_SUPPORTED_SYSTEM {
3023 assert!(System::host_name().is_some());
3024 }
3025 }
3026
3027 #[test]
3028 fn check_refresh_process_return_value() {
3029 // We don't want to test on unsupported systems.
3030 if IS_SUPPORTED_SYSTEM {
3031 let _pid = get_current_pid().expect("Failed to get current PID");
3032
3033 #[cfg(not(feature = "apple-sandbox"))]
3034 {
3035 let mut s = System::new();
3036 // First check what happens in case the process isn't already in our process list.
3037 assert_eq!(
3038 s.refresh_processes(ProcessesToUpdate::Some(&[_pid]), true),
3039 1
3040 );
3041 // Then check that it still returns 1 if the process is already in our process list.
3042 assert_eq!(
3043 s.refresh_processes(ProcessesToUpdate::Some(&[_pid]), true),
3044 1
3045 );
3046 }
3047 }
3048 }
3049
3050 #[test]
3051 fn check_cpus_number() {
3052 let mut s = System::new();
3053
3054 // This information isn't retrieved by default.
3055 assert!(s.cpus().is_empty());
3056 if IS_SUPPORTED_SYSTEM {
3057 // The physical cores count is recomputed every time the function is called, so the
3058 // information must be relevant even with nothing initialized.
3059 let physical_cores_count =
3060 System::physical_core_count().expect("failed to get number of physical cores");
3061
3062 s.refresh_cpu_usage();
3063 // The cpus shouldn't be empty anymore.
3064 assert!(!s.cpus().is_empty());
3065
3066 // In case we are running inside a VM, it's possible to not have a physical core, only
3067 // logical ones, which is why we don't test `physical_cores_count > 0`.
3068 let physical_cores_count2 =
3069 System::physical_core_count().expect("failed to get number of physical cores");
3070 assert!(physical_cores_count2 <= s.cpus().len());
3071 assert_eq!(physical_cores_count, physical_cores_count2);
3072 } else {
3073 assert_eq!(System::physical_core_count(), None);
3074 }
3075 assert!(System::physical_core_count().unwrap_or(0) <= s.cpus().len());
3076 }
3077
3078 // This test only exists to ensure that the `Display` and `Debug` traits are implemented on the
3079 // `ProcessStatus` enum on all targets.
3080 #[test]
3081 fn check_display_impl_process_status() {
3082 println!("{} {:?}", ProcessStatus::Parked, ProcessStatus::Idle);
3083 }
3084
3085 #[test]
3086 #[allow(clippy::unnecessary_fallible_conversions)]
3087 fn check_pid_from_impls() {
3088 assert!(crate::Pid::try_from(0usize).is_ok());
3089 // If it doesn't panic, it's fine.
3090 let _ = crate::Pid::from(0);
3091 assert!(crate::Pid::from_str("0").is_ok());
3092 }
3093
3094 #[test]
3095 #[allow(clippy::const_is_empty)]
3096 fn check_nb_supported_signals() {
3097 if IS_SUPPORTED_SYSTEM {
3098 assert!(
3099 !SUPPORTED_SIGNALS.is_empty(),
3100 "SUPPORTED_SIGNALS shouldn't be empty on supported systems!"
3101 );
3102 } else {
3103 assert!(
3104 SUPPORTED_SIGNALS.is_empty(),
3105 "SUPPORTED_SIGNALS should be empty on not support systems!"
3106 );
3107 }
3108 }
3109}
3110
3111#[cfg(doctest)]
3112mod doctest {
3113 // FIXME: Can be removed once negative trait bounds are supported.
3114 /// Check that `Process` doesn't implement `Clone`.
3115 ///
3116 /// First we check that the "basic" code works:
3117 ///
3118 /// ```no_run
3119 /// use sysinfo::{Process, System};
3120 ///
3121 /// let mut s = System::new_all();
3122 /// let p: &Process = s.processes().values().next().unwrap();
3123 /// ```
3124 ///
3125 /// And now we check if it fails when we try to clone it:
3126 ///
3127 /// ```compile_fail
3128 /// use sysinfo::{Process, System};
3129 ///
3130 /// let mut s = System::new_all();
3131 /// let p: &Process = s.processes().values().next().unwrap();
3132 /// let p = (*p).clone();
3133 /// ```
3134 mod process_clone {}
3135
3136 // FIXME: Can be removed once negative trait bounds are supported.
3137 /// Check that `System` doesn't implement `Clone`.
3138 ///
3139 /// First we check that the "basic" code works:
3140 ///
3141 /// ```no_run
3142 /// use sysinfo::{Process, System};
3143 ///
3144 /// let s = System::new();
3145 /// ```
3146 ///
3147 /// And now we check if it fails when we try to clone it:
3148 ///
3149 /// ```compile_fail
3150 /// use sysinfo::{Process, System};
3151 ///
3152 /// let s = System::new();
3153 /// let s = s.clone();
3154 /// ```
3155 mod system_clone {}
3156}