当前位置: 首页 > news >正文

6、进程理论和简单进程创建

一、了解进程推荐看这个视频,很详细

1、概念

  • 进程(Process)=程序的运行过程,是系统进行资源分配和调度的独立单元
  • 程序的运行过程:多个不同程序 并发,同一个程序同时执行多个任务。
    • 就需要很多资源来实现这个过程
  • 每个进程都有一个独立的地址空间【空间由0开始扩大,直到最大值,成一个连续的空间】。在这个空间里,进程能够执行读写操作,存放可执行的程序代码、程序运行所需的资源以及函数调用和局部变量存储的栈结构。
  • 进程控制块PCB):
    • 是一个数据结构
    • 描述进程的基本情况和运行状态
    • 为控制和管理提供数据依据

2、访问linux的进程方法

那么如何查看进程?
基本语法:ps 选项
a:显示当前终端下的所有进程信息,包括其他用户的进程
u:以用户为主的进程状态
x:通常与 a 这个参数一起使用,显示当前用户在所有终端下的进程信息
-e:显示系统内所有的进程信息
-l:使用长格式显示进程信息
-f:使用完整的格式显示进程信息
在这里插入图片描述

//使用ps -aux
ps -aux

在这里插入图片描述

ps -elf

在这里插入图片描述

top
q       退出显示
top -d  默认三秒,指定top命令每隔几秒刷新
top -i  使用top不显示任何闲置或者僵死的进程
top -p  通过指定监控ID来仅仅监考某个进程的状态
例如:
top -d 10  每10秒刷新1次
  • top命令将会在当前终端以全屏交互式的界面显示进程排名,及时跟踪CPU、内存等系统资源占用情况,默认情况下每三秒刷新一次,其作用类似于windows系统中的任务管理器。
    在这里插入图片描述
    在这里插入图片描述
pgrep 
  • 使用pgrep命令可以根据进程的名称、运行该进程的用户、进程所在的终端等多中属性查询特定进程的PID号
pstree  选项
-u  显示进程的用户名
-p  显示进程号(PID)
  • 将进程以树形的结构展现出来

3、删除进程

kill 进程号   删除进程
kill -9 进程号 强制删除进程 

4、进程的文件

  • 在**/proc/里面**
    在这里插入图片描述
    这些蓝色的就是进程号。

二、进程模型

严格来说,一个CPU核心在任一时刻仅能执行一个线程的任务,即便是系统配置有双核心(或更多CPU)时每个核心也是独立地且一次仅执行一个线程

  • 进程的组成
    • 1、代码段和相关数据段
    • 2、PCB(进程控制块)
      • 2.1、PCB包含的信息
      • ①进程标识符PID
      • ②进程控制管理信息
      • ③资源清单
      • ④进程调度信息
      • ⑤处理机状态
      • 2.2、PCB是什么?
      • ①是一个数据结构
      • ②描述进程的基本情况和运行状态
      • ③为管理和控制提供数据依据
  • 抽象的角度看,每个进程似乎都配备了专属的虚拟CPU以支持其独立执行,但物理程度上,CPU通过时间片机制在多个进程间进行快速切换从而并发执行的假象。【简而言之:抽象看是每个进程都有一个CPU;物理上看是只有一个CPU供所有进程使用,进程用时间片机制来快速切换,像并发一样。】
  • 如下图【物理上看】:

在这里插入图片描述

  • 如下图【抽象上看】

在这里插入图片描述

  • 所以可以发现:
    • 在经历足够长的一段时间后,所有的进程都运行了,但实际上在任何一个给定的瞬间仅有一个进程真正运行
    • 所以它们实际上是这样运行【A运行一点时间,就给B运行,B运行一点给C运行,如果需要回到A,就使用PCB,PCB记录了之前的状态。】的,如下图:
    • 在这里插入图片描述
  • PCB进程控制管理信息
    • 代码段和数据段的地址
    • 进程同步和通信信息
    • 资源清单地址
    • 进程队列指针
  • PCB处理机状态
    • 处理机中寄存器的内容
    • 作用:CPU切换时保存现场信息和回复现场信息。
  • PCB进程标识符
    • 进程号
  • PCB资源清单
    • 内存地址
    • 虚拟地址
    • 打开文件列表
    • I/O设备信息
  • PCB进程调度信息
    • 进程状态
    • 优先级
    • 等待和使用CPU时间总和
    • 进程调度和对换依据
  • 进程与进程之间怎么数据交换?
    • 依靠操作系统内核

    • 在这里插入图片描述

    • 但是从上图可知:进程1和进程2是独立的个体。似乎不相互影响。

  • 我们通过2段代码来理解【推荐先看下面部分的编程再看这里
  • 首先是创建一个全局变量 global_vary = 100 。再在child函数里改global_vary =200 。然后我们运行代码,得到结果如下图:
  • 会发现,parent还是100 。child的是200 。

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int global_vary = 100;//创建了一个全局变量
void child(){
        global_vary =200;
        printf("in child process:%d global_vary:%d \n",getpid(),global_vary);
}
void parent(){
        sleep(3);//休眠3秒后,再运行。
        printf("int parent process:%d global_vary:%d \n",getpid(),global_vary);
}
int main(){
        pid_t pid;
        pid=fork();
        if(pid<0){
                perror("fork have problem\n");
                exit(0);//释放pid
        }else if(pid==0){//child
                child();
        }else if(pid>0){
                parent();
        }
        return 0;

}

  • 使用sleep 修改
  • 让 子进程结束变慢。
    在这里插入图片描述
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int global_vary = 100;//创建了一个全局变量
void child(){
        global_vary =200;
        printf("in child process:%d global_vary:%d \n",getpid(),global_vary);
        sleep(3);
}
void parent(){
        sleep(1);        printf("int parent process:%d global_vary:%d \n",getpid(),global_vary);
}
int main(){
        pid_t pid;
        pid=fork();
        if(pid<0){
                perror("fork have problem\n");
                exit(0);//释放pid
        }else if(pid==0){//child
                child();
        }else if(pid>0){
                parent();
        }
        return 0;

}

