【Linux进程篇】Linux进程管理——进程创建与终止

news2024/11/13 15:11:33

W...Y的主页 😊

代码仓库分享💕


目录

 进程创建

fork函数初识

写时拷贝

fork常规用法

fork调用失败的原因

进程终止

进程退出场景

_exit函数

exit函数

return退出


 

 进程创建

fork函数初识

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

#include <unistd.h>
pid_t fork(void);
返回值:自进程中返回0,父进程返回子进程id,出错返回-1

进程调用fork,当控制转移到内核中的fork代码后,内核做:

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

 当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以开始它们自己的进程,看如下程序:

int main( void )
{
pid_t pid;
printf("Before: pid is %d\n", getpid());
if ( (pid=fork()) == -1 )perror("fork()"),exit(1);
printf("After:pid is %d, fork return %d\n", getpid(), pid);
sleep(1);
return 0;
}
运行结果:
[root@localhost linux]# ./a.out
Before: pid is 43676
After:pid is 43676, fork return 43677
After:pid is 43677, fork return 0

这里看到了三行输出,一行before,两行after。进程43676先打印before消息,然后它有打印after。另一个after消息有43677打印的。注意到进程43677没有打印before,为什么呢?如下图所示

所以,fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意,fork之后,谁先执行完全由调度器决定。 

子进程返回0,
父进程返回的是子进程的pid。

上面的fork函数我在前面的博客中已经提到过了,在这里就算一个复习。

写时拷贝

通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。这不得不提到虚拟地址和物理地址映射关系了。

当父进程中创建一个子进程时,子进程会拷贝父进程的代码与数据,然后由页表进行映射,映射的位置是相同的。当我们修改子进程中的数据时,操作系统会在物理内存中写时拷贝出一个新空间并重新建立页表映射。

为什么要写时拷贝呢?因为我们说过物理内存是有限的,当数据存入物理内存时,操作系统并不知道你是否要对数据进行修改,所以为了提高利用率,父子进程就会指向同一个物理空间。并且可以提高fork函数的效率。

写时拷贝?为什么要拷贝呢?直接开辟一块一样大的空间不就好了!!!因为我们对数据无非就是增删查改,不一定对数据有大的改动,所以当我们对数据进行操作时,我们进行拷贝后就可以知道这个数据,方便我们进行操作。 

如何做到写时拷贝呢?

我们看到上面这张图,这是一个父子进程的页表,里面存着虚拟内存与物理内存的映射。但是我们发现数据与代码的权限都是只读,代码不可修改我们可以理解,为什么数据我们也不能修改呢?

不是不能修改,而是操作系统故意为之。当我们修改数据时,但是数据的权限为只读。这时就会发现缺页中断,操作系统就会出现进行判断发现时数据进行操作,这个操作是正常的,然后操作系统就会触发写时拷贝!!!

fork常规用法

一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

fork调用失败的原因

系统中有太多的进程
实际用户的进程数超过了限制

进程终止

当我们在写程序时,好像固定在程序结尾要写一个return 0,为什么不能是return 1 或其他数字呢?main函数的返回值我们叫做退出码,一般0表示进程执行成功,非零表示失败。非零的数字都代表失败的退出的原因。

可以通过 echo $? 查看最近一次进程的退出码,当我们连续进行echo $? 前面是什么都无所谓后面都会变成0,因为当第二次使用echo $? 最近的进程就是其本身。

用户并不知道退出码的具体含义,所以要把错误码转换成错误描述,或者自定义进行。

怎么转换呢:

 我们可以使用程序查看一下:

1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 int main()
  6 {
  7   for(int i = 0; i < 200; i++)                                                                                                                       
  8   {
  9     printf("%d: %s\n",i,strerror(i));
 10 
 11   }
 12   return 0;
 13 }

 

我们可以看出来系统给出的错误码有133个,我只截取了首尾,其余自行查看。

我们也可以自己进行枚举:

