操作系统:进程(一)

进程的基本概念

一般的解释是:进程是程序的一个执行实例,是正在执行的程序。我们写的程序编译后是一段二进制的文件。启动的时候加载到系统里面执行,就是以进程的形式执行。也就是说,我们编译后的可执行程序是一个静态的概念,加载到系统中以进程的方式执行,是一个动态的概念。
从系统的角度看:进程是系统资源(cpu 时间,内存)分配的最小实体单位。

进程ID(PID)

每一个进程都有唯一的一个非负整数的ID,这个ID就是PID(process iD)

  • Getpid() :返回当前进程的ID
  • Getppid() : 返回当前进程的父进程的ID。
#include <unistd.h>
#include <sys/types.h>
pid_t getpid(void);
pid_t getppid(void);

父进程和子进程

这里涉及到父进程和子进程的概念。为什么会有父进程和子进程?进程的创建并不像结构体或者类一样,new一下就可以创建出来。进程之前存在着继承的关系。进程B继承于进程A,那么进程A就是进程B的父进程。进程B就是进程A的子进程。
因为进程是系统资源的分配实体,所以进程里面会有很多的系统信息,进程相关的分配的内存,寄存器,数据,PCB等很多的域。如果我们自己创建会是一个很繁琐的过程。在早期的操作系统设计的时候,就会考虑如何方便的创建进程。一个比较方便的办法就是把已经存在的进程的各个域完全拷贝一份,然后再修改不同的地方,就形成了一个新的进程,这样的话,创建的进程和被创建的进程之间就存在继承的关系,也就是父子进程。
在linux操作系统启动的时候,系统会先创建一个Init进程,这个是整个系统中的第一个进程,然后再由这个init进程去创建后面的系统进程和用户进程。所以从这个角度看,一个系统中的所有进程都有一个共同的祖先就是init进程。
父进程和子进程之间不只是复制一份的关系。父进程还需要负责子进程的资源的回收。也就是子进程结束后,有很多资源如果没有人回收的话,一个是会造成资源的浪费,另一个是时间久了,会导致整个系统没有可用的资源了。当前也会存在父进程比子进程先结束的情况,这种时候,init进程就会变成子进程的父进程。对资源进行回收,不过这个时间就会比较长。所以在编程的时候,大家还是最好自己创建的进程在使用完后就行回收,避免资源浪费。

进程退出

  • exit(status)
    这个函数没有返回值,会通过参数指定返回状态,这个返回状态会被父进程接收到,父进程就可以做一些处理。
#include<stdlib.h>
void exit(int status);

如何创建和初始化进程

上面在讲父进程和子进程的时候也提到了,如果先创建一个空的数据结构,再填充每个数据域,工作量是非常大的。所以操作系统采用的方式是通过父进程复制的方式创建新的进程。内核init进程是所有进程的祖先,pid=1, 所以的进程最初都是由init进程复制的方式而来的。
下面是创建新进程的时候用到的两个函数:

  • fork()
    通过fork()函数来创建新的进程(子进程),也就是通过这个函数去执行从父进程到子进程的复制工作。
    这个函数比较特殊的地方是,调用一个,有两个返回结果。
    1. 父进程返回创建的子进程的PID
    2. 子进程返回0
  • exec(…)
    通过上面的函数单纯的进行复制,并没有太大的意义,更多的时候我们还是希望新的进程可以执行新的任务,所以需要exec()这个函数.参数传进来一个program,更换当前的code和data,然后执行传进来的program命令。
#include <unistd.h>
#include <sys/types.h>
//Returns: 0 to child, Pid of child to parent, -1 on error
pid_t fork(void);

需要注意的是通过fork()创建的新的子进程,几乎,但不是完全的与父进程相同。父进程和子进程有不同的PID。
子进程得到一份父进程用户层虚拟机地址空间的完全拷贝。同时也得到父进程已打开的文件描述符的完全拷贝,这意味着子进程可以直接读写父进程中已经打开的任何文件。
下面是一个简单的例子:

1 #include "csapp.h"
2 #include <unistd.h>
3 int main()
4 {
5 		pid_t pid;
6 		int x = 1;
7
8 		pid = fork();
9 		if (pid == 0) { /* child */
10 		   printf("child : x=%d\n", ++x);
11 		  exit(0);
12      }
13
14 	/* parent */
15 	printf("parent: x=%d\n", --x);
16 	exit(0);
17 }

第8行调用fork()函数时,进程就产生了分差,变成了一个父进程一个子进程同时在系统中运行,在父进程中,fork()函数返回子进程的pid, 在子进程中,fork()函数返回0,表示当前是子进程自己。由于x的定义是在fork()之前,所以在执行fork()的时候,x被复制了一份,一个属于子进程,一个属于父进程。
在第10行的打印,是子进程打印的,x为2;第15行为父进程打印的为0.也就是说从fork往后,父进程和子进程的数据就是独立的两份了,相互没有了关系。

再举例如下:

1 #include "csapp.h"
2
3 int main()
4 {
5 		Fork();
6 		Fork();
7 		printf("hello!\n");
8 		exit(0);
9 }

