[Linux] 进程控制之创建和终止

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

          主厨:邪王真眼

主厨的主页:Chef‘s blog  

所属专栏:青果大战linux

总有光环在陨落,总有新星在闪烁


每日吐槽

不得不说,算法和linux交换着学习,真的很舒服,就是算法容易上头,得多加控制才行,还有一件事,少熬夜吧、、、、、又掉头发了,真的很emo' 

进程创建

fork

功能:linuxfork函数是非常重要的函数,包含在头文件<unistd.h>,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

返回值:类型是pid_t,包含在头文件<sys/typeds.h>,向父进程返回子进程的PID,向子进程返回0,若fork失败则向父进程返回-1

代码展示

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(){
pid_t p=fork();
if(p>0)
{
    printf("我是父进程,我的PID时:%d  我的PPID时%d\n",getpid(),getppid());
}
else if(p==0)

    printf("我是子进程,我的PID时:%d  我的PPID时%d\n",getpid(),getppid());
    else{
        printf("创建失败\n");
    }
}

fork都干了什么

  1. 分配新的内存块和内核数据结构给子进程
  2. 将父进程部分数据结构内容拷贝至子进程
  3. 添加子进程到系统进程列表当中
  4. fork返回,开始调度器调度


 子进程的拷贝工作

1.在子进程刚创建时,他的代码和数据都是和父进程共享的,我们上节课谈到了页表与虚拟地址,这里的共享指的就是子进程直接拷贝父进程的页表,因此二者的数据的虚拟地址一样,且物理地址一样。

2.我们知道代码是放在只读区无法被修改的,因此父子共享是没问题的,所以拷贝页表后就不用继续处理这部分内容了。

3.数据是有可能被修改的,而父进程修改数据后,有可能影响子进程的工作,(例如子进程需要通过该数据进行if判断,加减运算)同理,子进程修改也会影响父进程,为了保证进程之间的独立性,写时拷贝出现了。

4.写时拷贝:

fork()之后,OS会把父进程中页表权限都设为read-only,然后子进程将该页表进行拷贝。当父进程中要进行写入操作时,CPU中的MMU单元检测到该地址的页表属性是read-only的,于是生成一个访问权限异常,并向OS反馈,OS经过检测后就会重新开辟一片空间A,将该数据拷贝过去,并将父进程的页表中指向该数据的物理地址改为空间A的地址,设置权限为可写,并将原表中该数据的权限设置为可写。

5.缺页中断

访问了非法的地址(野指针)

访问的地址是合法的,但是该地址还未分配物理页框。

写时拷贝这样做对比直接在创建子进程时就拷贝所有数据大大提升了内存利用率,减少了不必要的空间浪费。

子进程的运行

子进程虽然代码和父进程共享,但它是从fork之后的语句(而不是main函数)开始运行的,一个正在CPU运行的进程,CPU的寄存器会记录要运行的下一条语句的地址(PC寄存器),只需要在创建子进程时把该信息存入子进程的PCB中,当子进程开始运行时就会从fork后开始运行而不是main函数了。具体可看进程切换上下文数据

fork的使用

我们通常用fork的返回值进行if else,来让父子进程跑不同的代码,如下

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(){
pid_t p=fork();
if(p>0)
    printf("记得关注啊!!\n");
else if(p==0)
    printf("记得点赞收藏啊\n");
    else{
        printf("创建失败\n");
    }
}

 最后,想必大家都很关心一件事,父进程和子进程到底谁先运行

答:不知道

这件事取决于操作系统,它觉得这次应该父进程先跑,那就父进程先跑了,它觉得下次子进程先跑那就子进程先跑了。


 fork创建失败

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制
直接写个死循环去fork
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(){
    while(1){
pid_t p=fork();
    if(p<0)
        printf("fork失败\n");
    }
}


进程终止

有始有终,当一个进程被创建,那他在未来某一刻一定会终止,此时又该怎么做呢?任其暴毙于内存,还是说,,,操作一番

进程结束的三种情况

  1. 代码运行完毕,结果正确
  2. 代码运行完毕,结果不正确
  3. 代码异常终止

不难理解,父进程既然要创建子进程,一定是让它去完成一些任务的,那么现在这个进程结束了,这个任务到底有没有完成呢?如果没有完成又是因为什么原因失败的呢?这些问题我们是需要为父进程解答的,好让他根据具体情况采取对策。

如何向父进程反馈?靠的就是退出码这个东西 

运行成功的话,父进程只要知道成功就好了,但如果失败了,父进程还需要知道他到底错哪了

因此我们规定了退出码为0,表示运行成功

退出码非零,表示运行错误,不同的值表示不同的错误原因

echo $?//查看上一次进程的退出码

代码展示

#include<stdio.h>
int main(){
    return 18;
}

