04进程原语-学习笔记

Process 进程原语

进程原语,linux操作系统提供的用于进程开发的一系列函数接口process_api

fork 叉子

共有三代fork

第一代,完全拷贝

第二代,只完成子进程创建和PCB拷贝

第三代,读时共享,写时复制,当前最常用的版本

1693830094547.png

读时共享,当父进程创建子进程后,建立映射,可以让子进程通过映射内存访问父进程资源, 无需拷贝

写时复制, 当子进程写访问映射内存时 ,触发写复制, 父进程将子进程访问的部分数据拷贝给子进程

写复制操作对父子进程都有效, 只要修改映射, 都会触发复制

原理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用方法

pid_t pid = fork(void);

在Liux文件系统中,/目录是所有文件夹或文件的父级

在Linux文件系统中,pid 1/sbin/init进程为根进程,是所有系统进程的父级

在父子进程间存在继承机制,任务或数据可以继承给子进程

僵尸进程

在linux下是内存泄漏现象,开发时系统中申请的内存资源,使用完毕及时释放,否则进程持续占用内存,影响其他进程使用或影响内存重用性

原因

子进程退出后,调用exit(0),进而系统调用EXIT(0),释放用户空间、释放内核空间,但是内核空间释放不完全,残留了PCB。子进程成为僵尸进程,造成内存泄露。

系统的所有进程结束后都会变成僵尸进程,是一种常态,一个必经环节。

危害

僵尸进程的危害

  1. 内存泄露

  2. 占用PCB,影响创建新的进程

操作系统这样设计的原因

当产生僵尸进程后,父进程要对僵尸进程进行回收。父进程可以通过这个PCB,对PCB中子进程退出的原因进行采集(验尸)。

wait

头文件sys/wait.h

pid_t zpid=wait(NULL);

调用一次,回收一个僵尸进程,如果有多个进程需要循环调用。

wait是阻塞函数,会等待子进程结束后进行回收

可以传入一个int* status去承接PCB中的信息,来实现验尸的目的,也可以传NULL放弃验尸。
后续通过status进行验证处理,获取子进程的退出原因
执行wait函数时,参数为null,表示只释放PCB内存,但是不采集子进程退出原因,不进行验尸操作

return zpid

返回僵尸进程的pid
zpid>0 僵尸进程回收成功
zpid==-1 回收失败,原因:没有子进程却执行回收操作

子进程经历的三个阶段

运行态

僵尸态

回收后,子进程消失

注意:多进程模式中,子进程一定会变成僵尸进程,所以父进程必须进行回收操作

waitpid

定义

wait的升级版

pid_t zpid = waitpid(pid_t pid, int* status, WNOHANG);

waitpid更多的回收方式,还支持非阻塞回收。

特点

  1. 更多的回收方式
    pid参数不同有着不同的含义
    • pid>0 指定子进程id,回收特点的子进程
    • -1 回收任意子进程,最常使用
    • 0 同组回收,表示回收与当前进程同组的所有子进程
    • pid<-1 如-3000 表示回收进程组id为3000的其中的子进程,跨组回收
  2. 非阻塞回收
    可以让父进程在回收的过程中交替执行的自己的任务,无需一直等待子进程

返回值

  1. 返回值>0,回收成功
  2. 返回值=0,非阻塞返回(子进程未结束,不需要回收)
  3. 返回值=-1,回收失败

status校验

两种情况

  1. 正常退出
    return 0 or exit,代码按运行逻辑,执行到退出执行导致进程退出,属于正常退出范畴
  2. 异常退出
    进程未执行完毕,被其他进程杀死,进程执行异常,被系统杀死

参数

  1.  WIFEXITED(status);
    

    此函数可以判断子进程是否是正常退出,如果正常退出,此函数返回1

    int code=WEXITSTATUS(status);
    

    此函数可以从status提取进程的返回值或退出值,并返回

  2.  WIFSIGNALED(status);
    

    此函数可以检测子进程是否被信号杀死(异常退出),如果是返回1

    int signo=WTERMSIG(status);
    

    此函数获取杀死子进程的信号编号并返回

excel函数,进程重载

1693830268034.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我是一个自然语言处理模型,无法提供代码编写功能。但是,你可以参考以下伪代码实现: ``` // 定义进程控制块 PCB class PCB { int pid; // 进程ID int status; // 进程状态 int memorySize; // 内存大小需求 int runTime; // 估计运行时长 // 其他属性和方法 } // 创建进程原语 void createProc(int memorySize, int runTime) { PCB pcb = new PCB(); pcb.pid = generatePid(); // 生成唯一的进程ID pcb.status = STATUS_READY; pcb.memorySize = memorySize; pcb.runTime = runTime; allocateMemory(pcb); // 分配内存空间 addPCBToList(pcb); // 将PCB加入进程列表 } // 终止进程命令 void killProc(int pid) { PCB pcb = findPCB(pid); if (pcb != null) { releaseMemory(pcb); // 释放内存空间 removePCBFromList(pcb); // 从进程列表中移除PCB } } // 阻塞进程命令 void ioStartProc(int pid) { PCB pcb = findPCB(pid); if (pcb != null) { pcb.status = STATUS_BLOCKED; } } // 唤醒进程命令 void ioFinishProc(int pid) { PCB pcb = findPCB(pid); if (pcb != null) { pcb.status = STATUS_READY; } } // 显示所有进程状态命令 void psProc() { for (PCB pcb : processList) { System.out.println("PID: " + pcb.pid + ", Status: " + getStatusName(pcb.status) + ", Memory Address: " + pcb.memoryAddress); } } // 显示内存空间使用情况信息 void mem() { for (MemoryBlock block : memoryList) { System.out.println("Memory Address: " + block.startAddress + " - " + block.endAddress + ", Size: " + block.size + ", Status: " + getStatusName(block.status)); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值