Linux中的fork()函数的面试题目

news2024/9/22 10:54:13

1.面试题目1

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

1).进程打开文件的流程

inode:

文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”。

每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。通过这个inode节点,即通过文件具体的一些信息,我们才能找到这个文件,读取它.

每个inode都有一个号码,操作系统用inode号码来识别不同的文件。

2).先打开再fork的流程(重点)  

代码如下:

先创建一个文件file.txt,内容为abcdefg;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>

int main()
{
    int fd=open("file.txt",O_RDONLY);
    assert(fd!=-1);

    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)
    {
        char buff[128]={0};
        int n=read(fd,buff,1);
        printf("child:%s\n",buff);
        sleep(1);
        n=read(fd,buff,1);
        printf("child:%s\n",buff);
    }
    else
    {
        char buff[128]={0};
        int n=read(fd,buff,1);
        printf("parent:%s\n",buff);
        sleep(1);
        n=read(fd,buff,1);
        printf("parent:%s\n",buff);

    }

    close(fd);
    exit(0);
}

父进程打开文件以后,fork产生子进程,父子进程共享打开的文件,同时共享文件偏移量;

为什么?如图:

3).先fork再open

代码修改如下:

 pid_t pid=fork();
  assert(pid!=-1);

int fd=open("file.txt",O_RDONLY);
    assert(fd!=-1);

(了解文件偏移量不共享)

为什么?如图:

面试题答案:

(1)在fork 之前打开的文件,在复制进程后,父子进程共享文件偏移量,所以文件指针在相同位置。

(2)代码如上

(3)先fork再打开文件,父子进程各自打开各自的,不共享偏移量;代码如上。

2.面试题目2

4).系统调用与库函数的区别

比如自己写的函数,调用的时候就是调换到函数的入口地址一句一句执行,但是系统调用就不一样,系统调用一旦执行,我们就需要 从用户空间切换到内核空间.
比如fopen :库函数 open:系统调用 fork:系统调用
可以man fopen (显示3),man  2 open (显示2),man  fork (显示2)

系统调用的执行过程:

在Linux中,每个系统调用都被赋予了一个系统调用号.这样,通过这个独一无二的号就可以关联系统调用.当用户空间的进程执行一个系统调用的时候,这个系统调用号就用来指明到底是要执行哪个系统调用号;进程并不会提及系统调用的名称;

系统调用是为了方便使用操作系统的接口,而库函数则是为了人们编程的方便;
库函数调用与系统无关,不同的系统,调用库函数,库函数会调用不同的底层函数实现,因此可移植性好;

5).malloc和free的三个问题:

思考下面三个问题:

(1)申请了一块空间没有free,进程就结束了,那么空间被回收了吗?
(2)malloc()申请3G的内存能否成功?判断依据是什么?

(3)父进程堆区申请的空间复制后,子进程也会有一份,也需要释放?

演示代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>

int main()
{
    char *s=(char *)malloc(1024ll*1024*1024*3);
    assert(s!=NULL);
    memset(s,0,1024ll*1024*1024*3);
    printf("main over!\n");
    exit(0);
}

1.进程在执行的过程中,malloc申请空间,不使用时,没有free就会出现内存泄漏;
如果进程结束了,那么所有向操作系统申请的内存都会被回放(释放);

2.申请1G或者更大空间,到底能不能成功?
如果当前的物理内存剩余空间够用,那么申请的空间肯定能成功;

如果不够用,我们先要看有没有虚拟内存,如果没有,不能成功;如果有虚拟内存,那么我们看内存+虚拟空间的大小能否满足,如果满足,那么我们是可以申请成功的,如果不够,当然不能成功;

首先我们需要了解一个名词:虚拟内存:

基于分页技术或者分页和分段技术的组合的虚拟内存,是现代计算机中内存管理最常用的方法之一.虚拟内存对应用程序完全透明,使得每个进程在执行时好像有无限的内存可用.为实现这一点,操作系统为每个进程在磁盘上创建一块虚拟地址空间,即虚拟内存.在需要的时候可以把部分虚拟内存载入到正在的内存中.这样,多个进程便可以共享相对比较小的内存.为了使虚拟内存载入到真正的内存中.这样,多个进程便可以共享相对比较小的内存.为了使虚拟内存更为有效,需要硬件机制来执行基本的分页和分段功能,如虚拟地址和实地址之间的地址转换.

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

