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, ProcessInner, SystemInner, Uid};
13
14/// Structs 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/// A struct representing system load average value.
920///
921/// It is returned by [`System::load_average`][crate::System::load_average].
922///
923/// ```no_run
924/// use sysinfo::System;
925///
926/// let load_avg = System::load_average();
927/// println!(
928///     "one minute: {}%, five minutes: {}%, fifteen minutes: {}%",
929///     load_avg.one,
930///     load_avg.five,
931///     load_avg.fifteen,
932/// );
933/// ```
934#[repr(C)]
935#[derive(Default, Debug, Clone)]
936pub struct LoadAvg {
937    /// Average load within one minute.
938    pub one: f64,
939    /// Average load within five minutes.
940    pub five: f64,
941    /// Average load within fifteen minutes.
942    pub fifteen: f64,
943}
944
945/// An enum representing signals on UNIX-like systems.
946///
947/// On non-unix systems, this enum is mostly useless and is only there to keep coherency between
948/// the different OSes.
949///
950/// If you want the list of the supported signals on the current system, use
951/// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
952#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
953#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
954pub enum Signal {
955    /// Hangup detected on controlling terminal or death of controlling process.
956    Hangup,
957    /// Interrupt from keyboard.
958    Interrupt,
959    /// Quit from keyboard.
960    Quit,
961    /// Illegal instruction.
962    Illegal,
963    /// Trace/breakpoint trap.
964    Trap,
965    /// Abort signal from C abort function.
966    Abort,
967    /// IOT trap. A synonym for SIGABRT.
968    IOT,
969    /// Bus error (bad memory access).
970    Bus,
971    /// Floating point exception.
972    FloatingPointException,
973    /// Kill signal.
974    Kill,
975    /// User-defined signal 1.
976    User1,
977    /// Invalid memory reference.
978    Segv,
979    /// User-defined signal 2.
980    User2,
981    /// Broken pipe: write to pipe with no readers.
982    Pipe,
983    /// Timer signal from C alarm function.
984    Alarm,
985    /// Termination signal.
986    Term,
987    /// Child stopped or terminated.
988    Child,
989    /// Continue if stopped.
990    Continue,
991    /// Stop process.
992    Stop,
993    /// Stop typed at terminal.
994    TSTP,
995    /// Terminal input for background process.
996    TTIN,
997    /// Terminal output for background process.
998    TTOU,
999    /// Urgent condition on socket.
1000    Urgent,
1001    /// CPU time limit exceeded.
1002    XCPU,
1003    /// File size limit exceeded.
1004    XFSZ,
1005    /// Virtual alarm clock.
1006    VirtualAlarm,
1007    /// Profiling time expired.
1008    Profiling,
1009    /// Windows resize signal.
1010    Winch,
1011    /// I/O now possible.
1012    IO,
1013    /// Pollable event (Sys V). Synonym for IO
1014    Poll,
1015    /// Power failure (System V).
1016    ///
1017    /// Doesn't exist on apple systems so will be ignored.
1018    Power,
1019    /// Bad argument to routine (SVr4).
1020    Sys,
1021}
1022
1023impl std::fmt::Display for Signal {
1024    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1025        let s = match *self {
1026            Self::Hangup => "Hangup",
1027            Self::Interrupt => "Interrupt",
1028            Self::Quit => "Quit",
1029            Self::Illegal => "Illegal",
1030            Self::Trap => "Trap",
1031            Self::Abort => "Abort",
1032            Self::IOT => "IOT",
1033            Self::Bus => "Bus",
1034            Self::FloatingPointException => "FloatingPointException",
1035            Self::Kill => "Kill",
1036            Self::User1 => "User1",
1037            Self::Segv => "Segv",
1038            Self::User2 => "User2",
1039            Self::Pipe => "Pipe",
1040            Self::Alarm => "Alarm",
1041            Self::Term => "Term",
1042            Self::Child => "Child",
1043            Self::Continue => "Continue",
1044            Self::Stop => "Stop",
1045            Self::TSTP => "TSTP",
1046            Self::TTIN => "TTIN",
1047            Self::TTOU => "TTOU",
1048            Self::Urgent => "Urgent",
1049            Self::XCPU => "XCPU",
1050            Self::XFSZ => "XFSZ",
1051            Self::VirtualAlarm => "VirtualAlarm",
1052            Self::Profiling => "Profiling",
1053            Self::Winch => "Winch",
1054            Self::IO => "IO",
1055            Self::Poll => "Poll",
1056            Self::Power => "Power",
1057            Self::Sys => "Sys",
1058        };
1059        f.write_str(s)
1060    }
1061}
1062
1063/// Contains memory limits for the current process.
1064#[derive(Default, Debug, Clone)]
1065pub struct CGroupLimits {
1066    /// Total memory (in bytes) for the current cgroup.
1067    pub total_memory: u64,
1068    /// Free memory (in bytes) for the current cgroup.
1069    pub free_memory: u64,
1070    /// Free swap (in bytes) for the current cgroup.
1071    pub free_swap: u64,
1072    /// Resident Set Size (RSS) (in bytes) for the current cgroup.
1073    pub rss: u64,
1074}
1075
1076/// Enum describing the different status of a process.
1077#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
1078#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1079pub enum ProcessStatus {
1080    /// ## Linux
1081    ///
1082    /// Idle kernel thread.
1083    ///
1084    /// ## macOs/FreeBSD
1085    ///
1086    /// Process being created by fork.
1087    ///
1088    /// ## Other OS
1089    ///
1090    /// Not available.
1091    Idle,
1092    /// Running.
1093    Run,
1094    /// ## Linux
1095    ///
1096    /// Sleeping in an interruptible waiting.
1097    ///
1098    /// ## macOS/FreeBSD
1099    ///
1100    /// Sleeping on an address.
1101    ///
1102    /// ## Other OS
1103    ///
1104    /// Not available.
1105    Sleep,
1106    /// ## Linux
1107    ///
1108    /// Stopped (on a signal) or (before Linux 2.6.33) trace stopped.
1109    ///
1110    /// ## macOS/FreeBSD
1111    ///
1112    /// Process debugging or suspension.
1113    ///
1114    /// ## Other OS
1115    ///
1116    /// Not available.
1117    Stop,
1118    /// ## Linux/FreeBSD/macOS
1119    ///
1120    /// Zombie process. Terminated but not reaped by its parent.
1121    ///
1122    /// ## Other OS
1123    ///
1124    /// Not available.
1125    Zombie,
1126    /// ## Linux
1127    ///
1128    /// Tracing stop (Linux 2.6.33 onward). Stopped by debugger during the tracing.
1129    ///
1130    /// ## Other OS
1131    ///
1132    /// Not available.
1133    Tracing,
1134    /// ## Linux
1135    ///
1136    /// Dead/uninterruptible sleep (usually IO).
1137    ///
1138    /// ## FreeBSD
1139    ///
1140    /// A process should never end up in this state.
1141    ///
1142    /// ## Other OS
1143    ///
1144    /// Not available.
1145    Dead,
1146    /// ## Linux
1147    ///
1148    /// Wakekill (Linux 2.6.33 to 3.13 only).
1149    ///
1150    /// ## Other OS
1151    ///
1152    /// Not available.
1153    Wakekill,
1154    /// ## Linux
1155    ///
1156    /// Waking (Linux 2.6.33 to 3.13 only).
1157    ///
1158    /// ## Other OS
1159    ///
1160    /// Not available.
1161    Waking,
1162    /// ## Linux
1163    ///
1164    /// Parked (Linux 3.9 to 3.13 only).
1165    ///
1166    /// ## macOS
1167    ///
1168    /// Halted at a clean point.
1169    ///
1170    /// ## Other OS
1171    ///
1172    /// Not available.
1173    Parked,
1174    /// ## FreeBSD
1175    ///
1176    /// Blocked on a lock.
1177    ///
1178    /// ## Other OS
1179    ///
1180    /// Not available.
1181    LockBlocked,
1182    /// ## Linux
1183    ///
1184    /// Waiting in uninterruptible disk sleep.
1185    ///
1186    /// ## Other OS
1187    ///
1188    /// Not available.
1189    UninterruptibleDiskSleep,
1190    /// Unknown.
1191    Unknown(u32),
1192}
1193
1194/// Enum describing the different kind of threads.
1195#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1196#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1197pub enum ThreadKind {
1198    /// Kernel thread.
1199    Kernel,
1200    /// User thread.
1201    Userland,
1202}
1203
1204/// Enum describing possible [`Process::kill_and_wait`] errors.
1205#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1206#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
1207pub enum KillError {
1208    /// This signal doesn't exist on this platform.
1209    SignalDoesNotExist,
1210    /// The signal failed to be sent to the target process.
1211    FailedToSendSignal,
1212}
1213
1214/// Struct containing information of a process.
1215///
1216/// ## iOS
1217///
1218/// This information cannot be retrieved on iOS due to sandboxing.
1219///
1220/// ## Apple app store
1221///
1222/// If you are building a macOS Apple app store, it won't be able
1223/// to retrieve this information.
1224///
1225/// ```no_run
1226/// use sysinfo::{Pid, System};
1227///
1228/// let s = System::new_all();
1229/// if let Some(process) = s.process(Pid::from(1337)) {
1230///     println!("{:?}", process.name());
1231/// }
1232/// ```
1233pub struct Process {
1234    pub(crate) inner: ProcessInner,
1235}
1236
1237impl Process {
1238    /// Sends [`Signal::Kill`] to the process (which is the only signal supported on all supported
1239    /// platforms by this crate).
1240    ///
1241    /// Returns `true` if the signal was sent successfully. If you want to wait for this process
1242    /// to end, you can use [`Process::wait`] or directly [`Process::kill_and_wait`].
1243    ///
1244    /// ⚠️ Even if this function returns `true`, it doesn't necessarily mean that the process will
1245    /// be killed. It just means that the signal was sent successfully.
1246    ///
1247    /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1248    /// levels than the current process for example.
1249    ///
1250    /// If you want to use another signal, take a look at [`Process::kill_with`].
1251    ///
1252    /// To get the list of the supported signals on this system, use
1253    /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1254    ///
1255    /// ```no_run
1256    /// use sysinfo::{Pid, System};
1257    ///
1258    /// let s = System::new_all();
1259    /// if let Some(process) = s.process(Pid::from(1337)) {
1260    ///     process.kill();
1261    /// }
1262    /// ```
1263    pub fn kill(&self) -> bool {
1264        self.kill_with(Signal::Kill).unwrap_or(false)
1265    }
1266
1267    /// Sends the given `signal` to the process. If the signal doesn't exist on this platform,
1268    /// it'll do nothing and will return `None`. Otherwise it'll return `Some(bool)`. The boolean
1269    /// value will depend on whether or not the signal was sent successfully.
1270    ///
1271    /// If you just want to kill the process, use [`Process::kill`] directly. If you want to wait
1272    /// for this process to end, you can use [`Process::wait`] or [`Process::kill_with_and_wait`].
1273    ///
1274    /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1275    /// levels than the current process for example.
1276    ///
1277    /// To get the list of the supported signals on this system, use
1278    /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1279    ///
1280    /// ```no_run
1281    /// use sysinfo::{Pid, Signal, System};
1282    ///
1283    /// let s = System::new_all();
1284    /// if let Some(process) = s.process(Pid::from(1337)) {
1285    ///     if process.kill_with(Signal::Kill).is_none() {
1286    ///         println!("This signal isn't supported on this platform");
1287    ///     }
1288    /// }
1289    /// ```
1290    pub fn kill_with(&self, signal: Signal) -> Option<bool> {
1291        self.inner.kill_with(signal)
1292    }
1293
1294    /// Sends [`Signal::Kill`] to the process then waits for its termination.
1295    ///
1296    /// Internally, this method is calling [`Process::kill`] then [`Process::wait`].
1297    ///
1298    /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1299    /// levels than the current process for example. In this case, this method could enter an
1300    /// infinite loop.
1301    ///
1302    /// ```no_run
1303    /// use sysinfo::{Pid, System};
1304    ///
1305    /// let s = System::new_all();
1306    /// if let Some(process) = s.process(Pid::from(1337)) {
1307    ///     if let Err(error) = process.kill_and_wait() {
1308    ///         println!("`kill_and_wait` failed: {error:?}");
1309    ///     }
1310    /// }
1311    /// ```
1312    pub fn kill_and_wait(&self) -> Result<Option<ExitStatus>, KillError> {
1313        self.kill_with_and_wait(Signal::Kill)
1314    }
1315
1316    /// Sends the given `signal` to the process.then waits for its termination.
1317    ///
1318    /// Internally, this method is calling [`Process::kill_with`] then [`Process::wait`].
1319    ///
1320    /// ⚠️ Please note that some processes might not be "killable", like if they run with higher
1321    /// levels than the current process for example. In this case, this method could enter an
1322    /// infinite loop.
1323    ///
1324    /// To get the list of the supported signals on this system, use
1325    /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
1326    ///
1327    /// ```no_run
1328    /// use sysinfo::{Pid, System};
1329    ///
1330    /// let s = System::new_all();
1331    /// if let Some(process) = s.process(Pid::from(1337)) {
1332    ///     if let Err(error) = process.kill_and_wait() {
1333    ///         println!("`kill_and_wait` failed: {error:?}");
1334    ///     }
1335    /// }
1336    /// ```
1337    pub fn kill_with_and_wait(&self, signal: Signal) -> Result<Option<ExitStatus>, KillError> {
1338        match self.inner.kill_with(signal) {
1339            Some(sent) => {
1340                if !sent {
1341                    return Err(KillError::FailedToSendSignal);
1342                }
1343            }
1344            None => return Err(KillError::SignalDoesNotExist),
1345        }
1346
1347        Ok(self.inner.wait())
1348    }
1349
1350    /// Wait for process termination and returns its [`ExitStatus`] if it could be retrieved,
1351    /// returns `None` otherwise.
1352    ///
1353    /// ```no_run
1354    /// use sysinfo::{Pid, System};
1355    ///
1356    /// let mut s = System::new_all();
1357    ///
1358    /// if let Some(process) = s.process(Pid::from(1337)) {
1359    ///     println!("Waiting for pid 1337");
1360    ///     let exit_status = process.wait();
1361    ///     println!("Pid 1337 exited with: {exit_status:?}");
1362    /// }
1363    /// ```
1364    pub fn wait(&self) -> Option<ExitStatus> {
1365        self.inner.wait()
1366    }
1367
1368    /// Returns the name of the process.
1369    ///
1370    /// **⚠️ Important ⚠️**
1371    ///
1372    /// On **Linux**, there are two things to know about processes' name:
1373    ///  1. It is limited to 15 characters.
1374    ///  2. It is not always the exe name.
1375    ///
1376    /// If you are looking for a specific process, unless you know what you are
1377    /// doing, in most cases it's better to use [`Process::exe`] instead (which
1378    /// can be empty sometimes!).
1379    ///
1380    /// ```no_run
1381    /// use sysinfo::{Pid, System};
1382    ///
1383    /// let s = System::new_all();
1384    /// if let Some(process) = s.process(Pid::from(1337)) {
1385    ///     println!("{:?}", process.name());
1386    /// }
1387    /// ```
1388    pub fn name(&self) -> &OsStr {
1389        self.inner.name()
1390    }
1391
1392    /// Returns the command line.
1393    ///
1394    ///  **⚠️ Important ⚠️**
1395    ///
1396    /// On **Windows**, you might need to use `administrator` privileges when running your program
1397    /// to have access to this information.
1398    ///
1399    /// ```no_run
1400    /// use sysinfo::{Pid, System};
1401    ///
1402    /// let s = System::new_all();
1403    /// if let Some(process) = s.process(Pid::from(1337)) {
1404    ///     println!("{:?}", process.cmd());
1405    /// }
1406    /// ```
1407    pub fn cmd(&self) -> &[OsString] {
1408        self.inner.cmd()
1409    }
1410
1411    /// Returns the path to the process.
1412    ///
1413    /// ```no_run
1414    /// use sysinfo::{Pid, System};
1415    ///
1416    /// let s = System::new_all();
1417    /// if let Some(process) = s.process(Pid::from(1337)) {
1418    ///     println!("{:?}", process.exe());
1419    /// }
1420    /// ```
1421    ///
1422    /// ### Implementation notes
1423    ///
1424    /// On Linux, this method will return an empty path if there
1425    /// was an error trying to read `/proc/<pid>/exe`. This can
1426    /// happen, for example, if the permission levels or UID namespaces
1427    /// between the caller and target processes are different.
1428    ///
1429    /// It is also the case that `cmd[0]` is _not_ usually a correct
1430    /// replacement for this.
1431    /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html)
1432    /// freely, making this an untrustworthy source of information.
1433    pub fn exe(&self) -> Option<&Path> {
1434        self.inner.exe()
1435    }
1436
1437    /// Returns the PID of the process.
1438    ///
1439    /// ```no_run
1440    /// use sysinfo::{Pid, System};
1441    ///
1442    /// let s = System::new_all();
1443    /// if let Some(process) = s.process(Pid::from(1337)) {
1444    ///     println!("{}", process.pid());
1445    /// }
1446    /// ```
1447    pub fn pid(&self) -> Pid {
1448        self.inner.pid()
1449    }
1450
1451    /// Returns the environment variables of the process.
1452    ///
1453    /// ```no_run
1454    /// use sysinfo::{Pid, System};
1455    ///
1456    /// let s = System::new_all();
1457    /// if let Some(process) = s.process(Pid::from(1337)) {
1458    ///     println!("{:?}", process.environ());
1459    /// }
1460    /// ```
1461    pub fn environ(&self) -> &[OsString] {
1462        self.inner.environ()
1463    }
1464
1465    /// Returns the current working directory.
1466    ///
1467    /// ```no_run
1468    /// use sysinfo::{Pid, System};
1469    ///
1470    /// let s = System::new_all();
1471    /// if let Some(process) = s.process(Pid::from(1337)) {
1472    ///     println!("{:?}", process.cwd());
1473    /// }
1474    /// ```
1475    pub fn cwd(&self) -> Option<&Path> {
1476        self.inner.cwd()
1477    }
1478
1479    /// Returns the path of the root directory.
1480    ///
1481    /// ```no_run
1482    /// use sysinfo::{Pid, System};
1483    ///
1484    /// let s = System::new_all();
1485    /// if let Some(process) = s.process(Pid::from(1337)) {
1486    ///     println!("{:?}", process.root());
1487    /// }
1488    /// ```
1489    pub fn root(&self) -> Option<&Path> {
1490        self.inner.root()
1491    }
1492
1493    /// Returns the memory usage (in bytes).
1494    ///
1495    /// This method returns the [size of the resident set], that is, the amount of memory that the
1496    /// process allocated and which is currently mapped in physical RAM. It does not include memory
1497    /// that is swapped out, or, in some operating systems, that has been allocated but never used.
1498    ///
1499    /// Thus, it represents exactly the amount of physical RAM that the process is using at the
1500    /// present time, but it might not be a good indicator of the total memory that the process will
1501    /// be using over its lifetime. For that purpose, you can try and use
1502    /// [`virtual_memory`](Process::virtual_memory).
1503    ///
1504    /// ```no_run
1505    /// use sysinfo::{Pid, System};
1506    ///
1507    /// let s = System::new_all();
1508    /// if let Some(process) = s.process(Pid::from(1337)) {
1509    ///     println!("{} bytes", process.memory());
1510    /// }
1511    /// ```
1512    ///
1513    /// [size of the resident set]: https://en.wikipedia.org/wiki/Resident_set_size
1514    pub fn memory(&self) -> u64 {
1515        self.inner.memory()
1516    }
1517
1518    /// Returns the virtual memory usage (in bytes).
1519    ///
1520    /// This method returns the [size of virtual memory], that is, the amount of memory that the
1521    /// process can access, whether it is currently mapped in physical RAM or not. It includes
1522    /// physical RAM, allocated but not used regions, swapped-out regions, and even memory
1523    /// associated with [memory-mapped files](https://en.wikipedia.org/wiki/Memory-mapped_file).
1524    ///
1525    /// This value has limitations though. Depending on the operating system and type of process,
1526    /// this value might be a good indicator of the total memory that the process will be using over
1527    /// its lifetime. However, for example, in the version 14 of macOS this value is in the order of
1528    /// the hundreds of gigabytes for every process, and thus not very informative. Moreover, if a
1529    /// process maps into memory a very large file, this value will increase accordingly, even if
1530    /// the process is not actively using the memory.
1531    ///
1532    /// ```no_run
1533    /// use sysinfo::{Pid, System};
1534    ///
1535    /// let s = System::new_all();
1536    /// if let Some(process) = s.process(Pid::from(1337)) {
1537    ///     println!("{} bytes", process.virtual_memory());
1538    /// }
1539    /// ```
1540    ///
1541    /// [size of virtual memory]: https://en.wikipedia.org/wiki/Virtual_memory
1542    pub fn virtual_memory(&self) -> u64 {
1543        self.inner.virtual_memory()
1544    }
1545
1546    /// Returns the parent PID.
1547    ///
1548    /// ```no_run
1549    /// use sysinfo::{Pid, System};
1550    ///
1551    /// let s = System::new_all();
1552    /// if let Some(process) = s.process(Pid::from(1337)) {
1553    ///     println!("{:?}", process.parent());
1554    /// }
1555    /// ```
1556    pub fn parent(&self) -> Option<Pid> {
1557        self.inner.parent()
1558    }
1559
1560    /// Returns the status of the process.
1561    ///
1562    /// ```no_run
1563    /// use sysinfo::{Pid, System};
1564    ///
1565    /// let s = System::new_all();
1566    /// if let Some(process) = s.process(Pid::from(1337)) {
1567    ///     println!("{:?}", process.status());
1568    /// }
1569    /// ```
1570    pub fn status(&self) -> ProcessStatus {
1571        self.inner.status()
1572    }
1573
1574    /// Returns the time where the process was started (in seconds) from epoch.
1575    ///
1576    /// ```no_run
1577    /// use sysinfo::{Pid, System};
1578    ///
1579    /// let s = System::new_all();
1580    /// if let Some(process) = s.process(Pid::from(1337)) {
1581    ///     println!("Started at {} seconds", process.start_time());
1582    /// }
1583    /// ```
1584    pub fn start_time(&self) -> u64 {
1585        self.inner.start_time()
1586    }
1587
1588    /// Returns for how much time the process has been running (in seconds).
1589    ///
1590    /// ```no_run
1591    /// use sysinfo::{Pid, System};
1592    ///
1593    /// let s = System::new_all();
1594    /// if let Some(process) = s.process(Pid::from(1337)) {
1595    ///     println!("Running since {} seconds", process.run_time());
1596    /// }
1597    /// ```
1598    pub fn run_time(&self) -> u64 {
1599        self.inner.run_time()
1600    }
1601
1602    /// Returns the total CPU usage (in %). Notice that it might be bigger than
1603    /// 100 if run on a multi-core machine.
1604    ///
1605    /// If you want a value between 0% and 100%, divide the returned value by
1606    /// the number of CPUs.
1607    ///
1608    /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed
1609    /// **twice** because CPU usage computation is based on time diff (process
1610    /// time on a given time period divided by total system time on the same
1611    /// time period).
1612    ///
1613    /// ⚠️ If you want accurate CPU usage number, better leave a bit of time
1614    /// between two calls of this method (take a look at
1615    /// [`MINIMUM_CPU_UPDATE_INTERVAL`][crate::MINIMUM_CPU_UPDATE_INTERVAL] for
1616    /// more information).
1617    ///
1618    /// ```no_run
1619    /// use sysinfo::{Pid, ProcessesToUpdate, ProcessRefreshKind, System};
1620    ///
1621    /// let mut s = System::new_all();
1622    /// // Wait a bit because CPU usage is based on diff.
1623    /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
1624    /// // Refresh CPU usage to get actual value.
1625    /// s.refresh_processes_specifics(
1626    ///     ProcessesToUpdate::All,
1627    ///     true,
1628    ///     ProcessRefreshKind::nothing().with_cpu()
1629    /// );
1630    /// if let Some(process) = s.process(Pid::from(1337)) {
1631    ///     println!("{}%", process.cpu_usage());
1632    /// }
1633    /// ```
1634    pub fn cpu_usage(&self) -> f32 {
1635        self.inner.cpu_usage()
1636    }
1637
1638    /// Returns the total accumulated CPU usage (in CPU-milliseconds). Note
1639    /// that it might be bigger than the total clock run time of a process if
1640    /// run on a multi-core machine.
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.accumulated_cpu_time());
1648    /// }
1649    /// ```
1650    pub fn accumulated_cpu_time(&self) -> u64 {
1651        self.inner.accumulated_cpu_time()
1652    }
1653
1654    /// Returns number of bytes read and written to disk.
1655    ///
1656    /// ⚠️ On Windows, this method actually returns **ALL** I/O read and
1657    /// written bytes.
1658    ///
1659    /// ⚠️ Files might be cached in memory by your OS, meaning that reading/writing them might not
1660    /// increase the `read_bytes`/`written_bytes` values. You can find more information about it
1661    /// in the `proc_pid_io` manual (`man proc_pid_io` on unix platforms).
1662    ///
1663    /// ```no_run
1664    /// use sysinfo::{Pid, System};
1665    ///
1666    /// let s = System::new_all();
1667    /// if let Some(process) = s.process(Pid::from(1337)) {
1668    ///     let disk_usage = process.disk_usage();
1669    ///     println!("read bytes   : new/total => {}/{}",
1670    ///         disk_usage.read_bytes,
1671    ///         disk_usage.total_read_bytes,
1672    ///     );
1673    ///     println!("written bytes: new/total => {}/{}",
1674    ///         disk_usage.written_bytes,
1675    ///         disk_usage.total_written_bytes,
1676    ///     );
1677    /// }
1678    /// ```
1679    pub fn disk_usage(&self) -> DiskUsage {
1680        self.inner.disk_usage()
1681    }
1682
1683    /// Returns the ID of the owner user of this process or `None` if this
1684    /// information couldn't be retrieved. If you want to get the [`User`] from
1685    /// it, take a look at [`Users::get_user_by_id`].
1686    ///
1687    /// [`User`]: crate::User
1688    /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1689    ///
1690    /// ```no_run
1691    /// use sysinfo::{Pid, System};
1692    ///
1693    /// let mut s = System::new_all();
1694    ///
1695    /// if let Some(process) = s.process(Pid::from(1337)) {
1696    ///     println!("User id for process 1337: {:?}", process.user_id());
1697    /// }
1698    /// ```
1699    pub fn user_id(&self) -> Option<&Uid> {
1700        self.inner.user_id()
1701    }
1702
1703    /// Returns the user ID of the effective owner of this process or `None` if
1704    /// this information couldn't be retrieved. If you want to get the [`User`]
1705    /// from it, take a look at [`Users::get_user_by_id`].
1706    ///
1707    /// If you run something with `sudo`, the real user ID of the launched
1708    /// process will be the ID of the user you are logged in as but effective
1709    /// user ID will be `0` (i-e root).
1710    ///
1711    /// ⚠️ It always returns `None` on Windows.
1712    ///
1713    /// [`User`]: crate::User
1714    /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1715    ///
1716    /// ```no_run
1717    /// use sysinfo::{Pid, System};
1718    ///
1719    /// let mut s = System::new_all();
1720    ///
1721    /// if let Some(process) = s.process(Pid::from(1337)) {
1722    ///     println!("User id for process 1337: {:?}", process.effective_user_id());
1723    /// }
1724    /// ```
1725    pub fn effective_user_id(&self) -> Option<&Uid> {
1726        self.inner.effective_user_id()
1727    }
1728
1729    /// Returns the process group ID of the process.
1730    ///
1731    /// ⚠️ It always returns `None` on Windows.
1732    ///
1733    /// ```no_run
1734    /// use sysinfo::{Pid, System};
1735    ///
1736    /// let mut s = System::new_all();
1737    ///
1738    /// if let Some(process) = s.process(Pid::from(1337)) {
1739    ///     println!("Group ID for process 1337: {:?}", process.group_id());
1740    /// }
1741    /// ```
1742    pub fn group_id(&self) -> Option<Gid> {
1743        self.inner.group_id()
1744    }
1745
1746    /// Returns the effective group ID of the process.
1747    ///
1748    /// If you run something with `sudo`, the real group ID of the launched
1749    /// process will be the primary group ID you are logged in as but effective
1750    /// group ID will be `0` (i-e root).
1751    ///
1752    /// ⚠️ It always returns `None` on Windows.
1753    ///
1754    /// ```no_run
1755    /// use sysinfo::{Pid, System};
1756    ///
1757    /// let mut s = System::new_all();
1758    ///
1759    /// if let Some(process) = s.process(Pid::from(1337)) {
1760    ///     println!("User id for process 1337: {:?}", process.effective_group_id());
1761    /// }
1762    /// ```
1763    pub fn effective_group_id(&self) -> Option<Gid> {
1764        self.inner.effective_group_id()
1765    }
1766
1767    /// Returns the session ID for the current process or `None` if it couldn't
1768    /// be retrieved.
1769    ///
1770    /// ⚠️ This information is computed every time this method is called.
1771    ///
1772    /// ```no_run
1773    /// use sysinfo::{Pid, System};
1774    ///
1775    /// let mut s = System::new_all();
1776    ///
1777    /// if let Some(process) = s.process(Pid::from(1337)) {
1778    ///     println!("Session ID for process 1337: {:?}", process.session_id());
1779    /// }
1780    /// ```
1781    pub fn session_id(&self) -> Option<Pid> {
1782        self.inner.session_id()
1783    }
1784
1785    /// Tasks run by this process. If there are none, returns `None`.
1786    ///
1787    /// ⚠️ This method always returns `None` on other platforms than Linux.
1788    ///
1789    /// ```no_run
1790    /// use sysinfo::{Pid, System};
1791    ///
1792    /// let mut s = System::new_all();
1793    ///
1794    /// if let Some(process) = s.process(Pid::from(1337)) {
1795    ///     if let Some(tasks) = process.tasks() {
1796    ///         println!("Listing tasks for process {:?}", process.pid());
1797    ///         for task_pid in tasks {
1798    ///             if let Some(task) = s.process(*task_pid) {
1799    ///                 println!("Task {:?}: {:?}", task.pid(), task.name());
1800    ///             }
1801    ///         }
1802    ///     }
1803    /// }
1804    /// ```
1805    pub fn tasks(&self) -> Option<&HashSet<Pid>> {
1806        cfg_if! {
1807            if #[cfg(all(
1808                any(target_os = "linux", target_os = "android"),
1809                not(feature = "unknown-ci")
1810            ))] {
1811                self.inner.tasks.as_ref()
1812            } else {
1813                None
1814            }
1815        }
1816    }
1817
1818    /// If the process is a thread, it'll return `Some` with the kind of thread it is. Returns
1819    /// `None` otherwise.
1820    ///
1821    /// ⚠️ This method always returns `None` on other platforms than Linux.
1822    ///
1823    /// ```no_run
1824    /// use sysinfo::System;
1825    ///
1826    /// let s = System::new_all();
1827    ///
1828    /// for (_, process) in s.processes() {
1829    ///     if let Some(thread_kind) = process.thread_kind() {
1830    ///         println!("Process {:?} is a {thread_kind:?} thread", process.pid());
1831    ///     }
1832    /// }
1833    /// ```
1834    pub fn thread_kind(&self) -> Option<ThreadKind> {
1835        cfg_if! {
1836            if #[cfg(all(
1837                any(target_os = "linux", target_os = "android"),
1838                not(feature = "unknown-ci")
1839            ))] {
1840                self.inner.thread_kind()
1841            } else {
1842                None
1843            }
1844        }
1845    }
1846
1847    /// Returns `true` if the process doesn't exist anymore but was not yet removed from
1848    /// the processes list because the `remove_dead_processes` argument was set to `false`
1849    /// in methods like [`System::refresh_processes`].
1850    ///
1851    /// ```no_run
1852    /// use sysinfo::{ProcessesToUpdate, System};
1853    ///
1854    /// let mut s = System::new_all();
1855    /// // We set the `remove_dead_processes` to `false`.
1856    /// s.refresh_processes(ProcessesToUpdate::All, false);
1857    ///
1858    /// for (_, process) in s.processes() {
1859    ///     println!(
1860    ///         "Process {:?} {}",
1861    ///         process.pid(),
1862    ///         if process.exists() { "exists" } else { "doesn't exist" },
1863    ///     );
1864    /// }
1865    /// ```
1866    pub fn exists(&self) -> bool {
1867        self.inner.exists()
1868    }
1869
1870    /// Returns the number of open files in the current process.
1871    ///
1872    /// Returns `None` if it failed retrieving the information or if the current system is not
1873    /// supported.
1874    ///
1875    /// **Important**: this information is computed every time this function is called.
1876    ///
1877    /// ```no_run
1878    /// use sysinfo::System;
1879    ///
1880    /// let s = System::new_all();
1881    ///
1882    /// for (_, process) in s.processes() {
1883    ///     println!(
1884    ///         "Process {:?} {:?}",
1885    ///         process.pid(),
1886    ///         process.open_files(),
1887    ///     );
1888    /// }
1889    /// ```
1890    pub fn open_files(&self) -> Option<usize> {
1891        self.inner.open_files()
1892    }
1893
1894    /// Returns the maximum number of open files for the current process.
1895    ///
1896    /// Returns `None` if it failed retrieving the information or if the current system is not
1897    /// supported.
1898    ///
1899    /// **Important**: this information is computed every time this function is called.
1900    ///
1901    /// ```no_run
1902    /// use sysinfo::System;
1903    ///
1904    /// let s = System::new_all();
1905    ///
1906    /// for (_, process) in s.processes() {
1907    ///     println!(
1908    ///         "Process {:?} {:?}",
1909    ///         process.pid(),
1910    ///         process.open_files_limit(),
1911    ///     );
1912    /// }
1913    /// ```
1914    pub fn open_files_limit(&self) -> Option<usize> {
1915        self.inner.open_files_limit()
1916    }
1917}
1918
1919macro_rules! pid_decl {
1920    ($typ:ty) => {
1921        #[doc = include_str!("../../md_doc/pid.md")]
1922        #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
1923        #[repr(transparent)]
1924        pub struct Pid(pub(crate) $typ);
1925
1926        impl From<usize> for Pid {
1927            fn from(v: usize) -> Self {
1928                Self(v as _)
1929            }
1930        }
1931        impl From<Pid> for usize {
1932            fn from(v: Pid) -> Self {
1933                v.0 as _
1934            }
1935        }
1936        impl FromStr for Pid {
1937            type Err = <$typ as FromStr>::Err;
1938            fn from_str(s: &str) -> Result<Self, Self::Err> {
1939                Ok(Self(<$typ>::from_str(s)?))
1940            }
1941        }
1942        impl fmt::Display for Pid {
1943            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1944                write!(f, "{}", self.0)
1945            }
1946        }
1947        impl Pid {
1948            /// Allows to convert [`Pid`][crate::Pid] into [`u32`].
1949            ///
1950            /// ```
1951            /// use sysinfo::Pid;
1952            ///
1953            /// let pid = Pid::from_u32(0);
1954            /// let value: u32 = pid.as_u32();
1955            /// ```
1956            pub fn as_u32(self) -> u32 {
1957                self.0 as _
1958            }
1959            /// Allows to convert a [`u32`] into [`Pid`][crate::Pid].
1960            ///
1961            /// ```
1962            /// use sysinfo::Pid;
1963            ///
1964            /// let pid = Pid::from_u32(0);
1965            /// ```
1966            pub fn from_u32(v: u32) -> Self {
1967                Self(v as _)
1968            }
1969        }
1970    };
1971}
1972
1973cfg_if! {
1974    if #[cfg(all(
1975        not(feature = "unknown-ci"),
1976        any(
1977            target_os = "freebsd",
1978            target_os = "linux",
1979            target_os = "android",
1980            target_os = "macos",
1981            target_os = "ios",
1982        )
1983    ))] {
1984        use libc::pid_t;
1985
1986        pid_decl!(pid_t);
1987    } else {
1988        pid_decl!(usize);
1989    }
1990}
1991
1992/// This enum allows you to specify when you want the related information to be updated.
1993///
1994/// For example if you only want the [`Process::exe()`] information to be refreshed only if it's not
1995/// already set:
1996///
1997/// ```no_run
1998/// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System, UpdateKind};
1999///
2000/// let mut system = System::new();
2001/// system.refresh_processes_specifics(
2002///     ProcessesToUpdate::All,
2003///     true,
2004///     ProcessRefreshKind::nothing().with_exe(UpdateKind::OnlyIfNotSet),
2005/// );
2006/// ```
2007#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2008pub enum UpdateKind {
2009    /// Never update the related information.
2010    #[default]
2011    Never,
2012    /// Always update the related information.
2013    Always,
2014    /// Only update the related information if it was not already set at least once.
2015    OnlyIfNotSet,
2016}
2017
2018impl UpdateKind {
2019    /// If `self` is `OnlyIfNotSet`, `f` is called and its returned value is returned.
2020    #[allow(dead_code)] // Needed for unsupported targets.
2021    pub(crate) fn needs_update(self, f: impl Fn() -> bool) -> bool {
2022        match self {
2023            Self::Never => false,
2024            Self::Always => true,
2025            Self::OnlyIfNotSet => f(),
2026        }
2027    }
2028}
2029
2030/// This enum allows you to specify if you want all processes to be updated or just
2031/// some of them.
2032///
2033/// Example:
2034///
2035/// ```no_run
2036/// use sysinfo::{ProcessesToUpdate, System, get_current_pid};
2037///
2038/// let mut system = System::new();
2039/// // To refresh all processes:
2040/// system.refresh_processes(ProcessesToUpdate::All, true);
2041///
2042/// // To refresh only the current one:
2043/// system.refresh_processes(
2044///     ProcessesToUpdate::Some(&[get_current_pid().unwrap()]),
2045///     true,
2046/// );
2047/// ```
2048#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2049pub enum ProcessesToUpdate<'a> {
2050    /// To refresh all processes.
2051    All,
2052    /// To refresh only the processes with the listed [`Pid`].
2053    ///
2054    /// [`Pid`]: crate::Pid
2055    Some(&'a [Pid]),
2056}
2057
2058/// Used to determine what you want to refresh specifically on the [`Process`] type.
2059///
2060/// When all refresh are ruled out, a [`Process`] will still retrieve the following information:
2061///  * Process ID ([`Pid`])
2062///  * Parent process ID (on Windows it never changes though)
2063///  * Process name
2064///  * Start time
2065///
2066/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2067/// the information won't be retrieved if the information is accessible without needing
2068/// extra computation.
2069///
2070/// ⚠️ ** Linux Specific ** ⚠️
2071/// When using `ProcessRefreshKind::everything()`, in linux we will fetch all relevant
2072/// information from `/proc/<pid>/` as well as all the information from `/proc/<pid>/task/<tid>/`
2073/// folders. This makes the refresh mechanism a lot slower depending on the number of tasks
2074/// each process has.
2075///  
2076/// If you don't care about tasks information, use `ProcessRefreshKind::everything().without_tasks()`
2077/// as much as possible.
2078///
2079/// ```
2080/// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System};
2081///
2082/// let mut system = System::new();
2083///
2084/// // We don't want to update the CPU information.
2085/// system.refresh_processes_specifics(
2086///     ProcessesToUpdate::All,
2087///     true,
2088///     ProcessRefreshKind::everything().without_cpu(),
2089/// );
2090///
2091/// for (_, proc_) in system.processes() {
2092///     // We use a `==` comparison on float only because we know it's set to 0 here.
2093///     assert_eq!(proc_.cpu_usage(), 0.);
2094/// }
2095/// ```
2096///
2097/// [`Process`]: crate::Process
2098#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2099pub struct ProcessRefreshKind {
2100    cpu: bool,
2101    disk_usage: bool,
2102    memory: bool,
2103    user: UpdateKind,
2104    cwd: UpdateKind,
2105    root: UpdateKind,
2106    environ: UpdateKind,
2107    cmd: UpdateKind,
2108    exe: UpdateKind,
2109    tasks: bool,
2110}
2111
2112/// Creates a new `ProcessRefreshKind` with every refresh set to `false`, except for `tasks`.
2113/// By default, we want to list all processes and tasks are considered processes on their own
2114/// in linux so we still fetch them by default. However, the processes information are not
2115/// refreshed.
2116impl Default for ProcessRefreshKind {
2117    fn default() -> Self {
2118        Self {
2119            cpu: false,
2120            disk_usage: false,
2121            memory: false,
2122            user: UpdateKind::default(),
2123            cwd: UpdateKind::default(),
2124            root: UpdateKind::default(),
2125            environ: UpdateKind::default(),
2126            cmd: UpdateKind::default(),
2127            exe: UpdateKind::default(),
2128            tasks: true, // Process by default includes all tasks.
2129        }
2130    }
2131}
2132
2133impl ProcessRefreshKind {
2134    /// Creates a new `ProcessRefreshKind` with every refresh set to `false`, except for `tasks`.
2135    /// By default, we want to list all processes and tasks are considered processes on their own
2136    /// in linux so we still fetch them by default. However, the processes information are not
2137    /// refreshed.
2138    /// ```
2139    /// use sysinfo::{ProcessRefreshKind, UpdateKind};
2140    ///
2141    /// let r = ProcessRefreshKind::nothing();
2142    ///
2143    /// assert_eq!(r.cpu(), false);
2144    /// assert_eq!(r.user(), UpdateKind::Never);
2145    /// ```
2146    pub fn nothing() -> Self {
2147        Self::default()
2148    }
2149
2150    /// Creates a new `ProcessRefreshKind` with every refresh set to `true` or
2151    /// [`UpdateKind::OnlyIfNotSet`].
2152    ///
2153    /// ```
2154    /// use sysinfo::{ProcessRefreshKind, UpdateKind};
2155    ///
2156    /// let r = ProcessRefreshKind::everything();
2157    ///
2158    /// assert_eq!(r.cpu(), true);
2159    /// assert_eq!(r.user(), UpdateKind::OnlyIfNotSet);
2160    /// ```
2161    pub fn everything() -> Self {
2162        Self {
2163            cpu: true,
2164            disk_usage: true,
2165            memory: true,
2166            user: UpdateKind::OnlyIfNotSet,
2167            cwd: UpdateKind::OnlyIfNotSet,
2168            root: UpdateKind::OnlyIfNotSet,
2169            environ: UpdateKind::OnlyIfNotSet,
2170            cmd: UpdateKind::OnlyIfNotSet,
2171            exe: UpdateKind::OnlyIfNotSet,
2172            tasks: true,
2173        }
2174    }
2175
2176    impl_get_set!(
2177        ProcessRefreshKind,
2178        cpu,
2179        with_cpu,
2180        without_cpu,
2181        "\
2182It will retrieve both CPU usage and CPU accumulated time,"
2183    );
2184    impl_get_set!(
2185        ProcessRefreshKind,
2186        disk_usage,
2187        with_disk_usage,
2188        without_disk_usage
2189    );
2190    impl_get_set!(
2191        ProcessRefreshKind,
2192        user,
2193        with_user,
2194        without_user,
2195        UpdateKind,
2196        "\
2197It will retrieve the following information:
2198
2199 * user ID
2200 * user effective ID (if available on the platform)
2201 * user group ID (if available on the platform)
2202 * user effective ID (if available on the platform)"
2203    );
2204    impl_get_set!(ProcessRefreshKind, memory, with_memory, without_memory);
2205    impl_get_set!(ProcessRefreshKind, cwd, with_cwd, without_cwd, UpdateKind);
2206    impl_get_set!(
2207        ProcessRefreshKind,
2208        root,
2209        with_root,
2210        without_root,
2211        UpdateKind
2212    );
2213    impl_get_set!(
2214        ProcessRefreshKind,
2215        environ,
2216        with_environ,
2217        without_environ,
2218        UpdateKind
2219    );
2220    impl_get_set!(ProcessRefreshKind, cmd, with_cmd, without_cmd, UpdateKind);
2221    impl_get_set!(ProcessRefreshKind, exe, with_exe, without_exe, UpdateKind);
2222    impl_get_set!(ProcessRefreshKind, tasks, with_tasks, without_tasks);
2223}
2224
2225/// Used to determine what you want to refresh specifically on the [`Cpu`] type.
2226///
2227/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2228/// the information won't be retrieved if the information is accessible without needing
2229/// extra computation.
2230///
2231/// ```
2232/// use sysinfo::{CpuRefreshKind, System};
2233///
2234/// let mut system = System::new();
2235///
2236/// // We don't want to update all the CPU information.
2237/// system.refresh_cpu_specifics(CpuRefreshKind::everything().without_frequency());
2238///
2239/// for cpu in system.cpus() {
2240///     assert_eq!(cpu.frequency(), 0);
2241/// }
2242/// ```
2243///
2244/// [`Cpu`]: crate::Cpu
2245#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2246pub struct CpuRefreshKind {
2247    cpu_usage: bool,
2248    frequency: bool,
2249}
2250
2251impl CpuRefreshKind {
2252    /// Creates a new `CpuRefreshKind` with every refresh set to `false`.
2253    ///
2254    /// ```
2255    /// use sysinfo::CpuRefreshKind;
2256    ///
2257    /// let r = CpuRefreshKind::nothing();
2258    ///
2259    /// assert_eq!(r.frequency(), false);
2260    /// assert_eq!(r.cpu_usage(), false);
2261    /// ```
2262    pub fn nothing() -> Self {
2263        Self::default()
2264    }
2265
2266    /// Creates a new `CpuRefreshKind` with every refresh set to `true`.
2267    ///
2268    /// ```
2269    /// use sysinfo::CpuRefreshKind;
2270    ///
2271    /// let r = CpuRefreshKind::everything();
2272    ///
2273    /// assert_eq!(r.frequency(), true);
2274    /// assert_eq!(r.cpu_usage(), true);
2275    /// ```
2276    pub fn everything() -> Self {
2277        Self {
2278            cpu_usage: true,
2279            frequency: true,
2280        }
2281    }
2282
2283    impl_get_set!(CpuRefreshKind, cpu_usage, with_cpu_usage, without_cpu_usage);
2284    impl_get_set!(CpuRefreshKind, frequency, with_frequency, without_frequency);
2285}
2286
2287/// Used to determine which memory you want to refresh specifically.
2288///
2289/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2290/// the information won't be retrieved if the information is accessible without needing
2291/// extra computation.
2292///
2293/// ```
2294/// use sysinfo::{MemoryRefreshKind, System};
2295///
2296/// let mut system = System::new();
2297///
2298/// // We don't want to update all memories information.
2299/// system.refresh_memory_specifics(MemoryRefreshKind::nothing().with_ram());
2300///
2301/// println!("total RAM: {}", system.total_memory());
2302/// println!("free RAM:  {}", system.free_memory());
2303/// ```
2304#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2305pub struct MemoryRefreshKind {
2306    ram: bool,
2307    swap: bool,
2308}
2309
2310impl MemoryRefreshKind {
2311    /// Creates a new `MemoryRefreshKind` with every refresh set to `false`.
2312    ///
2313    /// ```
2314    /// use sysinfo::MemoryRefreshKind;
2315    ///
2316    /// let r = MemoryRefreshKind::nothing();
2317    ///
2318    /// assert_eq!(r.ram(), false);
2319    /// assert_eq!(r.swap(), false);
2320    /// ```
2321    pub fn nothing() -> Self {
2322        Self::default()
2323    }
2324
2325    /// Creates a new `MemoryRefreshKind` with every refresh set to `true`.
2326    ///
2327    /// ```
2328    /// use sysinfo::MemoryRefreshKind;
2329    ///
2330    /// let r = MemoryRefreshKind::everything();
2331    ///
2332    /// assert_eq!(r.ram(), true);
2333    /// assert_eq!(r.swap(), true);
2334    /// ```
2335    pub fn everything() -> Self {
2336        Self {
2337            ram: true,
2338            swap: true,
2339        }
2340    }
2341
2342    impl_get_set!(MemoryRefreshKind, ram, with_ram, without_ram);
2343    impl_get_set!(MemoryRefreshKind, swap, with_swap, without_swap);
2344}
2345
2346/// Used to determine what you want to refresh specifically on the [`System`][crate::System] type.
2347///
2348/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2349/// the information won't be retrieved if the information is accessible without needing
2350/// extra computation.
2351///
2352/// ```
2353/// use sysinfo::{RefreshKind, System};
2354///
2355/// // We want everything except memory.
2356/// let mut system = System::new_with_specifics(RefreshKind::everything().without_memory());
2357///
2358/// assert_eq!(system.total_memory(), 0);
2359/// # if sysinfo::IS_SUPPORTED_SYSTEM && !cfg!(feature = "apple-sandbox") {
2360/// assert!(system.processes().len() > 0);
2361/// # }
2362/// ```
2363#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2364pub struct RefreshKind {
2365    processes: Option<ProcessRefreshKind>,
2366    memory: Option<MemoryRefreshKind>,
2367    cpu: Option<CpuRefreshKind>,
2368}
2369
2370impl RefreshKind {
2371    /// Creates a new `RefreshKind` with every refresh set to `false`/`None`.
2372    ///
2373    /// ```
2374    /// use sysinfo::RefreshKind;
2375    ///
2376    /// let r = RefreshKind::nothing();
2377    ///
2378    /// assert_eq!(r.processes().is_some(), false);
2379    /// assert_eq!(r.memory().is_some(), false);
2380    /// assert_eq!(r.cpu().is_some(), false);
2381    /// ```
2382    pub fn nothing() -> Self {
2383        Self::default()
2384    }
2385
2386    /// Creates a new `RefreshKind` with every refresh set to `true`/`Some(...)`.
2387    ///
2388    /// ```
2389    /// use sysinfo::RefreshKind;
2390    ///
2391    /// let r = RefreshKind::everything();
2392    ///
2393    /// assert_eq!(r.processes().is_some(), true);
2394    /// assert_eq!(r.memory().is_some(), true);
2395    /// assert_eq!(r.cpu().is_some(), true);
2396    /// ```
2397    pub fn everything() -> Self {
2398        Self {
2399            processes: Some(ProcessRefreshKind::everything()),
2400            memory: Some(MemoryRefreshKind::everything()),
2401            cpu: Some(CpuRefreshKind::everything()),
2402        }
2403    }
2404
2405    impl_get_set!(
2406        RefreshKind,
2407        processes,
2408        with_processes,
2409        without_processes,
2410        ProcessRefreshKind
2411    );
2412    impl_get_set!(
2413        RefreshKind,
2414        memory,
2415        with_memory,
2416        without_memory,
2417        MemoryRefreshKind
2418    );
2419    impl_get_set!(RefreshKind, cpu, with_cpu, without_cpu, CpuRefreshKind);
2420}
2421
2422/// Returns the pid for the current process.
2423///
2424/// `Err` is returned in case the platform isn't supported.
2425///
2426/// ```no_run
2427/// use sysinfo::get_current_pid;
2428///
2429/// match get_current_pid() {
2430///     Ok(pid) => {
2431///         println!("current pid: {}", pid);
2432///     }
2433///     Err(e) => {
2434///         println!("failed to get current pid: {}", e);
2435///     }
2436/// }
2437/// ```
2438#[allow(clippy::unnecessary_wraps)]
2439pub fn get_current_pid() -> Result<Pid, &'static str> {
2440    cfg_if! {
2441        if #[cfg(feature = "unknown-ci")] {
2442            fn inner() -> Result<Pid, &'static str> {
2443                Err("Unknown platform (CI)")
2444            }
2445        } else if #[cfg(any(
2446            target_os = "freebsd",
2447            target_os = "linux",
2448            target_os = "android",
2449            target_os = "macos",
2450            target_os = "ios",
2451        ))] {
2452            fn inner() -> Result<Pid, &'static str> {
2453                unsafe { Ok(Pid(libc::getpid())) }
2454            }
2455        } else if #[cfg(windows)] {
2456            fn inner() -> Result<Pid, &'static str> {
2457                use windows::Win32::System::Threading::GetCurrentProcessId;
2458
2459                unsafe { Ok(Pid(GetCurrentProcessId() as _)) }
2460            }
2461        } else {
2462            fn inner() -> Result<Pid, &'static str> {
2463                Err("Unknown platform")
2464            }
2465        }
2466    }
2467    inner()
2468}
2469
2470/// Contains all the methods of the [`Cpu`][crate::Cpu] struct.
2471///
2472/// ```no_run
2473/// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2474///
2475/// let mut s = System::new_with_specifics(
2476///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2477/// );
2478///
2479/// // Wait a bit because CPU usage is based on diff.
2480/// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
2481/// // Refresh CPUs again to get actual value.
2482/// s.refresh_cpu_all();
2483///
2484/// for cpu in s.cpus() {
2485///     println!("{}%", cpu.cpu_usage());
2486/// }
2487/// ```
2488pub struct Cpu {
2489    pub(crate) inner: CpuInner,
2490}
2491
2492impl Cpu {
2493    /// Returns this CPU's usage.
2494    ///
2495    /// Note: You'll need to refresh it at least twice (diff between the first and the second is
2496    /// how CPU usage is computed) at first if you want to have a non-zero value.
2497    ///
2498    /// ```no_run
2499    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2500    ///
2501    /// let mut s = System::new_with_specifics(
2502    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2503    /// );
2504    ///
2505    /// // Wait a bit because CPU usage is based on diff.
2506    /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
2507    /// // Refresh CPUs again to get actual value.
2508    /// s.refresh_cpu_all();
2509    ///
2510    /// for cpu in s.cpus() {
2511    ///     println!("{}%", cpu.cpu_usage());
2512    /// }
2513    /// ```
2514    pub fn cpu_usage(&self) -> f32 {
2515        self.inner.cpu_usage()
2516    }
2517
2518    /// Returns this CPU's name.
2519    ///
2520    /// ```no_run
2521    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2522    ///
2523    /// let s = System::new_with_specifics(
2524    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2525    /// );
2526    /// for cpu in s.cpus() {
2527    ///     println!("{}", cpu.name());
2528    /// }
2529    /// ```
2530    pub fn name(&self) -> &str {
2531        self.inner.name()
2532    }
2533
2534    /// Returns the CPU's vendor id.
2535    ///
2536    /// ```no_run
2537    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2538    ///
2539    /// let s = System::new_with_specifics(
2540    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2541    /// );
2542    /// for cpu in s.cpus() {
2543    ///     println!("{}", cpu.vendor_id());
2544    /// }
2545    /// ```
2546    pub fn vendor_id(&self) -> &str {
2547        self.inner.vendor_id()
2548    }
2549
2550    /// Returns the CPU's brand.
2551    ///
2552    /// ```no_run
2553    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2554    ///
2555    /// let s = System::new_with_specifics(
2556    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2557    /// );
2558    /// for cpu in s.cpus() {
2559    ///     println!("{}", cpu.brand());
2560    /// }
2561    /// ```
2562    pub fn brand(&self) -> &str {
2563        self.inner.brand()
2564    }
2565
2566    /// Returns the CPU's frequency.
2567    ///
2568    /// ```no_run
2569    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2570    ///
2571    /// let s = System::new_with_specifics(
2572    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2573    /// );
2574    /// for cpu in s.cpus() {
2575    ///     println!("{}", cpu.frequency());
2576    /// }
2577    /// ```
2578    pub fn frequency(&self) -> u64 {
2579        self.inner.frequency()
2580    }
2581}
2582
2583#[cfg(test)]
2584mod test {
2585    use crate::*;
2586    use std::str::FromStr;
2587
2588    // In case `Process::updated` is misused, `System::refresh_processes` might remove them
2589    // so this test ensures that it doesn't happen.
2590    #[test]
2591    fn check_refresh_process_update() {
2592        if !IS_SUPPORTED_SYSTEM {
2593            return;
2594        }
2595        let mut s = System::new_all();
2596        let total = s.processes().len() as isize;
2597        s.refresh_processes(ProcessesToUpdate::All, false);
2598        let new_total = s.processes().len() as isize;
2599        // There should be almost no difference in the processes count.
2600        assert!(
2601            (new_total - total).abs() <= 5,
2602            "{} <= 5",
2603            (new_total - total).abs()
2604        );
2605    }
2606
2607    #[test]
2608    fn check_cpu_arch() {
2609        assert!(!System::cpu_arch().is_empty());
2610    }
2611
2612    // Ensure that the CPUs frequency isn't retrieved until we ask for it.
2613    #[test]
2614    fn check_cpu_frequency() {
2615        if !IS_SUPPORTED_SYSTEM {
2616            return;
2617        }
2618        let mut s = System::new();
2619        s.refresh_processes(ProcessesToUpdate::All, false);
2620        for proc_ in s.cpus() {
2621            assert_eq!(proc_.frequency(), 0);
2622        }
2623        s.refresh_cpu_usage();
2624        for proc_ in s.cpus() {
2625            assert_eq!(proc_.frequency(), 0);
2626        }
2627        // In a VM, it'll fail.
2628        if std::env::var("APPLE_CI").is_err() && std::env::var("FREEBSD_CI").is_err() {
2629            s.refresh_cpu_specifics(CpuRefreshKind::everything());
2630            for proc_ in s.cpus() {
2631                assert_ne!(proc_.frequency(), 0);
2632            }
2633        }
2634    }
2635
2636    #[test]
2637    fn check_process_memory_usage() {
2638        let mut s = System::new();
2639        s.refresh_specifics(RefreshKind::everything());
2640
2641        if IS_SUPPORTED_SYSTEM {
2642            // No process should have 0 as memory usage.
2643            #[cfg(not(feature = "apple-sandbox"))]
2644            assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
2645        } else {
2646            // There should be no process, but if there is one, its memory usage should be 0.
2647            assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
2648        }
2649    }
2650
2651    #[test]
2652    fn check_system_implemented_traits() {
2653        fn check<T: Sized + std::fmt::Debug + Default + Send + Sync>(_: T) {}
2654
2655        check(System::new());
2656    }
2657
2658    #[test]
2659    fn check_memory_usage() {
2660        let mut s = System::new();
2661
2662        assert_eq!(s.total_memory(), 0);
2663        assert_eq!(s.free_memory(), 0);
2664        assert_eq!(s.available_memory(), 0);
2665        assert_eq!(s.used_memory(), 0);
2666        assert_eq!(s.total_swap(), 0);
2667        assert_eq!(s.free_swap(), 0);
2668        assert_eq!(s.used_swap(), 0);
2669
2670        s.refresh_memory();
2671        if IS_SUPPORTED_SYSTEM {
2672            assert!(s.total_memory() > 0);
2673            assert!(s.used_memory() > 0);
2674            if s.total_swap() > 0 {
2675                // I think it's pretty safe to assume that there is still some swap left...
2676                assert!(s.free_swap() > 0);
2677            }
2678        } else {
2679            assert_eq!(s.total_memory(), 0);
2680            assert_eq!(s.used_memory(), 0);
2681            assert_eq!(s.total_swap(), 0);
2682            assert_eq!(s.free_swap(), 0);
2683        }
2684    }
2685
2686    #[cfg(target_os = "linux")]
2687    #[test]
2688    fn check_processes_cpu_usage() {
2689        if !IS_SUPPORTED_SYSTEM {
2690            return;
2691        }
2692        let mut s = System::new();
2693
2694        s.refresh_processes(ProcessesToUpdate::All, false);
2695        // All CPU usage will start at zero until the second refresh
2696        assert!(s
2697            .processes()
2698            .iter()
2699            .all(|(_, proc_)| proc_.cpu_usage() == 0.0));
2700
2701        // Wait a bit to update CPU usage values
2702        std::thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
2703        s.refresh_processes(ProcessesToUpdate::All, true);
2704        assert!(s
2705            .processes()
2706            .iter()
2707            .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
2708                && proc_.cpu_usage() <= (s.cpus().len() as f32) * 100.0));
2709        assert!(s
2710            .processes()
2711            .iter()
2712            .any(|(_, proc_)| proc_.cpu_usage() > 0.0));
2713    }
2714
2715    #[test]
2716    fn check_cpu_usage() {
2717        if !IS_SUPPORTED_SYSTEM {
2718            return;
2719        }
2720        let mut s = System::new();
2721        for _ in 0..10 {
2722            s.refresh_cpu_usage();
2723            // Wait a bit to update CPU usage values
2724            std::thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
2725            if s.cpus().iter().any(|c| c.cpu_usage() > 0.0) {
2726                // All good!
2727                return;
2728            }
2729        }
2730        panic!("CPU usage is always zero...");
2731    }
2732
2733    #[test]
2734    fn check_system_info() {
2735        // We don't want to test on unsupported systems.
2736        if IS_SUPPORTED_SYSTEM {
2737            assert!(!System::name()
2738                .expect("Failed to get system name")
2739                .is_empty());
2740
2741            assert!(!System::kernel_version()
2742                .expect("Failed to get kernel version")
2743                .is_empty());
2744
2745            assert!(!System::os_version()
2746                .expect("Failed to get os version")
2747                .is_empty());
2748
2749            assert!(!System::long_os_version()
2750                .expect("Failed to get long OS version")
2751                .is_empty());
2752        }
2753
2754        assert!(!System::distribution_id().is_empty());
2755    }
2756
2757    #[test]
2758    fn check_host_name() {
2759        // We don't want to test on unsupported systems.
2760        if IS_SUPPORTED_SYSTEM {
2761            assert!(System::host_name().is_some());
2762        }
2763    }
2764
2765    #[test]
2766    fn check_refresh_process_return_value() {
2767        // We don't want to test on unsupported systems.
2768        if IS_SUPPORTED_SYSTEM {
2769            let _pid = get_current_pid().expect("Failed to get current PID");
2770
2771            #[cfg(not(feature = "apple-sandbox"))]
2772            {
2773                let mut s = System::new();
2774                // First check what happens in case the process isn't already in our process list.
2775                assert_eq!(
2776                    s.refresh_processes(ProcessesToUpdate::Some(&[_pid]), true),
2777                    1
2778                );
2779                // Then check that it still returns 1 if the process is already in our process list.
2780                assert_eq!(
2781                    s.refresh_processes(ProcessesToUpdate::Some(&[_pid]), true),
2782                    1
2783                );
2784            }
2785        }
2786    }
2787
2788    #[test]
2789    fn check_cpus_number() {
2790        let mut s = System::new();
2791
2792        // This information isn't retrieved by default.
2793        assert!(s.cpus().is_empty());
2794        if IS_SUPPORTED_SYSTEM {
2795            // The physical cores count is recomputed every time the function is called, so the
2796            // information must be relevant even with nothing initialized.
2797            let physical_cores_count =
2798                System::physical_core_count().expect("failed to get number of physical cores");
2799
2800            s.refresh_cpu_usage();
2801            // The cpus shouldn't be empty anymore.
2802            assert!(!s.cpus().is_empty());
2803
2804            // In case we are running inside a VM, it's possible to not have a physical core, only
2805            // logical ones, which is why we don't test `physical_cores_count > 0`.
2806            let physical_cores_count2 =
2807                System::physical_core_count().expect("failed to get number of physical cores");
2808            assert!(physical_cores_count2 <= s.cpus().len());
2809            assert_eq!(physical_cores_count, physical_cores_count2);
2810        } else {
2811            assert_eq!(System::physical_core_count(), None);
2812        }
2813        assert!(System::physical_core_count().unwrap_or(0) <= s.cpus().len());
2814    }
2815
2816    // This test only exists to ensure that the `Display` and `Debug` traits are implemented on the
2817    // `ProcessStatus` enum on all targets.
2818    #[test]
2819    fn check_display_impl_process_status() {
2820        println!("{} {:?}", ProcessStatus::Parked, ProcessStatus::Idle);
2821    }
2822
2823    #[test]
2824    #[allow(clippy::unnecessary_fallible_conversions)]
2825    fn check_pid_from_impls() {
2826        assert!(crate::Pid::try_from(0usize).is_ok());
2827        // If it doesn't panic, it's fine.
2828        let _ = crate::Pid::from(0);
2829        assert!(crate::Pid::from_str("0").is_ok());
2830    }
2831
2832    #[test]
2833    #[allow(clippy::const_is_empty)]
2834    fn check_nb_supported_signals() {
2835        if IS_SUPPORTED_SYSTEM {
2836            assert!(
2837                !SUPPORTED_SIGNALS.is_empty(),
2838                "SUPPORTED_SIGNALS shouldn't be empty on supported systems!"
2839            );
2840        } else {
2841            assert!(
2842                SUPPORTED_SIGNALS.is_empty(),
2843                "SUPPORTED_SIGNALS should be empty on not support systems!"
2844            );
2845        }
2846    }
2847}
2848
2849#[cfg(doctest)]
2850mod doctest {
2851    // FIXME: Can be removed once negative trait bounds are supported.
2852    /// Check that `Process` doesn't implement `Clone`.
2853    ///
2854    /// First we check that the "basic" code works:
2855    ///
2856    /// ```no_run
2857    /// use sysinfo::{Process, System};
2858    ///
2859    /// let mut s = System::new_all();
2860    /// let p: &Process = s.processes().values().next().unwrap();
2861    /// ```
2862    ///
2863    /// And now we check if it fails when we try to clone it:
2864    ///
2865    /// ```compile_fail
2866    /// use sysinfo::{Process, System};
2867    ///
2868    /// let mut s = System::new_all();
2869    /// let p: &Process = s.processes().values().next().unwrap();
2870    /// let p = (*p).clone();
2871    /// ```
2872    mod process_clone {}
2873
2874    // FIXME: Can be removed once negative trait bounds are supported.
2875    /// Check that `System` doesn't implement `Clone`.
2876    ///
2877    /// First we check that the "basic" code works:
2878    ///
2879    /// ```no_run
2880    /// use sysinfo::{Process, System};
2881    ///
2882    /// let s = System::new();
2883    /// ```
2884    ///
2885    /// And now we check if it fails when we try to clone it:
2886    ///
2887    /// ```compile_fail
2888    /// use sysinfo::{Process, System};
2889    ///
2890    /// let s = System::new();
2891    /// let s = s.clone();
2892    /// ```
2893    mod system_clone {}
2894}