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

linux中利用fork复制进程,printf隐藏的缓冲区,写时拷贝技术,进程的逻辑地址与物理地址

1.prinf隐藏的缓冲区

1.思考:为什么会有缓冲区的存在?

2.演示及思考?

1).演示缓存区没有存在感
那为什么我们感觉不到缓冲区的存在呢?我们要打印东西直接就打印了呢?
我们用代码演示一下:

比如打开一个main.c,输入内容如下:

 #include <stdio.h>int main(){printf("hello");}

我们运行的之后直接就打印了hello,好像没有感觉到缓冲区 的存在;
原因是因为此时程序已经结束了,它会刷新缓冲区的内容;

2)演示缓冲区的存在

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){printf("hello");sleep(3);exit(0);
}

3.强制刷新
(1)方法一:遇到\n自动刷新
printf("hello\n");
(2)使用fflush刷新屏幕
fflush(stdout);

  1. _exit与exit

exit是先刷新缓冲区,然后再调用_exit(真正的退出);
_exit直接退出,不会刷新缓冲区;

比如如下的代码:

 #include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(){printf("hello");//fflush(stdout);sleep(3);_exit(0);//注意这里,不输出hello}

5.总结
printf将内容先写入到缓冲区中,缓冲区刷新到界面(屏幕)上的条件是:
(1)缓冲区放满
(2)缓冲区未满,强制刷新缓冲区到屏幕(方法一:\n;方法二:主动刷新:fflush(stdout));
(3)程序结束时,自动刷新缓冲区:exit方法;

6.为什么会有缓冲区的存在?

屏幕是一个硬件设备,是由操作系统来管理的,因此printf打印的时候需要调用操作系统的接口才能完成,这个时候我们需要从用户态切换到内核态,这个开销是比较大的.

2.fork复制进程  (重点)

1)shell:

在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(command interpreter,命令解析器)。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。

我们就是通过命令解释器(称为shell)(bash是命令解释器中的一种)和内核和系统进行交互的(Windows通过图形界面进行交互的);例如我们把ls交给bash,bash帮我们运行ls,然后把结果给用户;

2)fork如何复制进程?

fork是把已有的进程复制一份,当然把PCB也复制了一份,然后申请一个PID,子进程的PID=父进程的PID+1;

   如果父子进程想要做不同的事情,那么我们通过返回值来判断;
man fork

代码如下(代码下去自己练习,理解):

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>int main()
{char *s=NULL;int n=0;//控制父子进程执行的次数;pid_t id=fork();assert(id!=-1);if(id==0)//子进程{s="child";n=3;}else//父进程{s="parent";n=7;}//父子进程int i=0;for(;i<n;i++){printf("s=%s\n",s);sleep(1);}exit(0);
}

父子进程是两个独立的进程,各自执行各自的代码;如果父子进程要做不一样的事情,就通过if  else返回值来操作;

3)fork的时机

fork产生的这个子进程不是从头开始执行的,而是从fork之后开始执行的,就是说fork下面的代码子进程才开始执行,具体的是说从返回值这里子进程开始执行,子进程不会再fork了,所以不会出现子进程再去fork产生一个子进程的问题.
也就是说:从返回值这里开始,父进程返回子进程的PID,子进程返回0;

4)getppid与getpid

getppid:得到一个进程的父进程的PID;
getpid:得到当前进程的PID;

man getpid;
man getppid

3.fork补充:

操作系统精髓与设计原理第101页;

4.如何学好多进程以及面试考点?

1)充分理解多进程的概念(每次程序多执行几次,多理解一下)

2)考点:

fork多以笔试的形式出现;

面试的考点:

例如:

1.我们在进程中看到的地址是进程的物理地址还是逻辑地址?(为什么这么问,单进程不分物理地址和逻辑地址吗);

2.进程同步设计(比如多进程抢夺资源)(难点,用程序实现)

3.fork与文件指针

(1)fork 以后,父进程打开的文件指针位置在子进程里面是否一样?(先open再fork)
(2)能否用代码简单的验证一下?
(3)先fork再打开文件父子进程是否共享偏移量?父进程打开的文件指针位置在子进程里面是否一样?能否用代码简单验证一下.(先fork再open会怎么样?)

4.fork+exec

5.僵死进程原因及处理方法;

5.内存管理相关概念

1.简单分页 逻辑页 物理页 页表的概念:
从哲学层次看操作系统157页(需要详细看)

2.虚拟内存:

虚拟内存提供的三个重要的能力:
1) 它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,根据需要在磁盘和主存之间来回传送数据,使得能够运行比内存大的多的进程。
2) 它为每个进程提供了一致的地址空间,从而简化了存储器管理.
3) 它保护每个进程的地址空间不被其他进程破坏 .

6.写时拷贝技术

不采用写时拷贝,如何fork?

第一:复制开销比较大;
第二:占用内存空间;
所以我们对fork复制进程的过程就做了一个优化-----写时拷贝技术;

综上,就是fork的时候,子进程直接把父进程的页表复制过来,子进程发生写入(修改)的时候才分配内存复制,然后进行相应的页表修改.

写时拷贝是一种可以推迟甚至免除拷贝数据的技术.

内核设计与实现22页;

7.我们在进程中看到的地址是进程的物理地址还是逻辑地址?

我们先来看代码: (打印n的地址)

 printf("s=%s,pid=%d,ppid=%d,n的地址为:%p\n",s,getpid(),getppid(),&n);//打印n的地址

 

8.进程的逻辑地址与物理地址

父子进程中n的值都不一样,那么我们为什么看到n的地址是相同的呢?

我们在进程中看到的地址就是进程的逻辑地址(进程的4G空间,从0开始,一直往上增长);

32位系统上,都有一个0-4G的地址空间:
在Linux系统上,最上面这1G由内核使用,下面3G是用户在使用;
为什么是4G呢?在32位系统上,能够寻址的范围就是2^32=4294967296字节/1000=4294976K /1000=4294M /1000=4.29 G 约等于4G  .

而我们把所有的地址都编号,

1K=2^10 ,4K=2^12
物理页面能有多少个页面呢?4G/4K=2^32 / 212=2(32-12)=2^20个页面

所以说,父子进程逻辑地址一样,但是物理地址是不一样的;

以前我们的程序都是只有一个进程,我们逻辑地址相同,那么我们的逻辑地址映射过去的物理地址肯定也是相同的一块空间,只有一个进程,就不用刻意去理解逻辑地址和物理地址的差异;对于同一进程,逻辑地址相同,物理地址肯定相同.
现在,我们的程序都是多进程的,逻辑地址相同,对应的物理地址就不一定相同了;也就是说A进程和B进程的逻辑地址相同,就不能说明物理地址一定相同,我们还需要看各自的页表,看看页表是否相同.(页表就是逻辑页和物理页的映射关系);
不同进程的逻辑地址是没有比较的意义的;

9.为什么在程序中不直接使用物理地址呢?

我们无法预知哪些物理地址是空闲的,同时空闲的也是动态变化的,程序在不断的申请释放空间中.

相关文章:

linux中利用fork复制进程,printf隐藏的缓冲区,写时拷贝技术,进程的逻辑地址与物理地址

1.prinf隐藏的缓冲区 1.思考:为什么会有缓冲区的存在? 2.演示及思考? 1).演示缓存区没有存在感 那为什么我们感觉不到缓冲区的存在呢?我们要打印东西直接就打印了呢? 我们用代码演示一下: 比如打开一个main.c,输入内容如下: #include <stdio.h>int main(){printf…...

java游戏制作-拼图游戏

一.制作主界面 首先创建一个Java项目命名为puzzlegame 结果&#xff1a;】 二.设置界面 代码&#xff1a; 三.初始化界面 代码&#xff1a; 优化代码&#xff1a; 四.添加图片 先在Java项目中创建图片文件夹&#xff0c;将图片导入其中 管理图片&#xff1a; 五.打乱图片顺序...

使用sklearn报AttributeError: ‘NoneType‘ object has no attribute ‘split‘

错误原因 在使用scikit-learn的时候报AttributeError: NoneType object has no attribute split Exception ignored on calling ctypes callback function: <function _ThreadpoolInfo._find_modules_with_dl_iterate_phdr..match_module_callback at 0x7fb757978160> T…...

C++学习 --map

目录 1&#xff0c; 什么是map 2&#xff0c; 创建map 2-1&#xff0c; 标准数据类型 2-2&#xff0c; 自定义数据类型 2-3&#xff0c; 其他创建方式 3&#xff0c; 操作map 3-1&#xff0c; 赋值 3-2&#xff0c; 插入元素(insert) 3-2-1&#xff0c; 插入标准数据类…...

基于Qt QList和QMap容器类示例

## QList<T> QList<T>容器是一个数组列表,特点如下: 1.大多数情况下可以用QList。像prepend()、append()和insert()这种操作,通常QList比QVector快的多。这是因为QList是基于index标签存储它的元素项在内存中(虽然内存不连续,这点与STL的list 是一样的),比…...

