Skip to main content

sysinfo/common/
system.rs

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