Linux文件操作应用及open和fork

1.文件操作的应用:

1).打开一个文件并往里面写入hello:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
int main()
{
    int fd=open("file.txt",O_WRONLY|O_CREAT,0600);
    assert(fd!=-1);

    printf("fd=%d\n",fd);
    write(fd,"hello",5);

    close(fd);
    exit(0);
}

2).打开文件,读取文件内容;

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
int main()
{
    int fd=open("file.txt",O_RDONLY);
    assert(fd!=-1);

    char buff[128]={0};
    int n=read(fd,buff,127);
    printf("n=%d,buff=%s\n",n,buff);

    close(fd);

    exit(0);
}

3).利用读和写对文件进行复制

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

int main()
{
    int fdr=open("file.txt",O_RDONLY);
    int fdw=open("newfile.txt",O_WRONLY|O_CREAT,0600);

    if(fdr==-1||fdw==-1)
    {
        exit(0);
    }

    char buff[256]={0};
    int num=0;

    while((num=read(fdr,buff,256))>0)
    {
        write(fdw,buff,num);
    }
    close(fdr);
    close(fdw);

    exit(0);
}

4).实现类似cp 命令

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

int main(int argc,char *argv[])
{
    if(argc!=3)
    {
        printf("argc error\n");
    }
    char *file_name=argv[1];
    char *newfile_name=argv[2];

    int fdr=open(file_name,O_RDONLY);
    int fdw=open(newfile_name,O_WRONLY|O_CREAT,0600);

    if(fdr==-1||fdw==-1)
    {
        exit(0);
    }

    char buff[256]={0};
    int num=0;

    while((num=read(fdr,buff,256))>0)
    {
        write(fdw,buff,num);
    }
    close(fdr);
    close(fdw);

    exit(0);
}

2.面试题详解fork

面试题目1:

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

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:

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) 它保护每个进程的地址空间不被其他进程破坏 .

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

(3)(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.mfbz.cn/a/193906.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解决Ruoyi-vue项目中接口请求超时的设置

背景&#xff1a; 有个几十亿的数据量的查询&#xff0c;查询时间超过40s&#xff0c;而Ruoyi-vue默认超过10s就拦截&#xff0c;因此需要修改默认超时时间 解决办法&#xff1a; 只需要打开request.js&#xff0c;把timeout设置扩大即可&#xff0c;默认是10000毫秒&#xff0…

6、Qt使用Log4Qt日志

一、知识点 1、Log4Qt有三部分 logger&#xff1a;负责捕获日志信息 layout&#xff1a;负责使用不同的样式输出日志 appender&#xff1a;负责输出信息到不同的目的地&#xff0c;比如数据库、文件、控制台等等 2、 日志级别如下&#xff0c;从上往下依次递增 ALL&#xff1a;…

线上问题整理-ConcurrentModificationException异常

项目场景&#xff1a; 商品改价&#xff1a;商品改价中通过多线程批量处理经过 Lists.partition拆分的集合对象 问题描述 商品改价中通过多线程批量处理经过 Lists.partition拆分的集合对象&#xff0c;发现偶尔会报 java.util.ConcurrentModificationException: nullat jav…

【密码学】【多方安全计算】不经意传输(Oblivious Transfer,OT)

文章目录 不经意传输&#xff08;oblivious transfer&#xff09;定义不经意传输的实例&#xff08;1 out 2&#xff0c;二选一不经意传输&#xff09;基于RSA的1 out 2 不经意传输疑问 不经意传输&#xff08;oblivious transfer&#xff09;定义 不经意传输&#xff08;obli…

开源运维监控系统-Nightingale(-夜莺)应用实践(未完)

一、前言 某业务系统因OS改造,原先的Zabbix监控系统推倒后未重建,本来计划用外部企业内其他监控系统接入,后又通知需要自建才能对接,考虑之前zabbix的一些不便,本次计划采用一个类Prometheus的监控系统,镜调研后发现Nightingale兼容Prometheus,又有一些其他功能增强,又…

【算法每日一练]-图论(保姆级教程 篇6(图上dp))#最大食物链 #游走

目录 题目&#xff1a;最大食物链 解法一&#xff1a; 解法二&#xff1a; 记忆化 题目&#xff1a;游走 思路&#xff1a; 题目&#xff1a;最大食物链 解法一&#xff1a; 我们标记f[i]是被f[x]捕食的点对应的类食物链数 不难得出&#xff1a; f[x]∑(f[i]) 首先从生…

Final project COMP 424, McGill University

Final project COMP 424, McGill University WeChat: zh6-86

电脑如何定时关机?

