Coverage Report

Created: 2025-02-21 07:11

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