Coverage Report

Created: 2026-09-19 07:25

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