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