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