【linux】进程|查看进程|PID值|fork原理(上)

简介: 【linux】进程|查看进程|PID值|fork原理(上)

1. 什么是进程

假设在一个文件中写代码,并生成一个可执行程序在磁盘中,可执行程序本质也是一个二进制文件

文件 =内容+属性

内容即 自己写的代码和数据

属性即 创建时间、权限等信息

使用 ./ 将其加载到内存中,cpu访问代码和数据,从而执行代码, 把代码和数据放入内存中 就可以叫做进程么?

当然不是!

- 举例:

如何成为你的学校的学生呢?

只要想办法进入你的学校里,在学校里,就是你的学校的学生么?

当然不是,看门的大爷和楼管阿姨也在学校里

想要成为学生,必须在学籍档案中有你个人的基本信息

同理,只把代码和数据放入内存中,不叫作进程

为什么基本信息在学籍档案中呢?

因为学校要对学生管理

随着程序加载到内存的数量增多,操作系统就要考虑如何把加载的代码个数据进行管理,

所以操作系统要管理进程

管理的本质是先描述,在管理 (不懂的可以点击查看具体解释)

管理本质的解释

描述

使用结构体构建了结构体对象,在操作系统教材中叫做 PCB ,在Linux中叫做 task_struct

并且结构体提取了所有进程的属性

同样使用各自的结构体,可以找到各自的代码和数据

组织

将结构体通过特定数据结构关联起来(以链表为例)

通过链表的增删查改操作,来完成对进程的增加、删除、查找、修改

结论

进程是内核关于进程的相关数据结构+当前进程的代码和数据

2.查看进程

查看进程方法1

 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   while(1)
  6   {
  7     printf("hello world\n");
  8     sleep(1);                                                                                                                                                        
  9   }
 10   return 0;
 11 }

创建一个pro.c的文件,同时生成一个可执行程序pro,使之无线循环下去

创建终端

在第一个终端中点击右键,复制SSH渠道,就会自动生成终端2


输入命令显示进程

在保证终端1的pro程序运行时,在第二个终端中

ps axj 查看当前系统中所有的进程

head -1 取第一行指令

grep pro 只查看自己的进程

grep -v grep 除了grep的内容显示出来

输入 ps axj | head -1 && ps axj | grep pro | grep -v grep,即可查看当前pro可执行程序的进程

[yzq@VM-8-8-centos ~]$ ps axj | head -1 && ps axj | grep pro | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
 3754  3943  3943  3754 pts/0     3943 S+    1002   0:00 ./pro

一个程序存在多个进程

首先创建三个终端

  • 在终端2和终端3中同时运行 ./pro ,再次在终端1中使用指令ps axj | head -1 && ps axj | grep pro | grep -v grep,发现生成两个PID值不同的进程
  • 将一个可执行程序多次加载内存,可执行程序内部存在多个进程

查看进程方法2

ls /proc,proc 为process的简称,保存进程相关属性的目录

  • 蓝色的数字就是进程的PID

查看成功

  • 在保证终端1正在运行./pro,在终端2中以第一次生成的PID为例

  • PID值为3943,ls proc/3943,即可查看相关的进程属性

查看失败

  • 若将终端1的pro可执行程序关闭,则进程不存在
[yzq@VM-8-8-centos ~]$ ls /proc/28439
ls: cannot access /proc/28439: No such file or directory

结论

  • 当把进程创建时,proc目录下会自动创建以PID命名的目录,里面会把内存运行的属性呈现出来
  • 当把进程终止时,proc目录下会自动把PID命名的目录全部删除

3.通过系统调用获取进程标识符

1.获取PID值

  • getpid 需要头文件 <sys/types.h> 和<unistd.h>,返回值为 getpid_t类型,表示当前进程的PID值
#include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6   while(1)
  7   {
  8     printf("我已经是一个进程了,PID为:%d\n",getpid());                                                                                                              
  9     sleep(1);                                                                                                                        
 10   }                                                                                                                                  
 11   return 0;                                                                                                                          
 12 }      
  • 在之前的pro.c文件进行修改,将其内容修改为上面的,并在终端1中使用./pro 执行可执行程序
[yzq@VM-8-8-centos lesson]$ ./pro
我已经是一个进程了,PID为:28286
我已经是一个进程了,PID为:28286
我已经是一个进程了,PID为:28286
我已经是一个进程了,PID为:28286
我已经是一个进程了,PID为:28286
我已经是一个进程了,PID为:28286
我已经是一个进程了,PID为:28286
  • 会生成不间断的相同PID值

验证PID值是否正确

  • 再次创建一个终端,并命名为终端2,并保证上述的pro程序在终端1中运行的情况下,使用指令 ps axj | head -1 && ps axj | grep pro | grep -v grep,发现PID值相同
[yzq@VM-8-8-centos lesson]$ ps axj | head -1 && ps axj | grep pro | grep -v grep
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
26652 28286 28286 26652 pts/0    28286 S+    1002   0:00 ./pro

2. 获取父进程PID值

getppid 头文件与getpid相同,返回值为父进程的PID值

 1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6   while(1)
  7   {
  8     printf("我已经是一个进程了,PID为:%d,我的父进程PID为:%d\n",getpid(),getppid());                                                                                 
  9     sleep(1);                                                                                                                                                    
 10   }                                                                                                                                                              
 11   return 0;                                                                                                                                                      
 12 }  
  • 再次将终端1中的pro.c文件内容修改为上面
[yzq@VM-8-8-centos lesson]$ ./pro
我已经是一个进程了,PID为:1013,我的父进程PID为:32452
我已经是一个进程了,PID为:1013,我的父进程PID为:32452
我已经是一个进程了,PID为:1013,我的父进程PID为:32452
我已经是一个进程了,PID为:1013,我的父进程PID为:32452

验证

  • ,在确保终端1中的pro可执行程序正在运行,打开终端2, 输入ps axj | head -1 && ps axj | grep pro | grep -v grep 指令
[yzq@VM-8-8-centos lesson]$ ps axj | head -1 && ps axj | grep pro | grep -v grep 
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
32452  1013  1013 32452 pts/2     1013 S+    1002   0:00 ./pro
  • 说明使用getppid查询结果正确

3. 父进程为什么不变化?

[yzq@VM-8-8-centos lesson]$ ./pro
我已经是一个进程了,PID为:2050,我的父进程PID为:32452
^C
[yzq@VM-8-8-centos lesson]$ ./pro
我已经是一个进程了,PID为:2059,我的父进程PID为:32452
^C
[yzq@VM-8-8-centos lesson]$ ./pro
我已经是一个进程了,PID为:2065,我的父进程PID为:32452
^C
相关文章
|
5月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
138 16
|
4月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
86 0
|
4月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
118 0
|
4月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
84 0
|
4月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
82 0
|
7月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
7月前
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
352 5
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
428 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。