当前位置: 首页 > news >正文

进程章节总结性实验

进程实验课笔记
本节需要有linux基础,懂基本的linux命令操作即可。

Ubuntu镜像下载
https://note.youdao.com/s/VxvU3eVC
ubuntu安装
https://www.bilibili.com/video/BV1j44y1S7c2/?spm_id_from=333.999.0.0
实验环境ubuntu22版本,那个linux环境都可以,mit这套课程的实验环境是xv6,这种类unix远古的环境都可以,那么正常环境都是没问题的,当然windows环境应该也是可以的,这里主要是Linux环境。
gcc基础
这里用一个helloworld演示

注意linux所有文件的后缀都是无意义的,我们这里标识.c只是单纯标识
当然先写代码

一步到位:gcc hello.c
这条命令隐含执行了
(1)预处理
(2)编译
(3)汇编
(4)链接
在这里插入图片描述
这里未指定输出文件,默认输出为a.out
gcc编译C源码有四个步骤:
预处理 ----> 编译 ----> 汇编 ----> 链接
现在我们就用gcc的命令选项来逐个剖析gcc过程。
在该阶段,编译器将C源代码中的包含的头文件如stdio.h添加进来
参数:”-E”
gcc –E hello.c –o hello.i
第一步预处理的过程,我们可以看下系统给我们做了什么
在这里插入图片描述
只加了注释,这里看不到汇编代码,那就算了
继续下一步
编译
gcc –S hello.i –o hello.s
这里报错了
在这里插入图片描述看起来不需要头文件
注释掉
在这里插入图片描述重新预处理和编译,注意这里要重新来
在这里插入图片描述

可以了
我们看下文件
转化成汇编了,不出所料
在这里插入图片描述在这里插入图片描述
不多深究了继续
链接 其实就是解析汇编代码了
gcc –c hello.s –o hello.o
在这里插入图片描述
链接其实就是做成exe文件
gcc hello.o -o hello

在这里插入图片描述
这步可以理解成加壳

注意要执行给权限,随便怎么给,我给777

在这里插入图片描述
lab1:获取进程号

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{ // getpid()函数返回当前进程的ID号
printf("Before fork Process id:%d\n", getpid());
printf("After fork Process id:%d\n", getpid());
pause();
return 0;
}

在这里插入图片描述我们运行一下
在这里插入图片描述

我们打开另外一个terminal
在这里插入图片描述

实验二:子进程与父进程的pid

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
//pid_t是数据类型,实际上是一个整型
//通过typedef重新定义了一个名字,用于存储进行ID
pid_t pid;
//parent pid
pid_t cid;
//child pid
// getpid()函数返回当前进程的ID号
printf("Before fork Process id:%d\n", getpid());fork();
printf("After fork Process id:%d\n", getpid());
pause();
return 0;
}

在这里插入图片描述为什么执行了三遍呢?
这里我们可以看出父进程执行了两次,而子进程执行了一次
我们再看下进程状况

在这里插入图片描述
至于为什么父进程执行了两边呢?

这就和我们系统创建子进程的过程相关了,创建子进程的第一步就是将父进程的内存数据全部clone一份,然后放入一份新的属于子进程的内存区域中。这样也就代表他们的内存中的text区域数据是一样的,这样他们就会执行相同的代码。当然这里是并发执行,那么父子进程都要执行一遍fork函数之后的代码,注意这里字进程是在fork函数执行时被唤醒的,所以子进程虽然有父进程的代码,但是子进程也只会并发执行fork函数后面的代码(也就是从fork函数开始执行)。

这里我们需要注意,这里并发执行虽然是父进程唤醒子进程,但是由于并发的机制让我们用户基本感受不到谁先执行,所以理论上来说我们可以让父进程执行的时间更长一些(比如调用write输出i/o设备产生的结果时间更长),这样就可以做到父进程还没有输出,但是子进程却已经输出结果了,让我们产生子进程优先执行的错觉。

实验三:fork函数返回值
先看下fork函数的返回值