就会发现结果还是 200 ,100 。
这就能体现出他们是独立的
它们是独立占用 0-3G虚拟空间。

三、进程的创建

1、了解情况

  • 随机分配,谁先获得CPU的使用权
  • 通过返回值来区分父子进程
  • 返回是2次,一次是父进程的,另一次是子进程的
  • 子父进程共享文件

2、简单编程实现

2.1、getpid和getppid和fork

  • fork() 的作用
    • fork() 会创建一个子进程,父进程返回子进程的 PID,子进程返回 0
    • 如果 fork() 失败(如系统资源不足),返回 -1,并进入错误处理。
  • getpid() 和 getppid()
    • getpid():返回当前进程PID
    • getppid():返回当前进程父进程 PID
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid;
    pid = fork();

    if (pid < 0) {
        perror("fork failed\n");
        exit(1);
    } else if (pid == 0) {
        printf("子进程: PID = %d, PPID = %d\n", getpid(), getppid());
        
    } else {
        printf("父进程: PID = %d, PPID = %d\n", getpid(), getppid());
        wait(NULL);  // 父进程等待子进程结束
    }
    return 0;
}

2.2、sleep

如果我想让子进程先运行,父进程后运行。就可以使用sleep(时间) 。这里的时间是默认按秒的时间,休眠作用。


#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void child(){
        printf("in child process:%d \n",getpid());
}
void parent(){
        sleep(3);//休眠3秒后,再运行。
        printf("int parent process:%d \n",getpid());
}
int main(){
        pid_t pid;
        pid=fork();
        if(pid<0){
                perror("fork have problem\n");
                exit(0);//释放pid
        }else if(pid==0){//child
                child();
                exit(0);
        }else if(pid>0){
                parent();
                exit(0);
        }
        return 0;

}

在这里插入图片描述

2.3、execlp和excvp

  • execvpexeclp很像,只是参数的写法不同
  • 都通过PATH的方式查找。
    • execvp的参数是指针数组
    • execlp的参数是可变参数列表
#include <unistd.h>

int main() {
    execlp("ls", "ls", "-l", NULL);  // 等价于 execvp("ls", {"ls", "-l", NULL})
    perror("execlp failed");
    return 1;
}
  • exlvp的作用:
    • 用于 替换当前进程的映像即运行另一个程序,当前进程的代码和数据会被新程序覆盖 。替换后,原进程的代码不会执行了。)。
函数原型
#include <unistd.h>
int execvp(const char *file, char *const argv[]);
argv以NULL结尾
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(){
        pid_t pid;
        pid=fork();
        if(pid<0){
                perror("fork have problem\n");
                exit(0);//释放pid
        }else if(pid==0){
                //替换成当前父进程的上下文,替换成新的进程静态数据区
                int ret=execlp("ls","ls","-l",NULL);
                if(ret<0){
                        perror("execlp error");
                        exit(-1);
                }
                printf("================================\n");
                exit(0);
        }else if(pid>0){
                //父进程回收子进程的资源
                getchar();
                wait(NULL);//阻塞接口,等待一个事件的发生
        }
        return 0;

}

3、创建进程中的指令总结

exit(数字)   用来终止执行
fork         创建进程
wait         接收另一个进程的退出[阻塞接口]
sleep        休眠
execlp       替换当前进程的映像
  • fork 子进程诞生,此时父进程是副本
  • exec系列调用,替换成静态区
  • exit系统调用,结束,变成僵尸
  • wait系统调用,回收资源,已经变成僵尸状态的子进程的资源。

相关文章:

  • WMS系统功能设计和源码实现(Java开发)
  • Redisson - 分布式锁和同步器
  • 嵌入式系统中各类存储方式的区别及接口协议详解
  • 如何应对竞品分析不足导致的方案偏差
  • 禅道后台命令执行漏洞
  • Vue 中provide和inject的作用,在什么场景下使用它们进行跨层级组件通信?
  • 图解AUTOSAR_SWS_FlashEEPROMEmulation
  • 《第三次世界大战》小说预告
  • Spring三级缓存解决循环依赖的深度解析
  • ar头显和眼镜图像特效处理
  • 蓝桥杯模拟题--约数的个数(约数和质因数的区别)
  • 【PCB工艺】时序图(Timing Diagram)
  • visual studio 2017配置QT5.9.4环境
  • DeepSeek绘画工程与第三方通道整合架构解析
  • 【越南体育比分系统开发实战 | 全栈技术解析+7天极速交付方案】
  • python深度评测:5大中文长度计算方案终极对决(你的选择可能一直是错的)
  • Mininet--topo.py-预定义拓扑图解析
  • docker数据卷挂载,安全与优化隔离,docker Compose
  • Visual Studio Code(简称 VS Code)下载与使用教程1(新建文件,语法高亮,快捷键,主题,快捷指令)
  • 猎豹移动营收连续三季增长,AI驱动的猎豹成绩单怎么分析?
  • 网站建设步骤和流程/可以免费推广的平台
  • 深圳市招聘信息网站/码迷seo
  • 莱阳网站建设公司/百度互联网营销
  • 太原网站制作哪家便宜/信阳网络推广公司
  • 做钻石的网站/培训机构招生方案范文
  • php语言的网站建设/游戏优化是什么意思