<<深入理解计算机系统>>580页:(由此可知2,3)

了解两个命令:
sudo swapoff -a;关闭虚拟内存;
sudo swapon -a;开启虚拟内存;

若是32位系统,申请3G空间一定会失败,因为32位系统的用户总空间大小为3G.

 

(3)父进程堆区申请的空间复制后,子进程是不是也会有一份?是不是也需要释放?

我们先来看下面的代码:

#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
    char *s=(char *)malloc(128);
    assert(s!=NULL);

    pid_t pid=fork();
    assert(pid!=-1);

    free(s);

    exit(0);
}

编译运行并没有出错,如果是共享空间的话, 那么父子进程会对一个空间分别free,我们有前面学过的C语言可以知道,如果我们对一个空间free两次,编译运行会出现错误.

所以父子进程堆空间不共享(这里指的是每个进程的堆空间).哪怕父子进程对申请的对空间都没有操作.

其实如果对空间操作也是没有问题的,如下:

#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>  //1
int main()
{
    char *s=(char *)malloc(128);
    assert(s!=NULL);

    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)//2
    {
        strcpy(s,"child");//3
    }
    else  //4
    {
        strcpy(s,"parent");//5
    }
    printf("s=%s\n",s); //6
    free(s);

    exit(0);
}

结论:

父进程堆区申请的空间复制后,子进程也有一份.也需要释放;也就是说,fork会把进程的上下文都复制一遍,如果是malloc申请的话,内核会给子进程分配和父进程一样多的空间,父子进程都需要分别free;

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

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

相关文章

解决:ValueError: the first two maketrans arguments must have equal length

解决&#xff1a;ValueError: the first two maketrans arguments must have equal length 文章目录 解决&#xff1a;ValueError: the first two maketrans arguments must have equal length背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在…

Jmeter进阶使用:BeanShell实现接口前置和后置操作!

一、背景 我们使用Jmeter做压力测试或者接口测试时&#xff0c;除了最简单的直接对接口发起请求&#xff0c;很多时候需要对接口进行一些前置操作&#xff1a;比如提前生成测试数据&#xff0c;以及一些后置操作&#xff1a;比如提取接口响应内容中的某个字段的值。举个最常用…

L1-008:求整数段和

题目描述 给定两个整数A和B&#xff0c;输出从A到B的所有整数以及这些数的和。 输入格式&#xff1a; 输入在一行中给出2个整数A和B&#xff0c;其中−100≤A≤B≤100&#xff0c;其间以空格分隔。 输出格式&#xff1a; 首先顺序输出从A到B的所有整数&#xff0c;每5个数字占一…

保存规则、nat、自定义链

目录 一、保存防火墙的规则 1、保存规则 二、nat 一、SNAT和DNAT 1.SNAT 2 DNAT 三、自定义链 1.添加自定义链 2.设置自定义链并生效 3.删除自定义链 一、保存防火墙的规则 1、保存规则 [rootlocalhost ~]# iptables -A INPUT -s 172.16.114.30 -p tcp -m multiport…

echarts 地图

效果图 业务组件 <template><mapEcharts :itemStyle"mapProps.itemStyle" :emphasisLabelStyle"mapProps.emphasisLabelStyle":emphasisItemStyle"mapProps.emphasisItemStyle" :labelInfo"mapProps.labelInfo":rippleEffec…

leetCode 93.复原 IP 地址 + 回溯算法 + 图解 + 笔记

93. 复原 IP 地址 - 力扣&#xff08;LeetCode&#xff09; 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1…

信贷销售经理简历模板

这份简历内容&#xff0c;以信贷销售经理招聘需求为背景&#xff0c;我们制作了1份全面、专业且具有参考价值的简历案例&#xff0c;大家可以灵活借鉴。 信贷销售经理简历模板在线编辑下载&#xff1a;百度幻主简历 求职意向 求职类型&#xff1a;全职 意向岗位&#xff…

【隐私计算】VOLE (Vector Oblivious Linear Evaluation)学习笔记

近年来&#xff0c;VOLE&#xff08;向量不经意线性评估&#xff09;被用于构造各种高效安全多方计算协议&#xff0c;具有较低的通信复杂度。最近的CipherGPT则是基于VOLE对线性层进行计算。 1 VOLE总体设计 VOLE的功能如下&#xff0c;VOLE发送 Δ \Delta Δ和 b b b给send…