#include <unistd.h>
int main(int argc, char const *argv[])
{
//pid_t是数据类型,实际上是一个整型
//通过typedef重新定义了一个名字,用于存储进行ID
pid_t pid;
//parent pid
//为了防止误判先给cid一个值
pid_t cid=8;
//child pid
// getpid()函数返回当前进程的ID号
printf("Before fork Process id:%d\n", getpid());cid = fork();
printf("cid=%d\n", cid);
pause();
return 0;
}

那么这个0是什么呢?

如果成功创建子进程,对于父子进程fork会返回不同的值,对于父进程它的返回值是子进程的pid号,而对于子进程他返回值是0,这里猜测这个0大概率是内核模式。如果创建失败,cid返回值为-1

实验四:并发与父子内存数据复制
并发

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
pid_t cid;
//child pid
printf("Before fork Process id:%d\n", getpid());
cid = fork();
if (cid == 0){
// 该分支是子进程执行的代码printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());for(int i = 0; i < 3; i++){printf("hello\n");}
}else{
// 该分支是父进程执行的代码printf("Parent Process id: %d\n",getpid());for(int i = 0; i < 3; i++){printf("world\n");}
wait(NULL);
}
return 0;
}

这里可以看出结果是父进程还是比子进程先执行,但是这个并看不出并发
在这里插入图片描述

我们将for循环增加次数直接增加到3000次

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
pid_t cid;
//child pid
printf("Before fork Process id:%d\n", getpid());
cid = fork();
if (cid == 0){
// 该分支是子进程执行的代码,for循环增加次数printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());for(int i = 0; i < 3000; i++){printf("hello\n");}
}else{
// 该分支是父进程执行的代码,for循环增加次数printf("Parent Process id: %d\n",getpid());for(int i = 0; i < 3000; i++){printf("world\n");}
wait(NULL);
}
return 0;
}

这一段输出我们可以看出父进程与子进程是你执行一下我执行一下,前面那个是因为进程执行输出数据太少看不出并发执行。
在这里插入图片描述

父子内存数据复制
我们前面说子进程是将父进程的内存空间数据copy了一份,那么我们现在设置一个值看下子进程读取是否会有问题

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{pid_t cid;
//child pid
printf("Before fork Process id:%d\n", getpid());
int value = 100;
cid = fork();
if (cid == 0){
printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid())
for(int i = 0; i < 3; i++){
printf("hello(%d)\n",value--);
}
}else{
printf("Parent Process id: %d\n",getpid());
for(int i = 0; i < 3; i++){
printf("world(%d)\n",value++);
}
wait(NULL);
}
return 0;
}

这里我们可以看出子进程和父进程的value值确实是一样的,
在这里插入图片描述

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
pid_t cid;
//child pid
printf("Before fork Process id:%d\n", getpid());
cid = fork();
if (cid == 0){
printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());
for(int i = 0; i < 3; i++){
printf("hello\n");
}
}else{
printf("Parent Process id: %d\n",getpid());
for(int i = 0; i < 1; i++){
printf("world\n");
}
//wait(NULL);
}
return 0;
}

在这里插入图片描述
我们ps -ef看下
在这里插入图片描述

我们可以看出这子进程的父进程是systemd这个进程

其实出现这个现象的原因是因为我们没有在父进程中加wait函数,那么父进程由于执行的太快,快到父进程唤醒子进程的过程还没开始,父进程就已经被执行完了,那么父进程已经进入终止状态,cpu使用权回到了systemd这个进程上,那么只能是systemd这个进程去调用子进程,所以现在子进程的父进程号就变成了systemd的进程号了。

解决上面这个问题,我们就必须要要让父进程等待子进程,直到子进程执行完再把cpu使用权返回给systemd。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
pid_t cid;
//child pid
printf("Before fork Process id:%d\n", getpid());
cid = fork();
if (cid == 0){
printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());
for(int i = 0; i < 3; i++){
printf("hello\n");
}
}else{
printf("Parent Process id: %d\n",getpid());
for(int i = 0; i < 1; i++){
printf("world(%d)\n",getppid());
}
wait(NULL); //等待子进程结束,再返回,()里面参数一般是空指针
}
return 0;
}