Flask学习一:概述

搭建项目 安装框架 pip install Flask第一个程序 from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return "Hello World"if __name__ __main__:app.run()怎么说呢&#xff0c;感觉还不错的样子。 调试模式 if __name__ __main__:a…...

LeetCode:689. 三个无重叠子数组的最大和(dp C++)

目录 689. 三个无重叠子数组的最大和 题目描述&#xff1a; 实现代码与解析&#xff1a; dp 原理思路&#xff1a; 滑动窗口&#xff1a; 原理思路&#xff1a; 689. 三个无重叠子数组的最大和 题目描述&#xff1a; 给你一个整数数组 nums 和一个整数 k &#xff0c;找…...

Leetcode—206.反转链表【简单】

2023每日刷题&#xff08;三十三&#xff09; Leetcode—206.反转链表 头插法实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* reverseList(struct ListNode* head) {if(head NULL…...

Linux - 内存 - 预留内存占用分析

说明 Linux启动log中会显示平台的内存信息&#xff0c;公司SOC平台&#xff0c;物理DRAM实际size是128M&#xff0c;但是启动log中total size不足128MB&#xff0c;并且预留内存&#xff08;82272K reserved&#xff09;过多&#xff0c;启动log如下&#xff1a; Memory: 480…...

Java学习之路 —— Java高级

文章目录 前言1. 单元测试2. 反射2.1 获取Class对象的三种方式2.2 获取类的构造器的方法2.3 获取类的成员变量2.4 获取类的成员方法2.5 反射的作用 3. 注解3.1 自定义注解3.2 注解的原理3.3 元注解3.4 注解的解析 4. 动态代理5. 总结 前言 终于走到新手村的末端了&#xff0c;…...

git使用及常用命令

在初入公司中&#xff0c;若使用的是git管理工具&#xff0c;需要做以下步骤&#xff1a; 1&#xff0c;常用命令在&#xff1a; &#xff08;1&#xff09;&#xff0c;git config --global user.name xxx(名字) //若不设置 那么下次提交代码时会报错 其次该设置名字和…...

vue 学习 -- day36(分析工程结构)

//引入的不再是Vue构造函数了&#xff0c;引入的是一个名为createApp的工厂函数 import { createApp } from vue import App from ./App.vue //创建应用实例对象——app(类似于之前Vue2中的vm&#xff0c;但app比vm更“轻”&#xff0c;它少了很多属性和方法) const app creat…...

SQL Injection

SQL Injection SQL injection&#xff08;SQL注入&#xff09;&#xff0c;通过在输入字段或URL查询参数中执行SQL命令&#xff0c;导致对数据库的未经授权的访问。如果SQL注入成功&#xff0c;未经授权的人可能会读取、创建、更新甚至删除数据库表的记录 举个例子&#xff1a;…...

【Go入门】 Go搭建一个Web服务器

【Go入门】 Go搭建一个Web服务器 前面小节已经介绍了Web是基于http协议的一个服务&#xff0c;Go语言里面提供了一个完善的net/http包&#xff0c;通过http包可以很方便的搭建起来一个可以运行的Web服务。同时使用这个包能很简单地对Web的路由&#xff0c;静态文件&#xff0c…...

VS 将 localhost访问改为ip访问

项目场景&#xff1a; 使用vs进行本地调试时需要多人访问界面,使用ip访问报错 问题描述 vs通过ip访问报错 虚拟机或其它电脑不能正常打开 原因分析&#xff1a; 原因是vs访问规则默认是iis,固定默认启动地址是localhost 解决方案&#xff1a; 1.vs项目启动之后会出现这个 右…...

app使用