王者小游戏

游戏里的经验动物 Bear package beast; import sxt.GameFrame; public class Bear extends Beast {public Bear(int x, int y, GameFrame gameFrame) {super(x, y, gameFrame);setImg("C:\\Users\\辛欣\\OneDrive\\桌面\\王者荣耀图片(1)\\王者荣耀图片\\beast\\bear.jp…

从物理机到K8S:应用系统部署方式的演进及其影响

公众号「架构成长指南」&#xff0c;专注于生产实践、云原生、分布式系统、大数据技术分享。 概述 随着科技的进步&#xff0c;软件系统的部署架构也在不断演进&#xff0c;从以前传统的物理机到虚拟机、Docker和Kubernetes&#xff0c;我们经历了一系列变化。 这些技术的引入…

liunx java 生成图片 中文显示不出来

使用java 生成图片,在图片上打的文字水印显示为一个方框,这种情况的原因,一般是liunx系统或者docker容器内,没有你在打文字水印时选择的字体 解决办法,先找一个免费的字体,比如 Alibaba-PuHuiTi-Regular.otf 然后使用字体 File newFileT new File("Alibaba-PuHuiTi-Re…

OSPF的8种状态机总结,小白必看!

OSPF概述 在OSPF网络中&#xff0c;为了交换路由信息&#xff0c;邻居设备之间首先要建立邻接关系&#xff0c;邻居&#xff08;Neighbors&#xff09;关系和邻接&#xff08;Adjacencies&#xff09;关系是两个不同的概念。 邻居关系 OSPF设备启动后&#xff0c;会通过OSPF…

Python streamlit指南,构建令人惊叹的可视化Web界面!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在当今数据驱动的世界中&#xff0c;构建交互式、美观且高效的数据可视化应用变得至关重要。而Streamlit&#xff0c;作为Python生态系统中为开发者提供了轻松创建Web应用的利器。 本文将深入探讨Streamlit的方…

Android Studio Giraffe版本遇到的问题

背景 上周固态硬盘挂了&#xff0c;恢复数据之后&#xff0c;重新换了新的固态安装了Win11系统&#xff0c;之前安装的是Android Studio 4.x的版本&#xff0c;这次也是趁着新的系统安装新的Android开发工具。 版本如下&#xff1a; 但是打开以前的Android旧项目时&#xff…

Informer辅助笔记:data/dataloader.py

以WTH为例 import os import numpy as np import pandas as pdimport torch from torch.utils.data import Dataset, DataLoader # from sklearn.preprocessing import StandardScalerfrom utils.tools import StandardScaler from utils.timefeatures import time_featuresim…

动态:class和:style绑定

1. 在应用界面中, 某个(些)元素的样式是变化的 class/style绑定就是专门用来实现动态样式效果的技术 2. 动态class绑定 :class等号后的变量值 可以是字符串 :class等号后 可以是对象 :class等号后 可以是数组 3. 动态style绑定 :style"{ color: myPinkColor, fontS…

功能测试换工作不被认可?那你缺少这5点建议

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

asla四大开源组件应用示例(alsa-lib、alsa-utils、alsa-tools、alsa-plugins)

文章目录 alsa设备文件/dev/snd//sys/class/sound/proc/asoundalsa-lib示例1alsa-utilsalsa-toolsalsa-plugins参考alsa设备文件 /dev/snd/ alsa设备文件目录位于,/dev/snd,如下所示 root@xboard:~#ls /dev/snd -l total 0 drwxr-xr-x 2 root root 60 Nov 6 2023 …

速达软件全系产品 RCE漏洞复现

0x01 产品简介 速达软件是中小企业管理软件第一品牌和行业领导者,是128万家企业用户忠实的选择。14年来速达致力于进销存软件、ERP软件、财务软件、CRM软件等管理软件的研发和服务。 0x02 漏洞概述 速达软件全系产品存在任意文件上传漏洞&#xff0c;未经身份认证得攻击者可以…

flask web开发学习之初识flask(二)

文章目录 一、创建程序实例并注册路由1. 为视图绑定绑定多个URL2. 动态URL 二、启动开发服务器1. 自动发现程序实例2. 管理环境变量3. 使用pycharm运行服务器4. 更多的启动选项5. 设置运行环境6. 调试器7. 重载器 一、创建程序实例并注册路由 app.py # 从flask包中导入flask类…