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}