相关文章:

进程章节总结性实验

进程实验课笔记 本节需要有linux基础&#xff0c;懂基本的linux命令操作即可。 Ubuntu镜像下载 https://note.youdao.com/s/VxvU3eVC ubuntu安装 https://www.bilibili.com/video/BV1j44y1S7c2/?spm_id_from333.999.0.0 实验环境ubuntu22版本&#xff0c;那个linux环境都可以…...

【MyBatis】MyBatis的缓存

10、MyBatis的缓存 10.1、MyBatis的一级缓存 一级缓存是SqlSession级别的&#xff0c;通过同一个SqlSession查询的数据会被缓存&#xff0c;下次查询相同的数据&#xff0c;就会从缓存中直接获取&#xff0c;不会从数据库重新访问 使一级缓存失效的四种情况&#xff1a; 不…...

MyBatis基本使用

一、简介 MyBatis 中文文档 https://mybatis.org/mybatis-3/zh/index.html 1.什么是 MyBatis 概述&#xff1a;MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBa…...

如何运行YOLOv6的代码实现目标识别?

YOLOv6是由美团视觉团队开发的1.环境配置我们先把YOLOv6的代码clone下来git clone https://github.com/meituan/YOLOv6.git安装一些必要的包pip install pycocotools2.0作者要求pytorch的版本是1.8.0,我的环境是1.7.0&#xff0c;也是可以正常运行的pip install -r requirement…...

新品BCM6755A1KFEBG/MT7921LE/MT7921AU WiFi芯片

博通在WiFi市场具有相当的实力。在WiFi6上有下面这几个解决方案&#xff1a;型号&#xff1a;BCM6755 BCM6755A1KFEBG类型&#xff1a;四核1.5GHz CPU封装&#xff1a;BGA批次&#xff1a;新BCM6755和BCM6750还是A7架构&#xff0c;更多的用在中低端型号上。BCM6755和BCM6750 C…...

析构函数、拷贝构造

1、析构函数析构函数的定义方式函数名和类名相同&#xff0c;在类名前加~&#xff0c;没有返回值类型&#xff0c;没有函数形参&#xff08;不能重载&#xff09;当对象生命周期结束的时候&#xff0c;系统会自动调用析构函数先调用析构函数&#xff0c;再释放对象的空间析构函…...

光学镜头是制作过程阶段理解

光学镜头是由多组镜片组合而成&#xff0c;它是摄影机投影一及显微镜上必不可少的部件。那么光学镜头是如何制造的呢&#xff1f;光学镜头的制作分为以下四个阶段&#xff1a;第一、首先将一大块光学玻璃用钻石锯片进行切片&#xff0c;然后用钻头在每一块玻璃切片上钻出多块冰…...

实验室设计|实验室设计要点SICOLAB

一、实验室设计规划要素1、实验室布局&#xff1a;实验室的布局要符合实验室工作流程&#xff0c;可以将实验室划分为干净区和污染区&#xff0c;以确保实验室的卫生和实验的准确性。2、设备选购&#xff1a;根据实验需要选择适当的设备&#xff0c;并确保设备的质量和性能符合…...

I.MX6ULL_Linux_系统篇(16) uboot分析-启动流程

原文链接&#xff1a;I.MX6ULL_系统篇(16) uboot分析-启动流程 – WSY Personal Blog (cpolar.cn) 前面我们详细的分析了 uboot 的顶层 Makefile&#xff0c;了解了 uboot 的编译流程。本章我们来详细的分析一下 uboot 的启动流程&#xff0c;理清 uboot 是如何启动的。通过对 …...

【C#】async关键字修饰后有无await的影响

文章目录测试总结拓展&#xff1a;js的async await问题参考测试 来自微软官网的说法&#xff1a; 异步方法通常包含 await 运算符的一个或多个匹配项&#xff0c;但缺少 await 表达式不会导致编译器错误。 如果异步方法未使用 await 运算符标记悬挂点&#xff0c;则该方法将作…...

