【Linux】六、进程控制

进程创建

fork函数的认识

#include <unistd.h>

pid_t fork(void)

#include <stdio.h>
#include <unistd.h>int main()
{printf("我是父进程!\n");pid_t id = fork();if(id < 0){printf("创建子进程失败\n");return 1;}else if{//子进程while(1){printf("我是子进程:pid: %d, ppid: %d\n",getpid(),getppid());sleep(1);}}else{//父进程while(1){printf("我是子进程:pid: %d, ppid: %d\n",getpid(),getppid());sleep(1);}}return 0;
}

请描述一下,fork创建子进程,操作系统都做了什么?

fork创建子进程就是系统里多了一个进程,也就是进程=内核数据结构+进程代码和数据;一般从磁盘中来,也就是C\C++程序加载后的结果;分配新的内存块和内核数据结构给子进程;将父进程部分数据结构内容拷贝到到子进程;添加子进程到系统进程列表当中,fork返回开始调度器调度;

创建子进程给子进程分配对应的内核结构,理论上子进程也要有自己的代码和数据,但是一般子进程没有加载的过程,也就是说子进程没有自己的代码和数据,所以子进程只能使用父进程的代码和数据;

代码:都是不可以被写的,只能读取,所以父子进程共享没有问题;

数据:可能被修改,所以必须分离;

当想要修改数据时,有两种方案

1、创建进程时,就直接拷贝分离,也就是将父进程给子进程拷贝一份,但这样做有一个问题,可能拷贝子进程根本不会用到的数据空间,即使用到了也就是读取;

#include <stdio.h>
#include <unistd.h>int main()
{char *str = "aaa";char *str1 = "aaa";printf("%p\n", str);printf("%p\n", str1);return 0;
}

此时打印出来的结果地址是相同的,编译器编译程序的时候都知道使用这种方式节省空间,所以操作系统在创建子进程的时候,不需要将不会被访问的或者只会读取的数据,拷贝出一份;那么什么样的数据值的被拷贝呢?将来会被父或子进程写入的数据;一般来说,即便是操作系统也无法提前知道哪些空间可能会被写入,并且即便是提前拷贝了可能也不会立刻使用,所以操作系统选择了写时拷贝技术将父子进程的数据进行分离;

2、写时拷贝;

fork之后是所有的代码共享,不是fork之后的代码共享;

原因:首先,当代吗进行汇编后,会有很多行代码,而且每行代码加载到内存后都有对应的地址;其次,因为进程随时可能被中断(可能没有执行完),下次回来,还必须从之前的位置继续运行,就要求CPU必须随时记录下当前进程执行的位置,所以,CPU内有对应的寄存器数据,用来记录当前进程执行的位置,寄存器叫做EIP,也叫做pc(point code)指针,程序计数器;寄存器在CPU内只有一份,但是寄存器的数据,可以有很多份,而这个数据也就是上下文数据,而这个上下文数据,通过写时拷贝给子进程,父子进程各自调度,各自会修改自己的EIP,但是此时子进程已经认为自己的EIP起始值就是fork之后的代码;

因为有写时拷贝,所以父子进程得以彻底分离,完成了进程独立性的技术保证,是一种延时申请技术,可以提高整机内存的使用率;

 

fork 的常规用法

一个父进程希望子进程复制自己,是父子进程执行同一份代码的不同区域;

父进程和子进程执行完全不同的代码;

一般而言父子进程实际使用时,像现实一样希望子承父业,或者父子从事不同的行业;

 

fork失败的原因

系统中有太多的进程;(内存不足)

实际用户的进程数超过了限制;(一般普通用户的进程数是有限制的)几百几千进程;

进程终止 

进程终止时操作系统做了什么?

释放进程申请的相关数据结构和对应的代码和数据;本质就是释放系统资源;内存或CPU等;

进程终止的常见方式?

代码跑完,结果正确;

代码跑完,结果不正确;(代码中的逻辑有问题)

代码没跑完,程序崩溃了;(信号部分)

 

main函数的返回值?main返回值的意义是什么?return 0的含义是什么?为什么总是 0 ?

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

 return后面的返回值并不是总是0的;

main的返回值是进程的退出码;

return 0 表示的是进程的运行结果正确,当运行结果不正确的时候返回值是非0;

使用 echo $? 可以获取最近一次进程返回的退出码;

返回值的意义是返回给上一级进程,用来评判进程执行结果用的;例;

 

#include <stdio.h>
#include <unistd.h>int sum(int top)
{int s=0;for(int i=1;i<=top;i++){s+=i;}return s;
}int main()
{int ret=0;int res=sum(100);if(res!=5050){ret=1;//代码运行结果不正确;}return ret;
}

可以通过对返回值做判断来判断自己的程序运行结果正确还是不正确;

如果程序结果正确了就不会关心为什么正确了,但是如果结果不正确,就会关心结果为什么不正确,非0值有无数个,不同的非0值可以表述不同的错误原因;从而给程序在运行结束后在结果不正确时,方便定位错误的原因细节;

退出码除了返回给上一级进程,还有一个就是可以通过退出码快速定位错误原因;

又因为自己定义的退出码系统并不能识别,所以需要用到一个接口,将退出码转化成字符串描述的错误原因; #include <string.h> strerror();

 

#include <stdio.h>
#include <unistd.h>
#include <string.h>int sum(int top)
{int s=0;for(int i=1;i<=top;i++){s+=i;}return s;
}int main()
{for(int number=0;number<100;number++){printf("%d: %s\n",number,strerror(number));}
}

最终打印出134个退出码和字符串;

我们自己可以使用这些退出码和含义,但是如果想要自己定义也可以自己设计一套退出方案;

用代码如何终止进程?

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea使用debug无法启动,使用run可以启动

1、将调试断点清除 使用快捷键ctrl shift F8&#xff0c;将勾选的选项去除即可 2、Error running SampleApplication: Command line is too long. Shorten command line for SampleApplication or also for Spring Boot default configuration&#xff0c;报这种错误&#x…

Python爬虫:制作一个属于自己的IP代理模块

前言 在Python爬虫过程中&#xff0c;为了避免被网站的反爬虫机制干扰&#xff0c;我们需要使用IP代理。所谓IP代理&#xff0c;就是通过修改网络请求中的IP地址&#xff0c;来达到隐藏真实IP地址的效果。本文将教你如何制作一个自己的IP代理模块&#xff0c;让你的爬虫更加稳…

Hadoop3教程(九):MapReduce框架原理概述

文章目录 简介参考文献 简介 这属于整个MR中最核心的一块&#xff0c;后续小节会展开描述。 整个MR处理流程&#xff0c;是分为Map阶段和Reduce阶段。 一般&#xff0c;我们称Map阶段的进程是MapTask&#xff0c;称Reduce阶段是ReduceTask。 其完整的工作流程如图&#xff…

uniapp-vue3-微信小程序-标签选择器wo-tag

采用uniapp-vue3实现, 是一款支持高度自定义的标签选择器组件&#xff0c;支持H5、微信小程序&#xff08;其他小程序未测试过&#xff0c;可自行尝试&#xff09; 可到插件市场下载尝试&#xff1a; https://ext.dcloud.net.cn/plugin?id14960 使用示例 <template>&…

windows常用命令

一.文件操作 dir&#xff1a;查看文件当前路径目录列表 cd .. &#xff1a;返回上一级目录 cd 路径&#xff1a;进入路径

问题记录1 json解析问题

问题&#xff1a; json解析int类型不符合预期&#xff0c;使用json.NewDecoder解决。 示例如下&#xff1a; package mainimport ("bytes""encoding/json""fmt" )func main() {data1 : map[string]interface{}{}data1["id"] int64(4…

STM32 ---- 再次学习STM32F103C8T6/STM32F409IGT6

目录 一、环境搭建及介绍 关于STM32基础介绍 新建工程 外设案例 LED流水灯 蜂鸣器 上拉电阻和下拉电阻知识 电压比较器 c语言基础知识 类型、结构体、枚举 类型int8_t int16_t int32_t 宏替换 #define 和typedef用法 结构体两种填充方法 和 命名规则 枚举用法 常用…

【Java 进阶篇】JavaScript DOM Document对象详解

在前端开发中&#xff0c;DOM&#xff08;文档对象模型&#xff09;扮演着重要的角色。它允许我们使用JavaScript来与网页文档进行交互&#xff0c;实现动态的网页效果。DOM的核心部分之一就是Document对象&#xff0c;它代表了整个HTML文档。在本篇博客中&#xff0c;我们将深…

Java系列 | 如何讲自己的JAR包上传至阿里云maven私有仓库【云效制品仓库】

什么是云效 云效是云原生时代一站式 BizDevOps 平台&#xff0c;产研数字化同行者&#xff0c;支持公共云、专有云和混合云多种部署形态&#xff0c;通过云原生新技术和研发新模式&#xff0c;助力创新创业和数字化转型企业快速实现产研数字化&#xff0c;打造“双敏”组织&…

这应该是关于回归模型最全的总结了(附原理+代码)

本文将继续修炼回归模型算法&#xff0c;并总结了一些常用的除线性回归模型之外的模型&#xff0c;其中包括一些单模型及集成学习器。 保序回归、多项式回归、多输出回归、多输出K近邻回归、决策树回归、多输出决策树回归、AdaBoost回归、梯度提升决策树回归、人工神经网络、随…

MySQL事务MVCC详解

一、概述 MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制机制。主要是通过数据多版本来实现读-写分离&#xff0c;做到即使有读写冲突时&#xff0c;也能做到不加锁&#xff0c;非阻塞并发读&#xff0c;从而提高数据库并发性能。 MVCC只在已提交读&#xff08…

如何设计 API?看这一篇就够了

在前后端分离的设计中&#xff0c;不管使用什么语言&#xff0c;后端都需要提供 WebAPI 给前端使用。如果是一个平台级的产品&#xff0c;还有可能需要将平台的公共 API 提供给第三方系统使用&#xff0c;这些都要考虑到 API 的设计。 本文聊下 API 设计可能遇到的问题以及处理…