Skip to main content

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