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    /// Waits for process termination and returns its [`ExitStatus`] if it could be retrieved,
1351    /// returns `None` otherwise. It means that as long as the process is alive, this method will
1352    /// not return.
1353    ///
1354    /// ⚠️ On **macOS** and **FreeBSD**, if the process died and a new one took its PID, unless
1355    /// you refreshed, it will wait for the new process to end.
1356    ///
1357    /// On **Windows**, as long as we have a (internal) handle, we can always retrieve the exit
1358    /// status.
1359    ///
1360    /// On **Linux**/**Android**, we check that the start time of the PID we're waiting is the same
1361    /// as the current process'. If not it means the process died and a new one got its PID.
1362    ///
1363    /// ```no_run
1364    /// use sysinfo::{Pid, System};
1365    ///
1366    /// let mut s = System::new_all();
1367    ///
1368    /// if let Some(process) = s.process(Pid::from(1337)) {
1369    ///     println!("Waiting for pid 1337");
1370    ///     let exit_status = process.wait();
1371    ///     println!("Pid 1337 exited with: {exit_status:?}");
1372    /// }
1373    /// ```
1374    pub fn wait(&self) -> Option<ExitStatus> {
1375        self.inner.wait()
1376    }
1377
1378    /// Returns the name of the process.
1379    ///
1380    /// **⚠️ Important ⚠️**
1381    ///
1382    /// On **Linux**, there are two things to know about processes' name:
1383    ///  1. It is limited to 15 characters.
1384    ///  2. It is not always the exe name.
1385    ///
1386    /// If you are looking for a specific process, unless you know what you are
1387    /// doing, in most cases it's better to use [`Process::exe`] instead (which
1388    /// can be empty sometimes!).
1389    ///
1390    /// ```no_run
1391    /// use sysinfo::{Pid, System};
1392    ///
1393    /// let s = System::new_all();
1394    /// if let Some(process) = s.process(Pid::from(1337)) {
1395    ///     println!("{:?}", process.name());
1396    /// }
1397    /// ```
1398    pub fn name(&self) -> &OsStr {
1399        self.inner.name()
1400    }
1401
1402    /// Returns the command line.
1403    ///
1404    ///  **⚠️ Important ⚠️**
1405    ///
1406    /// On **Windows**, you might need to use `administrator` privileges when running your program
1407    /// to have access to this information.
1408    ///
1409    /// ```no_run
1410    /// use sysinfo::{Pid, System};
1411    ///
1412    /// let s = System::new_all();
1413    /// if let Some(process) = s.process(Pid::from(1337)) {
1414    ///     println!("{:?}", process.cmd());
1415    /// }
1416    /// ```
1417    pub fn cmd(&self) -> &[OsString] {
1418        self.inner.cmd()
1419    }
1420
1421    /// Returns the path to the process.
1422    ///
1423    /// ```no_run
1424    /// use sysinfo::{Pid, System};
1425    ///
1426    /// let s = System::new_all();
1427    /// if let Some(process) = s.process(Pid::from(1337)) {
1428    ///     println!("{:?}", process.exe());
1429    /// }
1430    /// ```
1431    ///
1432    /// ### Implementation notes
1433    ///
1434    /// On Linux, this method will return an empty path if there
1435    /// was an error trying to read `/proc/<pid>/exe`. This can
1436    /// happen, for example, if the permission levels or UID namespaces
1437    /// between the caller and target processes are different.
1438    ///
1439    /// It is also the case that `cmd[0]` is _not_ usually a correct
1440    /// replacement for this.
1441    /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html)
1442    /// freely, making this an untrustworthy source of information.
1443    pub fn exe(&self) -> Option<&Path> {
1444        self.inner.exe()
1445    }
1446
1447    /// Returns the PID of the process.
1448    ///
1449    /// ```no_run
1450    /// use sysinfo::{Pid, System};
1451    ///
1452    /// let s = System::new_all();
1453    /// if let Some(process) = s.process(Pid::from(1337)) {
1454    ///     println!("{}", process.pid());
1455    /// }
1456    /// ```
1457    pub fn pid(&self) -> Pid {
1458        self.inner.pid()
1459    }
1460
1461    /// Returns the environment variables of the process.
1462    ///
1463    /// ```no_run
1464    /// use sysinfo::{Pid, System};
1465    ///
1466    /// let s = System::new_all();
1467    /// if let Some(process) = s.process(Pid::from(1337)) {
1468    ///     println!("{:?}", process.environ());
1469    /// }
1470    /// ```
1471    pub fn environ(&self) -> &[OsString] {
1472        self.inner.environ()
1473    }
1474
1475    /// Returns the current working directory.
1476    ///
1477    /// ```no_run
1478    /// use sysinfo::{Pid, System};
1479    ///
1480    /// let s = System::new_all();
1481    /// if let Some(process) = s.process(Pid::from(1337)) {
1482    ///     println!("{:?}", process.cwd());
1483    /// }
1484    /// ```
1485    pub fn cwd(&self) -> Option<&Path> {
1486        self.inner.cwd()
1487    }
1488
1489    /// Returns the path of the root directory.
1490    ///
1491    /// ```no_run
1492    /// use sysinfo::{Pid, System};
1493    ///
1494    /// let s = System::new_all();
1495    /// if let Some(process) = s.process(Pid::from(1337)) {
1496    ///     println!("{:?}", process.root());
1497    /// }
1498    /// ```
1499    pub fn root(&self) -> Option<&Path> {
1500        self.inner.root()
1501    }
1502
1503    /// Returns the memory usage (in bytes).
1504    ///
1505    /// This method returns the [size of the resident set], that is, the amount of memory that the
1506    /// process allocated and which is currently mapped in physical RAM. It does not include memory
1507    /// that is swapped out, or, in some operating systems, that has been allocated but never used.
1508    ///
1509    /// Thus, it represents exactly the amount of physical RAM that the process is using at the
1510    /// present time, but it might not be a good indicator of the total memory that the process will
1511    /// be using over its lifetime. For that purpose, you can try and use
1512    /// [`virtual_memory`](Process::virtual_memory).
1513    ///
1514    /// ```no_run
1515    /// use sysinfo::{Pid, System};
1516    ///
1517    /// let s = System::new_all();
1518    /// if let Some(process) = s.process(Pid::from(1337)) {
1519    ///     println!("{} bytes", process.memory());
1520    /// }
1521    /// ```
1522    ///
1523    /// [size of the resident set]: https://en.wikipedia.org/wiki/Resident_set_size
1524    pub fn memory(&self) -> u64 {
1525        self.inner.memory()
1526    }
1527
1528    /// Returns the virtual memory usage (in bytes).
1529    ///
1530    /// This method returns the [size of virtual memory], that is, the amount of memory that the
1531    /// process can access, whether it is currently mapped in physical RAM or not. It includes
1532    /// physical RAM, allocated but not used regions, swapped-out regions, and even memory
1533    /// associated with [memory-mapped files](https://en.wikipedia.org/wiki/Memory-mapped_file).
1534    ///
1535    /// This value has limitations though. Depending on the operating system and type of process,
1536    /// this value might be a good indicator of the total memory that the process will be using over
1537    /// its lifetime. However, for example, in the version 14 of macOS this value is in the order of
1538    /// the hundreds of gigabytes for every process, and thus not very informative. Moreover, if a
1539    /// process maps into memory a very large file, this value will increase accordingly, even if
1540    /// the process is not actively using the memory.
1541    ///
1542    /// ```no_run
1543    /// use sysinfo::{Pid, System};
1544    ///
1545    /// let s = System::new_all();
1546    /// if let Some(process) = s.process(Pid::from(1337)) {
1547    ///     println!("{} bytes", process.virtual_memory());
1548    /// }
1549    /// ```
1550    ///
1551    /// [size of virtual memory]: https://en.wikipedia.org/wiki/Virtual_memory
1552    pub fn virtual_memory(&self) -> u64 {
1553        self.inner.virtual_memory()
1554    }
1555
1556    /// Returns the parent PID.
1557    ///
1558    /// ```no_run
1559    /// use sysinfo::{Pid, System};
1560    ///
1561    /// let s = System::new_all();
1562    /// if let Some(process) = s.process(Pid::from(1337)) {
1563    ///     println!("{:?}", process.parent());
1564    /// }
1565    /// ```
1566    pub fn parent(&self) -> Option<Pid> {
1567        self.inner.parent()
1568    }
1569
1570    /// Returns the status of the process.
1571    ///
1572    /// ```no_run
1573    /// use sysinfo::{Pid, System};
1574    ///
1575    /// let s = System::new_all();
1576    /// if let Some(process) = s.process(Pid::from(1337)) {
1577    ///     println!("{:?}", process.status());
1578    /// }
1579    /// ```
1580    pub fn status(&self) -> ProcessStatus {
1581        self.inner.status()
1582    }
1583
1584    /// Returns the time where the process was started (in seconds) from epoch.
1585    ///
1586    /// ```no_run
1587    /// use sysinfo::{Pid, System};
1588    ///
1589    /// let s = System::new_all();
1590    /// if let Some(process) = s.process(Pid::from(1337)) {
1591    ///     println!("Started at {} seconds", process.start_time());
1592    /// }
1593    /// ```
1594    pub fn start_time(&self) -> u64 {
1595        self.inner.start_time()
1596    }
1597
1598    /// Returns for how much time the process has been running (in seconds).
1599    ///
1600    /// ```no_run
1601    /// use sysinfo::{Pid, System};
1602    ///
1603    /// let s = System::new_all();
1604    /// if let Some(process) = s.process(Pid::from(1337)) {
1605    ///     println!("Running since {} seconds", process.run_time());
1606    /// }
1607    /// ```
1608    pub fn run_time(&self) -> u64 {
1609        self.inner.run_time()
1610    }
1611
1612    /// Returns the total CPU usage (in %). Notice that it might be bigger than
1613    /// 100 if run on a multi-core machine.
1614    ///
1615    /// If you want a value between 0% and 100%, divide the returned value by
1616    /// the number of CPUs.
1617    ///
1618    /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed
1619    /// **twice** because CPU usage computation is based on time diff (process
1620    /// time on a given time period divided by total system time on the same
1621    /// time period).
1622    ///
1623    /// ⚠️ If you want accurate CPU usage number, better leave a bit of time
1624    /// between two calls of this method (take a look at
1625    /// [`MINIMUM_CPU_UPDATE_INTERVAL`][crate::MINIMUM_CPU_UPDATE_INTERVAL] for
1626    /// more information).
1627    ///
1628    /// ```no_run
1629    /// use sysinfo::{Pid, ProcessesToUpdate, ProcessRefreshKind, System};
1630    ///
1631    /// let mut s = System::new_all();
1632    /// // Wait a bit because CPU usage is based on diff.
1633    /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
1634    /// // Refresh CPU usage to get actual value.
1635    /// s.refresh_processes_specifics(
1636    ///     ProcessesToUpdate::All,
1637    ///     true,
1638    ///     ProcessRefreshKind::nothing().with_cpu()
1639    /// );
1640    /// if let Some(process) = s.process(Pid::from(1337)) {
1641    ///     println!("{}%", process.cpu_usage());
1642    /// }
1643    /// ```
1644    pub fn cpu_usage(&self) -> f32 {
1645        self.inner.cpu_usage()
1646    }
1647
1648    /// Returns the total accumulated CPU usage (in CPU-milliseconds). Note
1649    /// that it might be bigger than the total clock run time of a process if
1650    /// run on a multi-core machine.
1651    ///
1652    /// ```no_run
1653    /// use sysinfo::{Pid, System};
1654    ///
1655    /// let s = System::new_all();
1656    /// if let Some(process) = s.process(Pid::from(1337)) {
1657    ///     println!("{}", process.accumulated_cpu_time());
1658    /// }
1659    /// ```
1660    pub fn accumulated_cpu_time(&self) -> u64 {
1661        self.inner.accumulated_cpu_time()
1662    }
1663
1664    /// Returns number of bytes read and written to disk.
1665    ///
1666    /// ⚠️ On Windows, this method actually returns **ALL** I/O read and
1667    /// written bytes.
1668    ///
1669    /// ⚠️ Files might be cached in memory by your OS, meaning that reading/writing them might not
1670    /// increase the `read_bytes`/`written_bytes` values. You can find more information about it
1671    /// in the `proc_pid_io` manual (`man proc_pid_io` on unix platforms).
1672    ///
1673    /// ```no_run
1674    /// use sysinfo::{Pid, System};
1675    ///
1676    /// let s = System::new_all();
1677    /// if let Some(process) = s.process(Pid::from(1337)) {
1678    ///     let disk_usage = process.disk_usage();
1679    ///     println!("read bytes   : new/total => {}/{}",
1680    ///         disk_usage.read_bytes,
1681    ///         disk_usage.total_read_bytes,
1682    ///     );
1683    ///     println!("written bytes: new/total => {}/{}",
1684    ///         disk_usage.written_bytes,
1685    ///         disk_usage.total_written_bytes,
1686    ///     );
1687    /// }
1688    /// ```
1689    pub fn disk_usage(&self) -> DiskUsage {
1690        self.inner.disk_usage()
1691    }
1692
1693    /// Returns the ID of the owner user of this process or `None` if this
1694    /// information couldn't be retrieved. If you want to get the [`User`] from
1695    /// it, take a look at [`Users::get_user_by_id`].
1696    ///
1697    /// [`User`]: crate::User
1698    /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1699    ///
1700    /// ```no_run
1701    /// use sysinfo::{Pid, System};
1702    ///
1703    /// let mut s = System::new_all();
1704    ///
1705    /// if let Some(process) = s.process(Pid::from(1337)) {
1706    ///     println!("User id for process 1337: {:?}", process.user_id());
1707    /// }
1708    /// ```
1709    pub fn user_id(&self) -> Option<&Uid> {
1710        self.inner.user_id()
1711    }
1712
1713    /// Returns the user ID of the effective owner of this process or `None` if
1714    /// this information couldn't be retrieved. If you want to get the [`User`]
1715    /// from it, take a look at [`Users::get_user_by_id`].
1716    ///
1717    /// If you run something with `sudo`, the real user ID of the launched
1718    /// process will be the ID of the user you are logged in as but effective
1719    /// user ID will be `0` (i-e root).
1720    ///
1721    /// ⚠️ It always returns `None` on Windows.
1722    ///
1723    /// [`User`]: crate::User
1724    /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1725    ///
1726    /// ```no_run
1727    /// use sysinfo::{Pid, System};
1728    ///
1729    /// let mut s = System::new_all();
1730    ///
1731    /// if let Some(process) = s.process(Pid::from(1337)) {
1732    ///     println!("User id for process 1337: {:?}", process.effective_user_id());
1733    /// }
1734    /// ```
1735    pub fn effective_user_id(&self) -> Option<&Uid> {
1736        self.inner.effective_user_id()
1737    }
1738
1739    /// Returns the process group ID of the process.
1740    ///
1741    /// ⚠️ It always returns `None` on Windows.
1742    ///
1743    /// ```no_run
1744    /// use sysinfo::{Pid, System};
1745    ///
1746    /// let mut s = System::new_all();
1747    ///
1748    /// if let Some(process) = s.process(Pid::from(1337)) {
1749    ///     println!("Group ID for process 1337: {:?}", process.group_id());
1750    /// }
1751    /// ```
1752    pub fn group_id(&self) -> Option<Gid> {
1753        self.inner.group_id()
1754    }
1755
1756    /// Returns the effective group ID of the process.
1757    ///
1758    /// If you run something with `sudo`, the real group ID of the launched
1759    /// process will be the primary group ID you are logged in as but effective
1760    /// group ID will be `0` (i-e root).
1761    ///
1762    /// ⚠️ It always returns `None` on Windows.
1763    ///
1764    /// ```no_run
1765    /// use sysinfo::{Pid, System};
1766    ///
1767    /// let mut s = System::new_all();
1768    ///
1769    /// if let Some(process) = s.process(Pid::from(1337)) {
1770    ///     println!("User id for process 1337: {:?}", process.effective_group_id());
1771    /// }
1772    /// ```
1773    pub fn effective_group_id(&self) -> Option<Gid> {
1774        self.inner.effective_group_id()
1775    }
1776
1777    /// Returns the session ID for the current process or `None` if it couldn't
1778    /// be retrieved.
1779    ///
1780    /// ⚠️ This information is computed every time this method is called.
1781    ///
1782    /// ```no_run
1783    /// use sysinfo::{Pid, System};
1784    ///
1785    /// let mut s = System::new_all();
1786    ///
1787    /// if let Some(process) = s.process(Pid::from(1337)) {
1788    ///     println!("Session ID for process 1337: {:?}", process.session_id());
1789    /// }
1790    /// ```
1791    pub fn session_id(&self) -> Option<Pid> {
1792        self.inner.session_id()
1793    }
1794
1795    /// Tasks run by this process. If there are none, returns `None`.
1796    ///
1797    /// ⚠️ This method always returns `None` on other platforms than Linux.
1798    ///
1799    /// ```no_run
1800    /// use sysinfo::{Pid, System};
1801    ///
1802    /// let mut s = System::new_all();
1803    ///
1804    /// if let Some(process) = s.process(Pid::from(1337)) {
1805    ///     if let Some(tasks) = process.tasks() {
1806    ///         println!("Listing tasks for process {:?}", process.pid());
1807    ///         for task_pid in tasks {
1808    ///             if let Some(task) = s.process(*task_pid) {
1809    ///                 println!("Task {:?}: {:?}", task.pid(), task.name());
1810    ///             }
1811    ///         }
1812    ///     }
1813    /// }
1814    /// ```
1815    pub fn tasks(&self) -> Option<&HashSet<Pid>> {
1816        cfg_if! {
1817            if #[cfg(all(
1818                any(target_os = "linux", target_os = "android"),
1819                not(feature = "unknown-ci")
1820            ))] {
1821                self.inner.tasks.as_ref()
1822            } else {
1823                None
1824            }
1825        }
1826    }
1827
1828    /// If the process is a thread, it'll return `Some` with the kind of thread it is. Returns
1829    /// `None` otherwise.
1830    ///
1831    /// ⚠️ This method always returns `None` on other platforms than Linux.
1832    ///
1833    /// ```no_run
1834    /// use sysinfo::System;
1835    ///
1836    /// let s = System::new_all();
1837    ///
1838    /// for (_, process) in s.processes() {
1839    ///     if let Some(thread_kind) = process.thread_kind() {
1840    ///         println!("Process {:?} is a {thread_kind:?} thread", process.pid());
1841    ///     }
1842    /// }
1843    /// ```
1844    pub fn thread_kind(&self) -> Option<ThreadKind> {
1845        cfg_if! {
1846            if #[cfg(all(
1847                any(target_os = "linux", target_os = "android"),
1848                not(feature = "unknown-ci")
1849            ))] {
1850                self.inner.thread_kind()
1851            } else {
1852                None
1853            }
1854        }
1855    }
1856
1857    /// Returns `true` if the process doesn't exist anymore but was not yet removed from
1858    /// the processes list because the `remove_dead_processes` argument was set to `false`
1859    /// in methods like [`System::refresh_processes`].
1860    ///
1861    /// ```no_run
1862    /// use sysinfo::{ProcessesToUpdate, System};
1863    ///
1864    /// let mut s = System::new_all();
1865    /// // We set the `remove_dead_processes` to `false`.
1866    /// s.refresh_processes(ProcessesToUpdate::All, false);
1867    ///
1868    /// for (_, process) in s.processes() {
1869    ///     println!(
1870    ///         "Process {:?} {}",
1871    ///         process.pid(),
1872    ///         if process.exists() { "exists" } else { "doesn't exist" },
1873    ///     );
1874    /// }
1875    /// ```
1876    pub fn exists(&self) -> bool {
1877        self.inner.exists()
1878    }
1879
1880    /// Returns the number of open files in the current process.
1881    ///
1882    /// Returns `None` if it failed retrieving the information or if the current system is not
1883    /// supported.
1884    ///
1885    /// **Important**: this information is computed every time this function is called.
1886    ///
1887    /// ```no_run
1888    /// use sysinfo::System;
1889    ///
1890    /// let s = System::new_all();
1891    ///
1892    /// for (_, process) in s.processes() {
1893    ///     println!(
1894    ///         "Process {:?} {:?}",
1895    ///         process.pid(),
1896    ///         process.open_files(),
1897    ///     );
1898    /// }
1899    /// ```
1900    pub fn open_files(&self) -> Option<usize> {
1901        self.inner.open_files()
1902    }
1903
1904    /// Returns the maximum number of open files for the current process.
1905    ///
1906    /// Returns `None` if it failed retrieving the information or if the current system is not
1907    /// supported.
1908    ///
1909    /// **Important**: this information is computed every time this function is called.
1910    ///
1911    /// ```no_run
1912    /// use sysinfo::System;
1913    ///
1914    /// let s = System::new_all();
1915    ///
1916    /// for (_, process) in s.processes() {
1917    ///     println!(
1918    ///         "Process {:?} {:?}",
1919    ///         process.pid(),
1920    ///         process.open_files_limit(),
1921    ///     );
1922    /// }
1923    /// ```
1924    pub fn open_files_limit(&self) -> Option<usize> {
1925        self.inner.open_files_limit()
1926    }
1927}
1928
1929macro_rules! pid_decl {
1930    ($typ:ty) => {
1931        #[doc = include_str!("../../md_doc/pid.md")]
1932        #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
1933        #[repr(transparent)]
1934        pub struct Pid(pub(crate) $typ);
1935
1936        impl From<usize> for Pid {
1937            fn from(v: usize) -> Self {
1938                Self(v as _)
1939            }
1940        }
1941        impl From<Pid> for usize {
1942            fn from(v: Pid) -> Self {
1943                v.0 as _
1944            }
1945        }
1946        impl FromStr for Pid {
1947            type Err = <$typ as FromStr>::Err;
1948            fn from_str(s: &str) -> Result<Self, Self::Err> {
1949                Ok(Self(<$typ>::from_str(s)?))
1950            }
1951        }
1952        impl fmt::Display for Pid {
1953            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1954                write!(f, "{}", self.0)
1955            }
1956        }
1957        impl Pid {
1958            /// Allows to convert [`Pid`][crate::Pid] into [`u32`].
1959            ///
1960            /// ```
1961            /// use sysinfo::Pid;
1962            ///
1963            /// let pid = Pid::from_u32(0);
1964            /// let value: u32 = pid.as_u32();
1965            /// ```
1966            pub fn as_u32(self) -> u32 {
1967                self.0 as _
1968            }
1969            /// Allows to convert a [`u32`] into [`Pid`][crate::Pid].
1970            ///
1971            /// ```
1972            /// use sysinfo::Pid;
1973            ///
1974            /// let pid = Pid::from_u32(0);
1975            /// ```
1976            pub fn from_u32(v: u32) -> Self {
1977                Self(v as _)
1978            }
1979        }
1980    };
1981}
1982
1983cfg_if! {
1984    if #[cfg(all(
1985        not(feature = "unknown-ci"),
1986        any(
1987            target_os = "freebsd",
1988            target_os = "linux",
1989            target_os = "android",
1990            target_os = "macos",
1991            target_os = "ios",
1992        )
1993    ))] {
1994        use libc::pid_t;
1995
1996        pid_decl!(pid_t);
1997    } else {
1998        pid_decl!(usize);
1999    }
2000}
2001
2002/// This enum allows you to specify when you want the related information to be updated.
2003///
2004/// For example if you only want the [`Process::exe()`] information to be refreshed only if it's not
2005/// already set:
2006///
2007/// ```no_run
2008/// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System, UpdateKind};
2009///
2010/// let mut system = System::new();
2011/// system.refresh_processes_specifics(
2012///     ProcessesToUpdate::All,
2013///     true,
2014///     ProcessRefreshKind::nothing().with_exe(UpdateKind::OnlyIfNotSet),
2015/// );
2016/// ```
2017#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2018pub enum UpdateKind {
2019    /// Never update the related information.
2020    #[default]
2021    Never,
2022    /// Always update the related information.
2023    Always,
2024    /// Only update the related information if it was not already set at least once.
2025    OnlyIfNotSet,
2026}
2027
2028impl UpdateKind {
2029    /// If `self` is `OnlyIfNotSet`, `f` is called and its returned value is returned.
2030    #[allow(dead_code)] // Needed for unsupported targets.
2031    pub(crate) fn needs_update(self, f: impl Fn() -> bool) -> bool {
2032        match self {
2033            Self::Never => false,
2034            Self::Always => true,
2035            Self::OnlyIfNotSet => f(),
2036        }
2037    }
2038}
2039
2040/// This enum allows you to specify if you want all processes to be updated or just
2041/// some of them.
2042///
2043/// Example:
2044///
2045/// ```no_run
2046/// use sysinfo::{ProcessesToUpdate, System, get_current_pid};
2047///
2048/// let mut system = System::new();
2049/// // To refresh all processes:
2050/// system.refresh_processes(ProcessesToUpdate::All, true);
2051///
2052/// // To refresh only the current one:
2053/// system.refresh_processes(
2054///     ProcessesToUpdate::Some(&[get_current_pid().unwrap()]),
2055///     true,
2056/// );
2057/// ```
2058#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2059pub enum ProcessesToUpdate<'a> {
2060    /// To refresh all processes.
2061    All,
2062    /// To refresh only the processes with the listed [`Pid`].
2063    ///
2064    /// [`Pid`]: crate::Pid
2065    Some(&'a [Pid]),
2066}
2067
2068/// Used to determine what you want to refresh specifically on the [`Process`] type.
2069///
2070/// When all refresh are ruled out, a [`Process`] will still retrieve the following information:
2071///  * Process ID ([`Pid`])
2072///  * Parent process ID (on Windows it never changes though)
2073///  * Process name
2074///  * Start time
2075///
2076/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2077/// the information won't be retrieved if the information is accessible without needing
2078/// extra computation.
2079///
2080/// ⚠️ ** Linux Specific ** ⚠️
2081/// When using `ProcessRefreshKind::everything()`, in linux we will fetch all relevant
2082/// information from `/proc/<pid>/` as well as all the information from `/proc/<pid>/task/<tid>/`
2083/// folders. This makes the refresh mechanism a lot slower depending on the number of tasks
2084/// each process has.
2085///  
2086/// If you don't care about tasks information, use `ProcessRefreshKind::everything().without_tasks()`
2087/// as much as possible.
2088///
2089/// ```
2090/// use sysinfo::{ProcessesToUpdate, ProcessRefreshKind, System};
2091///
2092/// let mut system = System::new();
2093///
2094/// // We don't want to update the CPU information.
2095/// system.refresh_processes_specifics(
2096///     ProcessesToUpdate::All,
2097///     true,
2098///     ProcessRefreshKind::everything().without_cpu(),
2099/// );
2100///
2101/// for (_, proc_) in system.processes() {
2102///     // We use a `==` comparison on float only because we know it's set to 0 here.
2103///     assert_eq!(proc_.cpu_usage(), 0.);
2104/// }
2105/// ```
2106///
2107/// [`Process`]: crate::Process
2108#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2109pub struct ProcessRefreshKind {
2110    cpu: bool,
2111    disk_usage: bool,
2112    memory: bool,
2113    user: UpdateKind,
2114    cwd: UpdateKind,
2115    root: UpdateKind,
2116    environ: UpdateKind,
2117    cmd: UpdateKind,
2118    exe: UpdateKind,
2119    tasks: bool,
2120}
2121
2122/// Creates a new `ProcessRefreshKind` with every refresh set to `false`, except for `tasks`.
2123/// By default, we want to list all processes and tasks are considered processes on their own
2124/// in linux so we still fetch them by default. However, the processes information are not
2125/// refreshed.
2126impl Default for ProcessRefreshKind {
2127    fn default() -> Self {
2128        Self {
2129            cpu: false,
2130            disk_usage: false,
2131            memory: false,
2132            user: UpdateKind::default(),
2133            cwd: UpdateKind::default(),
2134            root: UpdateKind::default(),
2135            environ: UpdateKind::default(),
2136            cmd: UpdateKind::default(),
2137            exe: UpdateKind::default(),
2138            tasks: true, // Process by default includes all tasks.
2139        }
2140    }
2141}
2142
2143impl ProcessRefreshKind {
2144    /// Creates a new `ProcessRefreshKind` with every refresh set to `false`, except for `tasks`.
2145    /// By default, we want to list all processes and tasks are considered processes on their own
2146    /// in linux so we still fetch them by default. However, the processes information are not
2147    /// refreshed.
2148    /// ```
2149    /// use sysinfo::{ProcessRefreshKind, UpdateKind};
2150    ///
2151    /// let r = ProcessRefreshKind::nothing();
2152    ///
2153    /// assert_eq!(r.cpu(), false);
2154    /// assert_eq!(r.user(), UpdateKind::Never);
2155    /// ```
2156    pub fn nothing() -> Self {
2157        Self::default()
2158    }
2159
2160    /// Creates a new `ProcessRefreshKind` with every refresh set to `true` or
2161    /// [`UpdateKind::OnlyIfNotSet`].
2162    ///
2163    /// ```
2164    /// use sysinfo::{ProcessRefreshKind, UpdateKind};
2165    ///
2166    /// let r = ProcessRefreshKind::everything();
2167    ///
2168    /// assert_eq!(r.cpu(), true);
2169    /// assert_eq!(r.user(), UpdateKind::OnlyIfNotSet);
2170    /// ```
2171    pub fn everything() -> Self {
2172        Self {
2173            cpu: true,
2174            disk_usage: true,
2175            memory: true,
2176            user: UpdateKind::OnlyIfNotSet,
2177            cwd: UpdateKind::OnlyIfNotSet,
2178            root: UpdateKind::OnlyIfNotSet,
2179            environ: UpdateKind::OnlyIfNotSet,
2180            cmd: UpdateKind::OnlyIfNotSet,
2181            exe: UpdateKind::OnlyIfNotSet,
2182            tasks: true,
2183        }
2184    }
2185
2186    impl_get_set!(
2187        ProcessRefreshKind,
2188        cpu,
2189        with_cpu,
2190        without_cpu,
2191        "\
2192It will retrieve both CPU usage and CPU accumulated time,"
2193    );
2194    impl_get_set!(
2195        ProcessRefreshKind,
2196        disk_usage,
2197        with_disk_usage,
2198        without_disk_usage
2199    );
2200    impl_get_set!(
2201        ProcessRefreshKind,
2202        user,
2203        with_user,
2204        without_user,
2205        UpdateKind,
2206        "\
2207It will retrieve the following information:
2208
2209 * user ID
2210 * user effective ID (if available on the platform)
2211 * user group ID (if available on the platform)
2212 * user effective ID (if available on the platform)"
2213    );
2214    impl_get_set!(ProcessRefreshKind, memory, with_memory, without_memory);
2215    impl_get_set!(ProcessRefreshKind, cwd, with_cwd, without_cwd, UpdateKind);
2216    impl_get_set!(
2217        ProcessRefreshKind,
2218        root,
2219        with_root,
2220        without_root,
2221        UpdateKind
2222    );
2223    impl_get_set!(
2224        ProcessRefreshKind,
2225        environ,
2226        with_environ,
2227        without_environ,
2228        UpdateKind
2229    );
2230    impl_get_set!(ProcessRefreshKind, cmd, with_cmd, without_cmd, UpdateKind);
2231    impl_get_set!(ProcessRefreshKind, exe, with_exe, without_exe, UpdateKind);
2232    impl_get_set!(ProcessRefreshKind, tasks, with_tasks, without_tasks);
2233}
2234
2235/// Used to determine what you want to refresh specifically on the [`Cpu`] type.
2236///
2237/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2238/// the information won't be retrieved if the information is accessible without needing
2239/// extra computation.
2240///
2241/// ```
2242/// use sysinfo::{CpuRefreshKind, System};
2243///
2244/// let mut system = System::new();
2245///
2246/// // We don't want to update all the CPU information.
2247/// system.refresh_cpu_specifics(CpuRefreshKind::everything().without_frequency());
2248///
2249/// for cpu in system.cpus() {
2250///     assert_eq!(cpu.frequency(), 0);
2251/// }
2252/// ```
2253///
2254/// [`Cpu`]: crate::Cpu
2255#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2256pub struct CpuRefreshKind {
2257    cpu_usage: bool,
2258    frequency: bool,
2259}
2260
2261impl CpuRefreshKind {
2262    /// Creates a new `CpuRefreshKind` with every refresh set to `false`.
2263    ///
2264    /// ```
2265    /// use sysinfo::CpuRefreshKind;
2266    ///
2267    /// let r = CpuRefreshKind::nothing();
2268    ///
2269    /// assert_eq!(r.frequency(), false);
2270    /// assert_eq!(r.cpu_usage(), false);
2271    /// ```
2272    pub fn nothing() -> Self {
2273        Self::default()
2274    }
2275
2276    /// Creates a new `CpuRefreshKind` with every refresh set to `true`.
2277    ///
2278    /// ```
2279    /// use sysinfo::CpuRefreshKind;
2280    ///
2281    /// let r = CpuRefreshKind::everything();
2282    ///
2283    /// assert_eq!(r.frequency(), true);
2284    /// assert_eq!(r.cpu_usage(), true);
2285    /// ```
2286    pub fn everything() -> Self {
2287        Self {
2288            cpu_usage: true,
2289            frequency: true,
2290        }
2291    }
2292
2293    impl_get_set!(CpuRefreshKind, cpu_usage, with_cpu_usage, without_cpu_usage);
2294    impl_get_set!(CpuRefreshKind, frequency, with_frequency, without_frequency);
2295}
2296
2297/// Used to determine which memory you want to refresh specifically.
2298///
2299/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2300/// the information won't be retrieved if the information is accessible without needing
2301/// extra computation.
2302///
2303/// ```
2304/// use sysinfo::{MemoryRefreshKind, System};
2305///
2306/// let mut system = System::new();
2307///
2308/// // We don't want to update all memories information.
2309/// system.refresh_memory_specifics(MemoryRefreshKind::nothing().with_ram());
2310///
2311/// println!("total RAM: {}", system.total_memory());
2312/// println!("free RAM:  {}", system.free_memory());
2313/// ```
2314#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2315pub struct MemoryRefreshKind {
2316    ram: bool,
2317    swap: bool,
2318}
2319
2320impl MemoryRefreshKind {
2321    /// Creates a new `MemoryRefreshKind` with every refresh set to `false`.
2322    ///
2323    /// ```
2324    /// use sysinfo::MemoryRefreshKind;
2325    ///
2326    /// let r = MemoryRefreshKind::nothing();
2327    ///
2328    /// assert_eq!(r.ram(), false);
2329    /// assert_eq!(r.swap(), false);
2330    /// ```
2331    pub fn nothing() -> Self {
2332        Self::default()
2333    }
2334
2335    /// Creates a new `MemoryRefreshKind` with every refresh set to `true`.
2336    ///
2337    /// ```
2338    /// use sysinfo::MemoryRefreshKind;
2339    ///
2340    /// let r = MemoryRefreshKind::everything();
2341    ///
2342    /// assert_eq!(r.ram(), true);
2343    /// assert_eq!(r.swap(), true);
2344    /// ```
2345    pub fn everything() -> Self {
2346        Self {
2347            ram: true,
2348            swap: true,
2349        }
2350    }
2351
2352    impl_get_set!(MemoryRefreshKind, ram, with_ram, without_ram);
2353    impl_get_set!(MemoryRefreshKind, swap, with_swap, without_swap);
2354}
2355
2356/// Used to determine what you want to refresh specifically on the [`System`][crate::System] type.
2357///
2358/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
2359/// the information won't be retrieved if the information is accessible without needing
2360/// extra computation.
2361///
2362/// ```
2363/// use sysinfo::{RefreshKind, System};
2364///
2365/// // We want everything except memory.
2366/// let mut system = System::new_with_specifics(RefreshKind::everything().without_memory());
2367///
2368/// assert_eq!(system.total_memory(), 0);
2369/// # if sysinfo::IS_SUPPORTED_SYSTEM && !cfg!(feature = "apple-sandbox") {
2370/// assert!(system.processes().len() > 0);
2371/// # }
2372/// ```
2373#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
2374pub struct RefreshKind {
2375    processes: Option<ProcessRefreshKind>,
2376    memory: Option<MemoryRefreshKind>,
2377    cpu: Option<CpuRefreshKind>,
2378}
2379
2380impl RefreshKind {
2381    /// Creates a new `RefreshKind` with every refresh set to `false`/`None`.
2382    ///
2383    /// ```
2384    /// use sysinfo::RefreshKind;
2385    ///
2386    /// let r = RefreshKind::nothing();
2387    ///
2388    /// assert_eq!(r.processes().is_some(), false);
2389    /// assert_eq!(r.memory().is_some(), false);
2390    /// assert_eq!(r.cpu().is_some(), false);
2391    /// ```
2392    pub fn nothing() -> Self {
2393        Self::default()
2394    }
2395
2396    /// Creates a new `RefreshKind` with every refresh set to `true`/`Some(...)`.
2397    ///
2398    /// ```
2399    /// use sysinfo::RefreshKind;
2400    ///
2401    /// let r = RefreshKind::everything();
2402    ///
2403    /// assert_eq!(r.processes().is_some(), true);
2404    /// assert_eq!(r.memory().is_some(), true);
2405    /// assert_eq!(r.cpu().is_some(), true);
2406    /// ```
2407    pub fn everything() -> Self {
2408        Self {
2409            processes: Some(ProcessRefreshKind::everything()),
2410            memory: Some(MemoryRefreshKind::everything()),
2411            cpu: Some(CpuRefreshKind::everything()),
2412        }
2413    }
2414
2415    impl_get_set!(
2416        RefreshKind,
2417        processes,
2418        with_processes,
2419        without_processes,
2420        ProcessRefreshKind
2421    );
2422    impl_get_set!(
2423        RefreshKind,
2424        memory,
2425        with_memory,
2426        without_memory,
2427        MemoryRefreshKind
2428    );
2429    impl_get_set!(RefreshKind, cpu, with_cpu, without_cpu, CpuRefreshKind);
2430}
2431
2432/// Returns the pid for the current process.
2433///
2434/// `Err` is returned in case the platform isn't supported.
2435///
2436/// ```no_run
2437/// use sysinfo::get_current_pid;
2438///
2439/// match get_current_pid() {
2440///     Ok(pid) => {
2441///         println!("current pid: {}", pid);
2442///     }
2443///     Err(e) => {
2444///         println!("failed to get current pid: {}", e);
2445///     }
2446/// }
2447/// ```
2448#[allow(clippy::unnecessary_wraps)]
2449pub fn get_current_pid() -> Result<Pid, &'static str> {
2450    cfg_if! {
2451        if #[cfg(feature = "unknown-ci")] {
2452            fn inner() -> Result<Pid, &'static str> {
2453                Err("Unknown platform (CI)")
2454            }
2455        } else if #[cfg(any(
2456            target_os = "freebsd",
2457            target_os = "linux",
2458            target_os = "android",
2459            target_os = "macos",
2460            target_os = "ios",
2461        ))] {
2462            fn inner() -> Result<Pid, &'static str> {
2463                unsafe { Ok(Pid(libc::getpid())) }
2464            }
2465        } else if #[cfg(windows)] {
2466            fn inner() -> Result<Pid, &'static str> {
2467                use windows::Win32::System::Threading::GetCurrentProcessId;
2468
2469                unsafe { Ok(Pid(GetCurrentProcessId() as _)) }
2470            }
2471        } else {
2472            fn inner() -> Result<Pid, &'static str> {
2473                Err("Unknown platform")
2474            }
2475        }
2476    }
2477    inner()
2478}
2479
2480/// Contains all the methods of the [`Cpu`][crate::Cpu] struct.
2481///
2482/// ```no_run
2483/// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2484///
2485/// let mut s = System::new_with_specifics(
2486///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2487/// );
2488///
2489/// // Wait a bit because CPU usage is based on diff.
2490/// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
2491/// // Refresh CPUs again to get actual value.
2492/// s.refresh_cpu_all();
2493///
2494/// for cpu in s.cpus() {
2495///     println!("{}%", cpu.cpu_usage());
2496/// }
2497/// ```
2498pub struct Cpu {
2499    pub(crate) inner: CpuInner,
2500}
2501
2502impl Cpu {
2503    /// Returns this CPU's usage.
2504    ///
2505    /// Note: You'll need to refresh it at least twice (diff between the first and the second is
2506    /// how CPU usage is computed) at first if you want to have a non-zero value.
2507    ///
2508    /// ```no_run
2509    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2510    ///
2511    /// let mut s = System::new_with_specifics(
2512    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2513    /// );
2514    ///
2515    /// // Wait a bit because CPU usage is based on diff.
2516    /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
2517    /// // Refresh CPUs again to get actual value.
2518    /// s.refresh_cpu_all();
2519    ///
2520    /// for cpu in s.cpus() {
2521    ///     println!("{}%", cpu.cpu_usage());
2522    /// }
2523    /// ```
2524    pub fn cpu_usage(&self) -> f32 {
2525        self.inner.cpu_usage()
2526    }
2527
2528    /// Returns this CPU's name.
2529    ///
2530    /// ```no_run
2531    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2532    ///
2533    /// let s = System::new_with_specifics(
2534    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2535    /// );
2536    /// for cpu in s.cpus() {
2537    ///     println!("{}", cpu.name());
2538    /// }
2539    /// ```
2540    pub fn name(&self) -> &str {
2541        self.inner.name()
2542    }
2543
2544    /// Returns the CPU's vendor id.
2545    ///
2546    /// ```no_run
2547    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2548    ///
2549    /// let s = System::new_with_specifics(
2550    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2551    /// );
2552    /// for cpu in s.cpus() {
2553    ///     println!("{}", cpu.vendor_id());
2554    /// }
2555    /// ```
2556    pub fn vendor_id(&self) -> &str {
2557        self.inner.vendor_id()
2558    }
2559
2560    /// Returns the CPU's brand.
2561    ///
2562    /// ```no_run
2563    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2564    ///
2565    /// let s = System::new_with_specifics(
2566    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2567    /// );
2568    /// for cpu in s.cpus() {
2569    ///     println!("{}", cpu.brand());
2570    /// }
2571    /// ```
2572    pub fn brand(&self) -> &str {
2573        self.inner.brand()
2574    }
2575
2576    /// Returns the CPU's frequency.
2577    ///
2578    /// ```no_run
2579    /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
2580    ///
2581    /// let s = System::new_with_specifics(
2582    ///     RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
2583    /// );
2584    /// for cpu in s.cpus() {
2585    ///     println!("{}", cpu.frequency());
2586    /// }
2587    /// ```
2588    pub fn frequency(&self) -> u64 {
2589        self.inner.frequency()
2590    }
2591}
2592
2593#[cfg(test)]
2594mod test {
2595    use crate::*;
2596    use std::str::FromStr;
2597
2598    // In case `Process::updated` is misused, `System::refresh_processes` might remove them
2599    // so this test ensures that it doesn't happen.
2600    #[test]
2601    fn check_refresh_process_update() {
2602        if !IS_SUPPORTED_SYSTEM {
2603            return;
2604        }
2605        let mut s = System::new_all();
2606        let total = s.processes().len() as isize;
2607        s.refresh_processes(ProcessesToUpdate::All, false);
2608        let new_total = s.processes().len() as isize;
2609        // There should be almost no difference in the processes count.
2610        assert!(
2611            (new_total - total).abs() <= 5,
2612            "{} <= 5",
2613            (new_total - total).abs()
2614        );
2615    }
2616
2617    #[test]
2618    fn check_cpu_arch() {
2619        assert!(!System::cpu_arch().is_empty());
2620    }
2621
2622    // Ensure that the CPUs frequency isn't retrieved until we ask for it.
2623    #[test]
2624    fn check_cpu_frequency() {
2625        if !IS_SUPPORTED_SYSTEM {
2626            return;
2627        }
2628        let mut s = System::new();
2629        s.refresh_processes(ProcessesToUpdate::All, false);
2630        for proc_ in s.cpus() {
2631            assert_eq!(proc_.frequency(), 0);
2632        }
2633        s.refresh_cpu_usage();
2634        for proc_ in s.cpus() {
2635            assert_eq!(proc_.frequency(), 0);
2636        }
2637        // In a VM, it'll fail.
2638        if std::env::var("APPLE_CI").is_err() && std::env::var("FREEBSD_CI").is_err() {
2639            s.refresh_cpu_specifics(CpuRefreshKind::everything());
2640            for proc_ in s.cpus() {
2641                assert_ne!(proc_.frequency(), 0);
2642            }
2643        }
2644    }
2645
2646    #[test]
2647    fn check_process_memory_usage() {
2648        let mut s = System::new();
2649        s.refresh_specifics(RefreshKind::everything());
2650
2651        if IS_SUPPORTED_SYSTEM {
2652            // No process should have 0 as memory usage.
2653            #[cfg(not(feature = "apple-sandbox"))]
2654            assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
2655        } else {
2656            // There should be no process, but if there is one, its memory usage should be 0.
2657            assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
2658        }
2659    }
2660
2661    #[test]
2662    fn check_system_implemented_traits() {
2663        fn check<T: Sized + std::fmt::Debug + Default + Send + Sync>(_: T) {}
2664
2665        check(System::new());
2666    }
2667
2668    #[test]
2669    fn check_memory_usage() {
2670        let mut s = System::new();
2671
2672        assert_eq!(s.total_memory(), 0);
2673        assert_eq!(s.free_memory(), 0);
2674        assert_eq!(s.available_memory(), 0);
2675        assert_eq!(s.used_memory(), 0);
2676        assert_eq!(s.total_swap(), 0);
2677        assert_eq!(s.free_swap(), 0);
2678        assert_eq!(s.used_swap(), 0);
2679
2680        s.refresh_memory();
2681        if IS_SUPPORTED_SYSTEM {
2682            assert!(s.total_memory() > 0);
2683            assert!(s.used_memory() > 0);
2684            if s.total_swap() > 0 {
2685                // I think it's pretty safe to assume that there is still some swap left...
2686                assert!(s.free_swap() > 0);
2687            }
2688        } else {
2689            assert_eq!(s.total_memory(), 0);
2690            assert_eq!(s.used_memory(), 0);
2691            assert_eq!(s.total_swap(), 0);
2692            assert_eq!(s.free_swap(), 0);
2693        }
2694    }
2695
2696    #[cfg(target_os = "linux")]
2697    #[test]
2698    fn check_processes_cpu_usage() {
2699        if !IS_SUPPORTED_SYSTEM {
2700            return;
2701        }
2702        let mut s = System::new();
2703
2704        s.refresh_processes(ProcessesToUpdate::All, false);
2705        // All CPU usage will start at zero until the second refresh
2706        assert!(s
2707            .processes()
2708            .iter()
2709            .all(|(_, proc_)| proc_.cpu_usage() == 0.0));
2710
2711        // Wait a bit to update CPU usage values
2712        std::thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
2713        s.refresh_processes(ProcessesToUpdate::All, true);
2714        assert!(s
2715            .processes()
2716            .iter()
2717            .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
2718                && proc_.cpu_usage() <= (s.cpus().len() as f32) * 100.0));
2719        assert!(s
2720            .processes()
2721            .iter()
2722            .any(|(_, proc_)| proc_.cpu_usage() > 0.0));
2723    }
2724
2725    #[test]
2726    fn check_cpu_usage() {
2727        if !IS_SUPPORTED_SYSTEM {
2728            return;
2729        }
2730        let mut s = System::new();
2731        for _ in 0..10 {
2732            s.refresh_cpu_usage();
2733            // Wait a bit to update CPU usage values
2734            std::thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
2735            if s.cpus().iter().any(|c| c.cpu_usage() > 0.0) {
2736                // All good!
2737                return;
2738            }
2739        }
2740        panic!("CPU usage is always zero...");
2741    }
2742
2743    #[test]
2744    fn check_system_info() {
2745        // We don't want to test on unsupported systems.
2746        if IS_SUPPORTED_SYSTEM {
2747            assert!(!System::name()
2748                .expect("Failed to get system name")
2749                .is_empty());
2750
2751            assert!(!System::kernel_version()
2752                .expect("Failed to get kernel version")
2753                .is_empty());
2754
2755            assert!(!System::os_version()
2756                .expect("Failed to get os version")
2757                .is_empty());
2758
2759            assert!(!System::long_os_version()
2760                .expect("Failed to get long OS version")
2761                .is_empty());
2762        }
2763
2764        assert!(!System::distribution_id().is_empty());
2765    }
2766
2767    #[test]
2768    fn check_host_name() {
2769        // We don't want to test on unsupported systems.
2770        if IS_SUPPORTED_SYSTEM {
2771            assert!(System::host_name().is_some());
2772        }
2773    }
2774
2775    #[test]
2776    fn check_refresh_process_return_value() {
2777        // We don't want to test on unsupported systems.
2778        if IS_SUPPORTED_SYSTEM {
2779            let _pid = get_current_pid().expect("Failed to get current PID");
2780
2781            #[cfg(not(feature = "apple-sandbox"))]
2782            {
2783                let mut s = System::new();
2784                // First check what happens in case the process isn't already in our process list.
2785                assert_eq!(
2786                    s.refresh_processes(ProcessesToUpdate::Some(&[_pid]), true),
2787                    1
2788                );
2789                // Then check that it still returns 1 if the process is already in our process list.
2790                assert_eq!(
2791                    s.refresh_processes(ProcessesToUpdate::Some(&[_pid]), true),
2792                    1
2793                );
2794            }
2795        }
2796    }
2797
2798    #[test]
2799    fn check_cpus_number() {
2800        let mut s = System::new();
2801
2802        // This information isn't retrieved by default.
2803        assert!(s.cpus().is_empty());
2804        if IS_SUPPORTED_SYSTEM {
2805            // The physical cores count is recomputed every time the function is called, so the
2806            // information must be relevant even with nothing initialized.
2807            let physical_cores_count =
2808                System::physical_core_count().expect("failed to get number of physical cores");
2809
2810            s.refresh_cpu_usage();
2811            // The cpus shouldn't be empty anymore.
2812            assert!(!s.cpus().is_empty());
2813
2814            // In case we are running inside a VM, it's possible to not have a physical core, only
2815            // logical ones, which is why we don't test `physical_cores_count > 0`.
2816            let physical_cores_count2 =
2817                System::physical_core_count().expect("failed to get number of physical cores");
2818            assert!(physical_cores_count2 <= s.cpus().len());
2819            assert_eq!(physical_cores_count, physical_cores_count2);
2820        } else {
2821            assert_eq!(System::physical_core_count(), None);
2822        }
2823        assert!(System::physical_core_count().unwrap_or(0) <= s.cpus().len());
2824    }
2825
2826    // This test only exists to ensure that the `Display` and `Debug` traits are implemented on the
2827    // `ProcessStatus` enum on all targets.
2828    #[test]
2829    fn check_display_impl_process_status() {
2830        println!("{} {:?}", ProcessStatus::Parked, ProcessStatus::Idle);
2831    }
2832
2833    #[test]
2834    #[allow(clippy::unnecessary_fallible_conversions)]
2835    fn check_pid_from_impls() {
2836        assert!(crate::Pid::try_from(0usize).is_ok());
2837        // If it doesn't panic, it's fine.
2838        let _ = crate::Pid::from(0);
2839        assert!(crate::Pid::from_str("0").is_ok());
2840    }
2841
2842    #[test]
2843    #[allow(clippy::const_is_empty)]
2844    fn check_nb_supported_signals() {
2845        if IS_SUPPORTED_SYSTEM {
2846            assert!(
2847                !SUPPORTED_SIGNALS.is_empty(),
2848                "SUPPORTED_SIGNALS shouldn't be empty on supported systems!"
2849            );
2850        } else {
2851            assert!(
2852                SUPPORTED_SIGNALS.is_empty(),
2853                "SUPPORTED_SIGNALS should be empty on not support systems!"
2854            );
2855        }
2856    }
2857}
2858
2859#[cfg(doctest)]
2860mod doctest {
2861    // FIXME: Can be removed once negative trait bounds are supported.
2862    /// Check that `Process` doesn't implement `Clone`.
2863    ///
2864    /// First we check that the "basic" code works:
2865    ///
2866    /// ```no_run
2867    /// use sysinfo::{Process, System};
2868    ///
2869    /// let mut s = System::new_all();
2870    /// let p: &Process = s.processes().values().next().unwrap();
2871    /// ```
2872    ///
2873    /// And now we check if it fails when we try to clone it:
2874    ///
2875    /// ```compile_fail
2876    /// use sysinfo::{Process, System};
2877    ///
2878    /// let mut s = System::new_all();
2879    /// let p: &Process = s.processes().values().next().unwrap();
2880    /// let p = (*p).clone();
2881    /// ```
2882    mod process_clone {}
2883
2884    // FIXME: Can be removed once negative trait bounds are supported.
2885    /// Check that `System` doesn't implement `Clone`.
2886    ///
2887    /// First we check that the "basic" code works:
2888    ///
2889    /// ```no_run
2890    /// use sysinfo::{Process, System};
2891    ///
2892    /// let s = System::new();
2893    /// ```
2894    ///
2895    /// And now we check if it fails when we try to clone it:
2896    ///
2897    /// ```compile_fail
2898    /// use sysinfo::{Process, System};
2899    ///
2900    /// let s = System::new();
2901    /// let s = s.clone();
2902    /// ```
2903    mod system_clone {}
2904}