enum {
	    success=0,
	    open_err,
	    malloc_err
	};
	
	const char* errorToDesc(int code)
	{
	    switch(code)
	    {
	        case success:
	            return "success";
	        case open_err:
	            return "file open error";
	        case malloc_err:
	            return "malloc error";
	        default:
	            return "unknown error";
	    }

但是我们函数也是有返回值的,当我们在函数后写一个return 0,返回后主函数也是会执行的。函数退出我们怎么知道函数的执行情况呢?函数程序被我们称为子程序,主程序有退出码作为退出反馈,函数也有退出码。

进程退出场景

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

代码没有执行完,进程出异常是进程收到了异常信号!!!异常信号我们Linux中也有具体实例:

 我们使用kill -l可以查看各种异常信号,每个信号有不同的信号编号,不同的信号编号表明异常原因。

所以任何进程最终执行的情况我们可以使用两个数字表明具体的执行情况:

signumberexit_code情况
00正常退出
!00退出码无意义
0!0代码跑完,结果不正确
!0!0退出码无意义

_exit函数

 这个函数是系统调用接口,因为他存在man(2)中。_exit与exit的调用方式一模一样。

exit函数

这个函数不是程序退出,而是进程终止。status是进程退出时的退出码。在我们代码的任何位置使用exit函数都表示进程退出。 

那exit与_exit有什么区别呢?

 

int main()
{
printf("hello");
exit(0);
}
运行结果:
[root@localhost linux]# ./a.out
hello[root@localhost linux]#
int main()
{
printf("hello");
_exit(0);
}
运行结果:
[root@localhost linux]# ./a.out
[root@localhost linux]#

exit函数会支持刷新缓冲区,反之_exit不会刷新缓冲区。其实就是_exit是操作系统为用户提供的系统调用接口,而exit是C语言将_exit进行封装的,为了更好的跨平台性!!!

return退出

eturn是一种更常见的退出进程方法。执行return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做 exit的参数。


以上就是本次的全部内容,感谢大家观看!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Javascript 基础知识 —— 重写数组方法

1、写一个函数&#xff0c;实现深度克隆对象 const obj {name: "LIYUFAN",age: 25,career: "初级前端工程师",info: {field: ["JS", "CSS", "HTML"],framework: ["React", "Vue", "Angular"…

jmeter多用户并发登录教程

有时候为了模拟更真实的场景&#xff0c;在项目中需要多用户登录操作&#xff0c;大致参考如下 jmx脚本&#xff1a;百度网盘链接 提取码&#xff1a;0000 一&#xff1a; 单用户登录 先使用1个用户登录&#xff08;先把1个请求调试通过&#xff09; 发送一个登录请求&…

DSM驾驶行为分析系统在渣土车管理中的应用

随着科技的不断进步&#xff0c;智能交通系统正逐渐成为现代交通管理的重要工具。其中&#xff0c;DSM驾驶行为分析系统以其独特的功能和优势&#xff0c;在提升驾驶安全性、优化驾驶员管理等方面发挥着重要作用。索迪迈科技将DSM驾驶行为分析系统成功应用于渣土车管理中&#…

深兰科技获评2024年度人工智能出海先锋奖

5月25日&#xff0c;以“亚洲新势力&#xff1a;创新、融合与可持续发展”为主题的亚洲品牌经济峰会2024深圳会议在深圳益田威斯汀酒店举办。本次活动由中国亚洲经济发展协会指导&#xff0c;亚洲国际品牌研究院主办&#xff0c;旨在搭建品牌创新与经济发展交流平台&#xff0c…

服务器感染了. rmallox勒索病毒,如何确保数据文件完整恢复?

导言&#xff1a; 近年来&#xff0c;随着信息技术的飞速发展&#xff0c;网络安全问题日益凸显。其中&#xff0c;勒索病毒作为一种严重的网络威胁&#xff0c;对个人和企业数据造成了巨大的威胁。本文将重点介绍.rmallox勒索病毒的特点、传播途径以及应对策略&#xff0c;旨…

基于 FastAI 文本迁移学习的情感分类(93%+Accuracy)

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

J.搬砖【蓝桥杯】/01背包+贪心

搬砖 01背包贪心 思路&#xff1a;要让重量更小的在更前面&#xff0c;价值更大的在更后面&#xff0c;vi−wj>vj−wi viwi>vjwj 第 i 个箱子放在第 j 个箱子下面就显然更优。所以进行排序再用01背包即可。 #include<iostream> #include<algorithm> #defi…

vs工程添加自定义宏

一、简介 用户可以添加自定义宏变量方便工程路径名称的修改和配置 例&#xff1a;$(SolutionDir) 为解决方案路径&#xff0c;$(PojectDir) 为工程所在路径 测试环境&#xff1a;vs2017&#xff0c;qt5.14.0 二、配置 1、打开属性窗口&#xff1a;视图-》其他窗口-》属性管…

Android笔记--应用安装

这一节了解一下普通应用安装app的方式&#xff0c;主要是唤起系统来安装&#xff0c;直接上代码: 申请权限 <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.WRITE_EXT…

HaloDB 的 Oracle 兼容模式

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 前倾回顾 前面介绍了“光环”数据库的基本情况和安装办法。 哈喽&#xff0c;国产数据库&#xff01;Halo DB! 三步走&#xff0c;Halo DB 安装指引 ★ HaloDB是基于原生PG打造的新一代高性能安…

Python Selenium 详解:实现高效的UI自动化测试

落日余辉&#xff0c;深情不及久伴。大家好&#xff0c;在当今软件开发的世界中&#xff0c;自动化测试已经成为保障软件质量和快速迭代的重要环节。而在自动化测试的领域中&#xff0c;UI自动化测试是不可或缺的一部分&#xff0c;它可以帮助测试团队快速验证用户界面的正确性…

爬虫案例(读书网)

一.我们还是使用简单的bs4库和lxml&#xff0c;使用xpath&#xff1a; 导入下面的库&#xff1a; import requests from bs4 import BeautifulSoup from lxml import etree 我们可以看见它的div和每个书的div框架&#xff0c;这样会观察会快速提高我们的简单爬取能力。 二.实…

Nginx网页服务

nginx的配置: 1、全局块&#xff1a;全局配置&#xff0c;对全局生效&#xff1b; 2、events块&#xff1a;配置影响 Nginx 服务器与用户的网络连接&#xff1b; 3、http块&#xff1a;配置代理&#xff0c;缓存&#xff0c;日志定义等绝大多数功能和第三方模块的配置&#xf…

C语言---文件操作

【C语言详解】——文件操作&#xff08;建议收藏&#xff09;_c语言 写文件原理-CSDN博客 一、文件的读取 # define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<errno.h> #include<string.h>int main() {FILE * pffopen("C:\\Users\\zhw\\De…

Java中的ORM框架——myBatis

一、什么是ORM ORM 的全称是 Object Relational Mapping。Object代表应用程序中的对象&#xff0c;Relational表示的是关系型数据库&#xff0c;Mapping即是映射。结合起来就是在程序中的对象和关系型数据库之间建立映射关系&#xff0c;这样就可以用面向对象的方式&#xff0c…

Vue3使用Composition API实现响应式

title: Vue3使用Composition API实现响应式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端开发 tags: Vue3CompositionRefsReactiveWatchLifecycleDebugging 1. 介绍 Composition API是Vue.js 3中新增的一组API&#xff0c;用于在组件中组…

服装服饰商城小程序的作用是什么

要说服装商家&#xff0c;那数量是非常多&#xff0c;厂家/经销门店/小摊/无货源等&#xff0c;线上线下同行竞争激烈&#xff0c;虽然用户群体广涵盖每个人&#xff0c;但每个商家肯定都希望更多客户被自己转化&#xff0c;渠道运营方案营销环境等不可少。 以年轻人为主的消费…

30【Aseprite 作图】桌子——拆解

1 桌子只要画左上方&#xff0c;竖着5&#xff0c;斜着3个1&#xff0c;斜着两个2&#xff0c;斜着2个3&#xff0c;斜着一个5&#xff0c;斜着一个很长的 然后左右翻转 再上下翻转 在桌子腿部分&#xff0c;竖着三个直线&#xff0c;左右都是斜线&#xff1b;这是横着水平线不…

使用NuScenes数据集生成ROS Bag文件:深度学习与机器人操作的桥梁

在自动驾驶、机器人导航及环境感知的研究中&#xff0c;高质量的数据集是推动算法发展的关键。NuScenes数据集作为一项开源的多模态自动驾驶数据集&#xff0c;提供了丰富的雷达、激光雷达&#xff08;LiDAR&#xff09;、摄像头等多种传感器数据&#xff0c;是进行多传感器融合…

检索字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;字符串对象提供了很多应用于字符串查找的方法&#xff0c;这里主要介绍以下几种方法。 &#xff08;1&#xff09;count()方…