sysinfo/common/
system.rs

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