font-face{font-family:‘kaishu’; src: url(data:application/font-ttf;charsetutf-8;base64,AAEAAAASAQAABAAgRFNJR5PpVzIAAAEsAAAacEdTVUIzhvftAAAbnAAAAXBPUy8yY8pHoQAAHQwAAABWY21hcAsTB9YAAB1kAADD5GN2dCAvAiIAADhSAAAA5pmcGdt/siFHQAA5OQAAAOiZ2FzcAAXAAkAAOiIAAAAEGds…...

【迅搜01】安装运行并测试XunSearch

安装运行并测试XunSearch 这回的新系列&#xff0c;我们将学习到的是一个搜索引擎 迅搜 XunSearch 的使用。这个搜索引擎在 PHP 圈可能还是有一点名气的&#xff0c;而且也是一直在更新的&#xff0c;虽说现在 ElasticSearch 已经是实际上的搜索引擎霸主了&#xff0c;而且还有…...

Mac电脑VSCode配置PHP开发环境

1.安装 PHP 首先&#xff0c;打开终端&#xff0c;安装 Homebrew&#xff0c;输入如下命令&#xff1a; $ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 安装了 Homebrew 之后&#xff0c;你可以使用下面的…...

SpirngBoot + Vue 前后端分离开发工具代码

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…...

【数据结构初阶】单链表(附全部码源)

单链表 1&#xff0c;单链表的概念及结构2&#xff0c;单链表的实现2.1初始化内容&#xff08;所需文件&#xff0c;接口&#xff09;2.2申请结点2.3打印单链表2.4尾插2.5头插2.6尾删2.7头删2.8查找2.9在pos位置之后插入2.10在pos位置前面插入2.11删除pos之后的值2.12删除pos位…...

数据治理入门

处理模式 模式名称常见场景常见框架批处理夜间几个小时&#xff0c;无人值守hive spark datax流处理7*24H一直运行&#xff0c;无人值守maxwell, flink, flume, kafka即席处理人机交互接口访问 web页面 数据治理的意义 数据质量低&#xff1a;数据错误&#xff0c;不准确或不…...

uniapp 微信小程序登录 新手专用 引入即可

预览 第一步导入插件 在引入的页面的登录按钮下拷贝一下代码 <template><view class"content"><button type"primary" click"login">微信登录</button></view><TC-WXlogin :wxloginwxlogin /> </templ…...

PMCW体制雷达系列文章(4) – PMCW雷达之抗干扰

说明 本文作为PMCW体制雷达系列文章之一&#xff0c;主要聊聊FMCW&PMCW两种体制雷达的干扰问题。事实上不管是通信领域还是雷达领域&#xff0c;对于一切以电磁波作为媒介的信息传递活动&#xff0c;干扰是无处不在的。近年来&#xff0c;随着雷达装车率的提高&#xff0c;…...

Gin框架源码解析

概要 目录 Gin路由详解 Gin框架路由之Radix Tree 一、路由树节点 二、请求方法树 三、路由注册以及匹配 中间件含义 Gin框架中的中间件 主要讲述Gin框架路由和中间件的详细解释。本文章将从Radix树&#xff08;基数树或者压缩前缀树&#xff09;、请求处理、路由方法树…...

MacOS设置JAVA_HOME环境变量

首先先查看一下&#xff0c;系统当前使用的java是谁&#xff0c;可以使用/usr/libexec/java_home命令 % /usr/libexec/java_home /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home检查一下这个路径下的文件&#xff0c;发现这是一个jre的目录。加上-V参数看…...

闭眼检测实现

引言 这段代码是一个实时眼睛状态监测程序&#xff0c;可以用于监测摄像头捕获的人脸图像中的眼睛状态&#xff0c;判断眼睛是否闭合。具体应用实现作用说明如下&#xff1a; 1. 实时监测眼睛状态 通过摄像头捕获的实时视频流&#xff0c;检测人脸关键点并计算眼睛的 EAR&a…...

系列六、Java垃圾回收器主要有哪些?

一、Java垃圾回收器主要有哪些? UseSerialGC、UseParallelGC、UseConcMarkSweepGC、UseParallelNewGC、UseParallelOldGC、UseG1GC...

【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis

目录 【7】Spring Boot 3 集成组件&#xff1a;缓存组件 spring cache spring data redis什么是缓存抽象声明式注解JSR-107对应SpEL上下文数据 引入依赖cache 支持的缓存类型缓存类型配置NONESIMPLEREDIS自定义配置 CAFFEINE Hazelcast...总结 个人主页: 【⭐️个人主页】 需要…...

说说Java中的不可重入锁

什么是锁&#xff1f; 简单来讲在Java中&#xff0c;锁是一种用于并发控制的机制&#xff0c;用于保护共享资源&#xff0c;防止多个线程同时访问或修改数据导致的数据不一致性和线程安全问题。在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;每个对象都有一个相关联的…...

C++学习 --vector

目录 1&#xff0c; 什么是vector 2&#xff0c; 创建vector 2-1&#xff0c; 标准数据类型 2-2&#xff0c; 自定义数据类型 2-3&#xff0c; 其他创建方式 3&#xff0c; 操作vector 3-1&#xff0c; 赋值 3-2&#xff0c; 添加元素 3-2-1&#xff0c; 添加元素(assi…...