当前位置: 首页 > 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;就这么办吧”。这可能是非专业的行为中最…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...