Interspeech2022 | 一种基于元辅助学习的低资源口语语义理解方法

中国移动研究院首席科学家冯俊兰博士带领人工智能与智慧运营中心语音团队共同撰写的文章《Meta Auxiliary Learning for Low-resource Spoken Language Understanding》被语音国际顶会Interspeech2022接收。 关于Interspeech Interspeech 是国际最大且最全面关于言语科学与技…...

File类的用法和InputStream,OutputStream的用法

这里写自定义目录标题一、File类1.构造方法2.普通方法二、InputStream1.方法2.FileInputStream3.Scanner类的应用三、OutputStream1.方法2.FileOutputStream3.PrintWriter类的应用一、File类 1.构造方法 签名说明File(File parent, Stringchild)根据父目录 孩子文件路径&…...

Java多线程——Thread类的基本用法

一.线程的创建继承Thread类//继承Thread类class MyThread extends Thread{Overridepublic void run() {System.out.println("线程运行的代码");} } public class Demo1 {public static void main(String[] args) {MyThread t new MyThread();t.start();//启动线程&a…...

【C++】类和对象练习——日期类的实现

文章目录前言1. 日期的合法性判断2. 日期天数&#xff08;/&#xff09;2.1 和的重载2.2 对于两者复用的讨论3. 前置和后置重载4. 日期-天数&#xff08;-/-&#xff09;5. 前置- -和后置- -的重载6. 日期-日期7. 流插入<<重载8. 流提取>>重载9. 总结10. 源码展示前…...

[LeetCode周赛复盘] 第 333 场周赛20230219

[LeetCode周赛复盘] 第 333 场周赛20230219 一、本周周赛总结二、 [Easy] 6362. 合并两个二维数组 - 求和法1. 题目描述2. 思路分析3. 代码实现三、[Medium] 6365. 将整数减少到零需要的最少操作数1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6364. 无平方子集计数1. 题目描…...

数字化时代,如何做好用户体验与应用性能管理

引言 随着数字化时代的到来&#xff0c;各个行业的应用系统从传统私有化部署逐渐转向公有云、行业云、微服务&#xff0c;这种变迁给运维部门和应用部门均带来了较大的挑战。基于当前企业 IT 运维均为多部门负责&#xff0c;且使用多种运维工具&#xff0c;因此&#xff0c;当…...

Python爬虫(7)selenium3种弹窗定位后点击操作,解决点击登录被隐藏iframe无法点击的登陆问题

之前的文章有关于更多操作方式详细解答&#xff0c;本篇基于前面的知识点进行操作&#xff0c;如果不了解可以先看之前的文章 Python爬虫&#xff08;1&#xff09;一次性搞定Selenium(新版)8种find_element元素定位方式 Python爬虫&#xff08;2&#xff09;-Selenium控制浏览…...

如何对项目健康度进行测量?评估项目健康状况

项目驱动变革&#xff0c;大部分公司逐步由运营驱动转变为项目驱动&#xff0c;带来更多重新和商业价值。对组织而言&#xff0c;从商业角度看&#xff0c;项目旨在推动组织从一个状态转到另一个状态&#xff0c;从而达成特定目标。项目的健康情况如何关乎项目和变革的成本&…...

美国原装二手keysight E4980A(安捷伦)2MHZ LCR表

Agilent E4980A、Keysight E4980A、LCR 表&#xff0c;20 Hz - 2 MHz E4980A 是 Agilent 的 2 MHz LCR 表。LCR表是一种电子测试设备&#xff0c;用于测量电子元件的电感&#xff08;L&#xff09;、电容&#xff08;C&#xff09;和电阻&#xff08;R&#xff09;。LCR 表可…...

《clean coder》:关于摆烂,争论和心态

“凡是不能在五分钟之内解决的争论&#xff0c;都不能依靠辩论解决” ---- Kent Beck 作为一个码农&#xff0c;我并不是一个喜欢争论的角色。很长一段时间会陷入一种摆烂的&#xff0c;被动的状态。“既然其他人想要这么做&#xff0c;就这么办吧”。这可能是非专业的行为中最…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...