文件缓冲区
前置博客 基础IO
为什么有缓冲因为磁盘的读写与内存的读写操作速度相比,磁盘的读写是相差数量级的慢,所以为了提高内存多次,频繁读写磁盘文件的效率,缓冲区被投入使用。尤其是内存内容写入磁盘时,常常先写入内存级缓冲区,再在特定规则下一次性将缓冲区的内容写入磁盘
**本文以C语言提供的用户级缓冲区为例介绍缓冲区
缓冲区的刷新规则首先当一个进程正常退出时,会先刷新缓冲区再关闭文件,此时必定有一次刷新
而当进程运行时缓冲区的刷新策略主要有以下三种
无缓冲 内容直接写入文件
C语言文件操作
用户级文件操作C语言的文件操作也是用户级的文件操作,通过FILE对象来管理每一个被打开的文件,以及提供了用户级文件缓冲区,因此还涉及到冲刷缓冲区等问题
FILE 类FILE类描述了一个文件流。里面存储了文件控制所需的信息:
指向自身缓冲区的的指针
位置指示器
状态指示器
所以C语言中对文件的管理就是对FILE对象的管理
基础操作 - 针对一般文件基础示例1234567891011#include <stdio.h>int main(){ FILE* pfile = fopen("file.txt", "w");//"w"模式打开文件file.txt int code = 1; const char* msg = "this is a msg"; fprintf(pfile, "get msg : %s code:%d", msg, code);//格式化输出字符串 fclose(pfile);//冲刷缓冲区并关闭文件 return 0;}
以上代码创建 ...
=C++= sizeof关键字详解
简介sizeof作为C/C++关键字,基本用法是求字节大小,但仅仅这一项用法在细节上就有很多说法了
求内置类型变量的大小有两种写法,以int a = 0的变量a为例
sizeof a
sizeof(a)
都可以求变量a的大小,但注意,该变量的大小仅与变量类型有关,而与值无关
求内置类型的大小求类型大小时必须加上括号
例如sizeof(int)
求数组的大小
当数组声明在全局或sizeof处于数组声明语句的局部作用范围时,能够用sizeof(<数组名>)求数组大小
当数组名经过函数传参或加减常量运算后,退化为指针变量,类型大小在32位机器中为4,64位机器中为8
12345678910111213141516171819#include <iostream>using namespace std;int g_arr[10] = { 0 };void func(int st_arr[]){ cout << sizeof(st_arr) << endl;//此处退化为指针变量,输出4或8} ...
基础IO
共识原理
文件 = 内容 + 属性
被打开的文件需要加载到内存中
内存中的文件需要被操作系统管理
用户级文件接口详见C++文件操作
详见C语言文件操作
Linux系统调用接口fd 文件描述符 与访问文件的本质
fd(file descriptor),即文件描述符,下文的系统调用接口经常以fd命名变量,fd是整形变量,作为数组下标,用于管理打开的文件
可以看到,一个进程通过struct files _struct里的指针数组,管理多个同时打开的文件
且每个进程启动时,会默认打开三个文件,且默认fd固定
stdout
read所需头文件#include <unistd.h>声明ssize_t read(int fd, void *buf, size_t count);
参数
fd即为目标文件的文件描述符
buf为要从文件读取字节到的内存地址
count为最大读取字节数
返回值
若成功,返回读取文件的字节数,类型为ssize_t,是层层封装的long int
若失败,返回-1,并设置errno的值
write所需头文件#include <unistd ...
初识动静态库(修改中)
动态库静态库
fork子进程,进程退出与等待
认识fork()头文件<unistd.h>提供的fork()函数用于从已有的原进程创建一个新的子进程,而原进程在关系式称为父进程
fork()的返回值12#include <unistd.h>pid_t id = fork();
父子进程中fork()函数的返回值(此处用变量id储存)是不同的:
父进程里id的值为子进程的PID,其值>0;子进程里id值固定为0
id > 0 父进程
id == 0 子进程
id < 0 fork()失败
分流https://picbed0521.oss-cn-shanghai.aliyuncs.com/blogpic/PixPin_2024-07-09_13-00-38.png
利用父子进程中fork()返回值的不同,可以用if...else...进行分流,让父子进程执行不同的代码
fork()的过程进程调用fork,当控制转移到内核中的fork代码后,内核做
分配新的内存块和内核数据结构给子进程
将父进程部分数据结构内容拷贝至子进程
添加子进程到系统进程列表当中
fork返回,开始调度器调度
ht ...
环境变量
基本概念
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性
构成:环境变量是一系列字符串的统称,所以一个环境变量由变量名和值构成
这么说还是太抽象了,我们接下来会举几个具体样例,体会环境变量在获取系统全局的变量,系统指令路径等方面的作用
常见环境变量
变量名
功能
PATH
指定命令的搜索路径
HOME
指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
USER
当前用户名
SHELL
当前Shell,它的值通常是/bin/bash
PWD
当前工作目录
操作系统变量查看环境变量echo $NAME NAME为变量名
以PATH为例,查看PATH的值的指令为
1echo $PATH
https://picbed0521.oss-cn-shanghai.aliyuncs.com/blogpic/PixPin_2024-07-08_12-46-35.png
可以看到PATH的内容为多个文件路径,互相以:分隔
而若要查看 ...
初识进程
操作系统平台:Linux服务器系统: CentOS 7
概念抽象程序程序 = 代码 + 数据
程序是储存在硬盘上的可执行文件
进程将程序加载到内存后,就在内存中程序的就是进程。也就是说一个正在运行的程序就能叫做进程
结构关系如下
如图,操作系统为了管理内存中的进程,使用了PCB结构体来描述进程,通过管理PCB来管理进程,依然是先描述再组织
PCB:进程控制块的数据结构(process control block)
所以实际上:进程=PCB+代码和数据
对于代码和数据没什么好说的,接下来主要讨论PCB
task_structLinux平台下的PCB叫做task_struct
task_struct内容分类:
标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据: 进程执行时处理器的寄存器中的数据。
I/O状态信息: 包括显示的I/ ...
C/C++ static关键字的使用
因为static的用法又多又杂,值得单出一篇博客用以汇总
C/C++ 通用用法局部变量->全局属性当对原本声明在函数栈帧里的变量使用static修饰时,该变量的存储空间会改变到静态区,不会随着函数栈帧的销毁而销毁。
初始化:初次调用声明语句时会执行声明操作,而之后再执行到该语句处时会自动跳过。
作用范围:与不加static时的作用范围相同,还是局部可用
销毁:和全局变量一样在main函数的栈帧销毁时一并销毁
全局变量->限制访问原本同级文件夹下的源文件可以用extern关键字互相获取全局变量,但如果用static修饰本地全局变量,那么这个全局变量只能在本文件调用,而其它文件看不到它
全局函数->限制访问原本同级文件夹下的源文件可以用extern关键字声明函数,然后去其它源文件的全局函数中寻找实现方式,但如果用static修饰本地全局函数,那么这个全局函数的实现只能在本文件调用,而其它文件看不到它
C++类和对象成员变量->静态成员 (全局变量)原本声明的成员变量在实例化后,属于由类实例化出来的对象,生命周期与所属对象相同,但在加了static后 ...