电脑如何定时关机&#xff1f;我承认自己是个相当粗心的人&#xff0c;尤其是在急于离开时经常会忘记关闭电脑&#xff0c;结果就是电量耗尽&#xff0c;导致电脑自动关机。而且&#xff0c;在我使用电脑的时候&#xff0c;经常需要进行软件下载、更新等任务。如果我一直坐等任…

XIAO ESP32S3之套件简绍

很高兴收到柴火创客空间寄来的XIAO ESP32S3开发套件。 一、套件介绍 1、电路板部分 一块XIAO ESP32S3主板、一块摄像头接口板&#xff08;可接SD卡&#xff09;&#xff0c;一根2.4G天线。 2、配件部分 一根USB-A转TypeC数据线、一个USB3.0转TypeC转接头、一个SD卡读卡器&am…

vue实战——登录【详解】(含自适配全屏背景,记住账号--支持多账号,显隐密码切换,登录状态保持)

效果预览 技术要点——自适配全屏背景 https://blog.csdn.net/weixin_41192489/article/details/119992992 技术要点——密码输入框 自定义图标切换显示隐藏 https://blog.csdn.net/weixin_41192489/article/details/133940676 技术要点——记住账号&#xff08;支持多账号&…

【WP】Geek Challenge 2023 web 部分wp

EzHttp http协议基础题 unsign 简单反序列化题 n00b_Upload 很简单的文件上传&#xff0c;上传1.php&#xff0c;抓包&#xff0c;发现php内容被过滤了&#xff0c;改为<? eval($_POST[‘a’]);?>&#xff0c;上传成功&#xff0c;命令执行读取就好了 easy_php …

Docker+Jmeter+InfluxDB+Grafana优化压测报告

1、安装docker 运行Docker&#xff0c;并记录当前Docker的IP地址&#xff0c;本处IP为192.168.99.100 2、安装并配置influxDB 下载镜像 网上获取&#xff1a;docker pull tutum/influxdb 本地安装&#xff1a;docker load < influxdb.tar 安装influxDB容器 docker run…

尚硅谷大数据项目《在线教育之实时数仓》笔记008

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第10章 数仓开发之DWS层 P066 P067 P068 P069 P070 P071 P072 P073 P074 P075 P076 P077 P078 P079 P080 P081 P082 第10章 数仓开发之DWS层 P066 第10章 数仓开发之DW…

Java游戏 王者荣耀

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayList…

2023年亚太杯APMCM数学建模大赛A题水果采摘机器人的图像识别

2023年亚太杯APMCM数学建模大赛 A题 水果采摘机器人的图像识别 原题再现 中国是世界上最大的苹果生产国&#xff0c;年产量约3500万吨。同时&#xff0c;中国也是世界上最大的苹果出口国&#xff0c;世界上每两个苹果中就有一个是中国出口的&#xff0c;世界上超过六分之一的…

Docker-简介、基本操作

目录 Docker理解 1、Docker本质 2、Docker与虚拟机的区别 3、Docker和JVM虚拟化的区别 4、容器、镜像的理解 5、Docker架构 Docker客户端 Docker服务器 Docker镜像 Docker容器 镜像仓库 Docker基本操作 1、Docker镜像仓库 镜像仓库分类 镜像仓库命令 docker lo…

CV计算机视觉每日开源代码Paper with code速览-2023.11.22

点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【语义分割】Mobile-Seed: Joint Semantic Segmentation and Boundary Detection for Mobile Robots 论文地址&#xff1a;https://arxiv.or…

高效视频剪辑:按指定时长批量分割视频,释放无尽创意

随着数字媒体技术的不断发展&#xff0c;视频剪辑已经成为日常生活中不可或缺的一部分。无论是制作电影、电视剧&#xff0c;还是创意生活短视频&#xff0c;视频剪辑都扮演着重要的角色。然而&#xff0c;对于许多非专业人士来说&#xff0c;视频剪辑可能是一项复杂而耗时的任…

C#,《小白学程序》第二十五课:大数乘法(BigInteger Multiply)的Karatsuba算法及源代码

1 文本格式 /// <summary> /// 《小白学程序》第二十五课&#xff1a;大数&#xff08;BigInteger&#xff09;的Karatsuba乘法 /// Multiplies two bit strings X and Y and returns result as long integer /// </summary> /// <param name"a">&…

如何在Ubuntu系统上安装Redis

Redis的下载 Redis安装包分为windows版和Linux版当前示例中介绍的是Linux版本Linux的下载地址&#xff1a;Index of /releases/ (redis.io)本次下载的压缩包为&#xff1a;redis-6.2.14.tar.gzRedis的安装 将压缩包通过ssh远程工具上传到Linux服务器中解压压缩包 tar -zxvf red…
最新文章