经过第5行的fork(),就会产生一对父子进程,两个进程继续向下走,到第6行,再次fork(),两个进程又分别创建一个子进程。如下图,到第七行打印的时候就有4个进程在打印。所以使用fork()创建进程是一种指数的增长。
在这里插入图片描述

进程的并行

在操作系统中进程是并行运行的,即使是父子进程,从创建出子进程的一刻开始,两个进程就开始并行运行了。所以基于上面的程序虽然会打印4次hello.但我们无法判断是哪个进程先打印,哪个进程后打印的。

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

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

相关文章

【数据结构】树与二叉树(二十):树获取大儿子、大兄弟结点的算法(GFC、GNB)

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语 5.2 二叉树5.3 树5.3.1 树的存储结构1. 理论基础2. 典型实例3. Father链接结构4. 儿子链表链接结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子结点的算法&#xff08;GFC&#xff09;…

为什么软件公司很少用Python开发Web项目?

实际上&#xff0c;Python在Web开发方面有着广泛的应用&#xff0c;许多软件公司也确实使用Python来开发Web项目。 Python拥有诸如Django、Flask等流行的Web框架&#xff0c;这些框架使得开发者能够迅速、高效地开发出Web应用。 然而&#xff0c;Python在Web开发中的使用可能会…

利用 Pandoc + ChatGPT 优雅地润色论文,并保持 Word 公式格式:Pandoc将Word和LaTeX文件互相转化

论文润色完美解决方案&#xff1a;Pandoc 与 ChatGPT 的强强联合 写在最前面其他说明 一、通过 Pandoc 将 Word 转换为 LaTeX 的完整指南步骤 1: 安装 PandocWindows:macOS:Linux: 步骤 2: 准备 Word 文档步骤 3: 转换文档步骤 4: 检查并调整输出步骤 5: 编译 LaTeX 文档总结 二…

图新地球地图导入操作步骤

1、下载图源&#xff0c;如下&#xff1a; 2、将其全部复制或部分复制&#xff0c;然后回到桌面&#xff0c;打开文件所在位置&#xff0c;如下&#xff1a; 3、将复制的数据粘贴到文件夹下&#xff0c;具体如下&#xff1a; 4、复制到路径如下&#xff1a; 5、复制结果如下&am…

应用场景丨迭代市政综合管廊监测系统建设

市政综合管廊是指在城市地下建造的隧道空间&#xff0c;将市政、电力、通讯、燃气、给排水等各种管线集于一体&#xff0c;实施统一规划、设计、建设和管理。综合管廊有利于解决反复开挖路面、架空线网密集、管线事故频发等问题&#xff0c;是保障城市运行的重要基础设施和“生…

OpenGL 坐标投影与反投影(Qt)

文章目录 一、简介1.1投影1.2反投影二、应用代码三、实现效果参考资料一、简介 在学习OpenGL一段时间之后,我们都会了解坐标的转换过程,如下图所示: 1.1投影 正如图中所述,OpenGL将一个3D坐标投影到一个2D空间主要有以下几个步骤,这也是我们比较熟知的几个步骤: 现实局部…

ElasticSearch快速入门

一、全文检索 1、什么是全文检索 全文索引是一种通过对文本内容进行全面索引和搜索的技术。它可以快速的在大量文本数据中查找包含特定关键词或短语的文档&#xff0c;并返回相关的搜索结果。 全文检索广泛应用于各种信息管理系统和应用中&#xff0c;如搜索引擎、文档管理系…

三十一、W5100S/W5500+RP2040树莓派Pico<TCP_Server多路socket>

文章目录 1 前言2 简介2. 1 使用多路socket的优点2.2 多路socket数据交互原理2.3 多路socket应用场景 3 WIZnet以太网芯片4 多路socket设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 W5100S/W5500是一…

并发编程(多线程)-可见性、有序性、原子性问题

目录 可见性 可见性概念 可见性演示 小结 原子性 原子性概念 原子性演示 小结 有序性 有序性概念 有序性演示 小结 可见性 可见性概念 可见性&#xff08;Visibility&#xff09;&#xff1a;是指一个线程对共享变量进行修改&#xff0c;另一个先立即得到修改后的…

Python------列表 集合 字典 推导式(本文以 集合为主)

推导式&#xff1a; 推导式comprehensions&#xff08;又称解析式&#xff09;&#xff0c;是Python的一种独有特性。推导式是可以从一个数据序列 构建 另一个 新的数据序列&#xff08;一个有规律的列表或控制一个有规律列表&#xff09;的结构体。 共有三种推导&#xff…

【C++】类与对象(上)

目录 1. 面向过程和面向对象初步认识 2. 类的引入 3. 类的定义 4. 类的访问限定符及封装 4.1 访问限定符 4.2 封装 5. 类的作用域 6. 类的实例化 7. 类对象模型 7.1 如何计算类对象的大小 7.2 类对象的存储方式猜测 7.3 结构体内存对齐规则 8. this指针 8.1 this指…

springboot引入第三方jar包放到项目目录中,添加web.xml

参考博客&#xff1a;https://www.cnblogs.com/mask-xiexie/p/16086612.html https://zhuanlan.zhihu.com/p/587605618 1、在resources目录下新建lib文件夹&#xff0c;将jar包放到lib文件夹中 2、修改pom.xml文件 <dependency><groupId>com.lanren312</grou…