文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-09-26 12:30

关注

文章目录

1. 什么是进程

在这里插入图片描述
假设在一个文件中写代码,并生成一个可执行程序在磁盘中,可执行程序本质也是一个二进制文件
文件 =内容+属性
内容即 自己写的代码和数据
属性即 创建时间、权限等信息

在这里插入图片描述

在这里插入图片描述
随着程序加载到内存的数量增多,操作系统就要考虑如何把加载的代码个数据进行管理,
所以操作系统要管理进程
管理的本质是先描述,在管理 (不懂的可以点击查看具体解释)

管理本质的解释

描述

在这里插入图片描述
使用结构体构建了结构体对象,在操作系统教材中叫做 PCB ,在Linux中叫做 task_struct
并且结构体提取了所有进程的属性
同样使用各自的结构体,可以找到各自的代码和数据

组织

将结构体通过特定数据结构关联起来(以链表为例)
在这里插入图片描述
通过链表的增删查改操作,来完成对进程的增加、删除、查找、修改

结论

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

2.查看进程

查看进程方法1

 #include  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

ls /proc,proc 为process的简称,保存进程相关属性的目录
在这里插入图片描述

查看成功

在这里插入图片描述

在这里插入图片描述

查看失败
[yzq@VM-8-8-centos ~]$ ls /proc/28439ls: cannot access /proc/28439: No such file or directory
结论

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

1.获取PID值

