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