错误码

不同的非0退出码可以表示不同的错误信息,那么退出码和错误信息的一一对应关系是什么呢?

其实OS已经给我们设定好了一套标准,这里我们称那些非0退出码为错误码,他们对应的信息为错误信息。c语言给我们提供了很多接口去调用它们。

  • errno

表示当前进程的错误码,假如没有错误发生就是0,每次出现错误就会更新,包含在<errno.h>头文件中。

  • strerror

参数是错误码,返回值是该错误码对应的错误信息(字符串)可以把输出对应的的错误信息,输入错误码

  • perror

输出当前错误码的错误信息,可以自定义输出,传入字符串s,输出s+错误信息


当程序在运行时发生了运行时错误(野指针,除零等等)就会自动记录错误码,每个错误码都有对应的错误信息,我们可以演示一下

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main(){
        printf("Before:错误码%d  错误信息%s\n",errno,strerror(errno));
    FILE* f=fopen("./test","r");
    if(f==NULL)
        printf("After:错误码%d  错误信息%s\n",errno,strerror(errno));
   return errno;
}

 

我们可以打印出所有错误吗及其错误信息来查看(我的版本下一共134条)

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main(){
   for(int i=0;i<140;i++)
       {
       printf("[%d]  :%s\n",i,strerror(i));

   }
}

当然,你也可以不用这些错误码,而是自己规定一套去使用,事实上在你的代码和系统并非强相关时,我们通常会选择自己设定错误码,比如你写一个二分算法,就可以规定错误码1表示死循环,2表示超时等等,


exit

#include<stdio.h>
#include<stdlib.h>
void func(){
    exit(100);
}
int main(){
    func();
    return 10;
}

可以发现,exit会直接退出该进程,而return只能退出该函数 。exit的参数即是该进程最后的退出码。

exit和_exit都是直接退出进程,但是exit在退出时会把缓冲区里的数据刷出来,而_exit不会,如下所示

_exit是系统提供的接口,exit是语言里的接口。exit是对_exit的封装

这里我们多说一句,事实上缓冲区不是OS创建的,而是编程语言创建的.


感觉有用的话,就点个关注吧,博主正在持续更新linux,对于想学linux的宝,可以提供很多帮助哦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/909371.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

介绍一下rand函数生成随机数(c基础)

适合对象 c语言初学者 总结语言用色&#xff0c;个人强调用红色&#xff0c;注意为易错点&#xff0c;若有问题请告诉我谢谢。(建议通过目录观看)。一定要自己动手打代码。 rand函数 是生成随机数的函数&#xff0c;但实则是伪随机数。(即是同一个值) 格式 #include<st…

vue3入门知识(一)

vue3简介 性能的提升 打包大小减少41%初次渲染快55%&#xff0c;更新渲染快133%内存减少54% 源码的升级 使用Proxy代替defineProperty实现响应式重写虚拟DOM的实现和Tree-Shaking 新的特性 1. Composition API&#xff08;组合API&#xff09; setupref与reactivecomput…

FET113i-S核心板已支持RISC-V,打造国产化降本的更优解 -飞凌嵌入式

FET113i-S核心板是飞凌嵌入式基于全志T113-i处理器设计的国产工业级核心板&#xff0c;凭借卓越的稳定性和超高性价比&#xff0c;FET113i-S核心板得到了客户朋友们的广泛关注。作为一款拥有A7核RISC-V核DSP核的多核异构架构芯片&#xff0c;全志科技于近期释放了T113-i的RISC-…

C语言进阶:二.数据的存储(2)

❤个人主页❤&#xff1a;折枝寄北-CSDN博客 ❤学习专栏❤&#xff1a; C语言专栏&#xff1a;https://blog.csdn.net/2303_80170533/category_12794764.html?spm1001.2014.3001.5482https://blog.csdn.net/2303_80170533/category_12794764.html?spm1001.2014.3001.5482 在…

城市智慧公厕解决方案,建设城市智能化公厕

在城市的飞速发展进程中&#xff0c;公厕作为城市基础设施的重要一环&#xff0c;其智能化建设已成为提升城市品质与居民生活舒适度的关键举措。以下是关于城市智慧公厕的几点解决方案。 一、智能设施配备 首先&#xff0c;要引入智能化的卫生设备。例如&#xff0c;安装自动感…

【STL栈和队列】:高效数据结构的应用秘籍

前言&#xff1a; C 标准模板库&#xff08;STL&#xff09;为我们提供了多种容器&#xff0c;其中 stack&#xff08;栈&#xff09;和 queue&#xff08;队列&#xff09;是非常常用的两种容器。 根据之前C语言实现的栈和队列&#xff0c;&#xff08;如有遗忘&#xff0c;…

vue data变量之间相互赋值或进行数据联动