#include  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 }      
[yzq@VM-8-8-centos lesson]$ ./pro我已经是一个进程了,PID为:28286我已经是一个进程了,PID为:28286我已经是一个进程了,PID为:28286我已经是一个进程了,PID为:28286我已经是一个进程了,PID为:28286我已经是一个进程了,PID为:28286我已经是一个进程了,PID为:28286
验证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 COMMAND26652 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 }  
[yzq@VM-8-8-centos lesson]$ ./pro我已经是一个进程了,PID为:1013,我的父进程PID为:32452我已经是一个进程了,PID为:1013,我的父进程PID为:32452我已经是一个进程了,PID为:1013,我的父进程PID为:32452我已经是一个进程了,PID为:1013,我的父进程PID为:32452
验证
[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 COMMAND32452  1013  1013 32452 pts/2     1013 S+    1002   0:00 ./pro
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
[yzq@VM-8-8-centos lesson]$ ps ajx | head -1 && ps ajx |grep 32452 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND  907  3167  3166   907 pts/3     3166 R+    1002   0:00 grep --color=auto 3245232451 32452 32452 32452 pts/2    32452 Ss+   1002   0:00 -bash
4. 为什么都是bash?

bash怕你写的代码有问题,所以使用bash创建的子进程完成任务,这样就算是挂了,bash也没事

4.指定进程暂停

[yzq@VM-8-8-centos lesson]$ ./pro我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428我已经是一个进程了,PID为:29031,我的父进程PID为:28428Killed

5.如何创建子进程

创建子进程—— fork,头文件为 ,返回值是 pid_t类型

#include  2 #include<sys/types.h>  3 #include<unistd.h>  4 int main()  5 {  6   printf("AAAA\n");  7   fork();  8   printf("BBBB\n");  9  sleep(1);                10   return 0;                      11 } 
[yzq@VM-8-8-centos lesson]$ ./proAAAABBBBBBBB
#include  2 #include<sys/types.h>  3 #include<unistd.h>  4 int main()  5 {  6   printf("AAAA\n");  7   fork();  8   printf("BBBB:pid:%d,ppid:%d\n",getpid(),getppid());  9  sleep(1);               10   return 0;              11 }  
[yzq@VM-8-8-centos lesson]$ ./proAAAABBBB:pid:4285,ppid:31919BBBB:pid:4286,ppid:4285

1. fork返回值

  1 #include<stdio.h>  2 #include<sys/types.h>  3 #include<unistd.h>  4 int main()  5 {  6   printf("AAAA\n");  7  pid_t ret= fork();  8   printf("BBBB:pid:%d,ppid:%d,%d,%p\n",getpid(),getppid(),ret,&ret);  9  sleep(1);                      10   return 0;                     11 } 
[yzq@VM-8-8-centos lesson]$ ./proAAAABBBB:pid:7799,ppid:31919,7800,0x7ffefc72c02cBBBB:pid:7800,ppid:7799,0,0x7ffefc72c02c

在终端1中运行./pro,上面的BBBB,ret值返回是下面BBBB的PID值 ,说明是父进程
而下面的BBBB,ret值为0,说明是子进程

2.使父子进程执行不同的任务

#include  2 #include<sys/types.h>  3 #include<unistd.h>  4 int main()  5 {  6  pid_t ret= fork();  7  if(ret==0)  8  {  9    //子进程 10    while(1)   11    { 12    printf("我是子进程,我的pid是:%d,我的父进程是:%d\n",getpid(),getppid()); 13    sleep(1); 14    } 15      16  } 17  else if(ret>0) 18  { 19    //父进程 20    while(1) 21    { 22    printf("我是父进程,我的pid是:%d,我的父进程是:%d\n",getpid(),getppid()); 23    sleep(1); 24    }                      25  } 26  else 27  {    //报错 29  }          30   return 0; }
[yzq@VM-8-8-centos lesson]$ ./pro我是父进程,我的pid是:13505,我的父进程是:31919我是子进程,我的pid是:13506,我的父进程是:13505我是子进程,我的pid是:13506,我的父进程是:13505我是父进程,我的pid是:13505,我的父进程是:31919我是子进程,我的pid是:13506,我的父进程是:13505我是父进程,我的pid是:13505,我的父进程是:31919我是父进程,我的pid是:13505,我的父进程是:31919我是子进程,我的pid是:13506,我的父进程是:13505

父进程和子进程是同时运行的
说明在多执行流的环境下 if和else if可以同时成立

3. 结论

6. fork 原理

1.fork做了什么

在这里插入图片描述

子进程pcb的大部分属性会以父进程pcb为模板,把父进程大部分里面的数据拷给子进程
小部分属于子进程私有的,例如PID、PPID值
因为进程等于数据结构+代码和数据,所以父进程指向自己的代码和数据,子进程也会指向同样的代码和数据
创建子进程:创建独立的pcb结构,父子进程看到的是同一份代码和数据

2.fork 如何看待代码和数据

在这里插入图片描述

当我们把画图关闭后,并不会影响有道云笔记的使用,说明他们都是独立存在的
进程在运行的时候,是具有独立性的
当我们在执行代码同时运行父子进程时,若使用 kill- 9 干掉父进程后,子进程仍能运行
父子进程在运行时,也是具有独立性的

父子进程指向同一块代码和数据,独立性如何保证?

代码:
代码在内存区域是只读的(从来不会自己发生变化,不会有人修改)
父子进程两者都读,不会互相影响

数据:

  1 #include<stdio.h>    2 #include<sys/types.h>    3 #include<unistd.h>    4 int main()    5 {    6   int x=100;    7  pid_t ret= fork();    8  if(ret==0)    9  {   10    //子进程   11    while(1)   12    { 13    printf("我是子进程,我的pid是:%d,我的父进程是:%d,%d\n",getpid(),getppid(),x); 14    sleep(1); 15    } 16      17  } 18  else if(ret>0) 19  { 20    //父进程 21    while(1) 22    { 23    printf("我是父进程,我的pid是:%d,我的父进程是:%d,%d\n",getpid(),getppid(),x); 24    x=50; 25    sleep(1); 26    } 27  } 28   return 0; 29 }   
[yzq@VM-8-8-centos lesson]$ ./pro我是父进程,我的pid是:26332,我的父进程是:21231,100我是子进程,我的pid是:26333,我的父进程是:26332,100我是父进程,我的pid是:26332,我的父进程是:21231,50我是子进程,我的pid是:26333,我的父进程是:26332,100我是父进程,我的pid是:26332,我的父进程是:21231,50我是子进程,我的pid是:26333,我的父进程是:26332,100我是父进程,我的pid是:26332,我的父进程是:21231,50我是子进程,我的pid是:26333,我的父进程是:26332,100

使用./pro执行可执行程序,修改父进程中的x值后,只有父进程的x值被修改,子进程x值不变
说明如果有一个进程把数据改了,并不会影响另一个进程
当有一个执行流尝试修改数据的时候,操作系统自动给当前进程触发:写时拷贝
4

3.fork如何理解两个返回值问题

在这里插入图片描述

来源地址:https://blog.csdn.net/qq_62939852/article/details/128723839

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