摘要&#xff1a; 使用vue时开发会用到data中是数据是相互驱动&#xff0c;经常会想到watch,computed&#xff0c;总结一下&#xff01; 直接赋值&#xff1a; 在 data 函数中定义的变量可以直接在方法中进行赋值。 export default {data() {return {a: 1,b: 2};},methods: {u…

HTML 基础标签——分组标签 <div>、<span> 和基础语义容器

文章目录 1. `<div>` 标签特点用途示例2. `<span>` 标签特点用途示例3. `<fieldset>` 标签特点用途示例4. `<section>` 标签特点用途示例5. `<article>` 标签特点用途示例总结HTML中的分组(容器)标签用于结构化内容,将页面元素组织成逻辑区域…

Java开发配置文件的详情教程配置文件类型

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

全面解析:网络协议及其应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 全面解析&#xff1a;网络协议及其应用 全面解析&#xff1a;网络协议及其应用 全面解析&#xff1a;网络协议及其应用 网络协议…

软件压力测试有多重要?北京软件测试公司有哪些?

软件压力测试是一种基本的质量保证行为&#xff0c;它是每个重要软件测试工作的一部分。压力测试是给软件不断加压&#xff0c;强制其在极限的情况下运行&#xff0c;观察它可以运行到何种程度&#xff0c;从而发现性能缺陷。 在数字化时代&#xff0c;用户对软件性能的要求越…

聊一聊Qt中的Slider和ProgressBar

目录 QAbstractSilder 主要属性 设置值 信号 其他功能 API QSlider 主要功能 控制刻度 信号 用户交互 键盘操作 API QProgressBar API QScrollBar 详细描述 QDial API 一个示例 Slider和ProgressBar从某种程度上都是反应了自己对目标控件的进度状态。在Qt中…

源鲁杯 2024 web(部分)

[Round 1] Disal F12查看: f1ag_is_here.php 又F12可以发现图片提到了robots 访问robots.txt 得到flag.php<?php show_source(__FILE__); include("flag_is_so_beautiful.php"); $a$_POST[a]; $keypreg_match(/[a-zA-Z]{6}/,$a); $b$_REQUEST[b];if($a>99999…

qt QFileDialog详解

1、概述 QFileDialog是Qt框架中的一个对话框类&#xff0c;用于提供一个标准的文件选择对话框。它允许用户浏览文件系统&#xff0c;选择一个或多个文件或目录&#xff0c;以及指定文件名。QFileDialog支持本地文件系统和远程文件系统&#xff08;如通过FTP或SFTP访问的文件系…

【客户服务】客户不是上帝---投诉管理新智慧

第一讲 怎样正确看待客户投诉 什么是客户投诉 当客户对于产品或服务产生不满&#xff0c;当客户的需求得不到满足时&#xff0c;就会产生客户投诉。 投诉的根源有两方面 产品质量服务质量 投诉对企业是好事还是坏事 坏事&#xff1a;不良口碑的传递和客户的升级投诉会影响…

责任链模式 Chain of Responsibility

1 意图 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。 2 结构 Handler 定义一个处理请求的接口;(可选)实现后继链。 ConcreteHandler …

JMM内存模型,JMM三大特性(面试回答)

1.什么是JMM JMM就是Java内存模型(java memory model)。因为在不同的硬件生产商和不同的操作系统下&#xff0c;内存的访问有一定的差异&#xff0c;所以会造成相同的代码运行在不同的系统上会出现各种问题。所以Java内存模型(JMM)屏蔽掉各种硬件和操作系统的内存访问差异&…

Mybatis查询数据库,返回List集合,集合元素也是List。

#有时间需求会要求&#xff1a;查询全校的学生数据&#xff0c;且学生数据按班级划分。那么就需要List<List<user>>类型的数据。 SQL语句 SELECT JSON_ARRAYAGG(JSON_OBJECT(name , name ,BJMC, BJMC ,BJBH,BJBH)) as dev_user FROM dev_user WHERE project_id …

CKA认证 | 使用kubeadm部署K8s集群(v1.26)

一、前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式&#xff1a; ① kubeadm Kubeadm是一个K8s部署工具&#xff0c;提供kubeadm init和kubeadm join&#xff0c;用于快速部署Kubernetes集群。 ② 二进制包 从github下…

ffmpeg命令——从wireshark包中的rtp包中分离h264

ffmpeg命令——从wireshark包中的rtp包中分离h264 过滤 RTP打开wireshark的RTP 播放器选中流并导出荷载使用 ffmpeg 命令行分离出 h264 过滤 RTP 打开wireshark的RTP 播放器 选中流并导出荷载 使用 ffmpeg 命令行分离出 h264 ffmpeg -i test.raw -vcodec copy -an -f h264 tes…