【notes1】linux命令,samba服务器,工具,并发/IO/内存


1.linux命令

nohup java -jar a.jar产生nohup.out(不是脚本输出打印而是异常打印)
netstat -ntlp查看运行程序的端口。
kill -9 %1(这个1就是jobs命令的1编号)。
top -d/n 1
内存条:dmidecode |grep -P -A5 "Memory\s+Device"|grep Size|grep -v Range
ps -ef | grep memtester | grep -v grep | cut -c 9-16 | xargs kill -9

echo b > /proc/sysrq-trigger # 强制重启(echo 1 > /proc/sys/kernel/sysrq激活,不保存数据,直接终止所有进程)
reboot -d 60 # 表示60秒后重启,发送SIGTERM信号通知进程保存数据
shutdown -r +5  # 系统将在5分钟后重启
shutdown -r now  # 立即重启

rm -rf !(bak)
du -sh openbmc
scp -r -P
rsync -av --exclude='build' openbmc/ /home/a/openbmc # 拷贝

find . -ls | grep 'usr/bin/',find . -iname a -not -path "./build/*"

1.1 用户管理及权限

useradd -m -s /bin/bash john (/bin/sh: chsh -s /bin/bash john),passwd john
vi /etc/sudoers, a ALL=(ALL:ALL) ALL , wq!保存, a用户能切到root用户。p是指管道文件。

在这里插入图片描述
在这里插入图片描述

1.2 find

在这里插入图片描述
日志文件没清空非常大,要找到删除,如下找系统中大文件,超过10M。
在这里插入图片描述
如下查找文件夹,文件夹有相应名字或大小属性。
在这里插入图片描述
如下基于修改时间,time是天。-1:今天一天之内。1:1天前这一天。+1:1天前。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下指定最大文件深度。
在这里插入图片描述
如下是find指令总结。
在这里插入图片描述

1.3 grep

在这里插入图片描述
如下* 可换成 * .txt
在这里插入图片描述
-r:递归子路径,-n:显示行号。-i:忽略大小写。
在这里插入图片描述
如下用于java日志文件非常大,要grep出某个异常如ioexception,且需要打印出exception下面几行看什么出了错。
在这里插入图片描述
在这里插入图片描述
如下.中的\是转义符,.168这样重复3次(注意168前面有.,不是168,而是数字)。
在这里插入图片描述
在这里插入图片描述

1.4 cat/more

cat的文件非常大,非常占用cpu和内存,这时候可以每次读取一小部分。
在这里插入图片描述
如下通过空格往后翻页。
在这里插入图片描述
如下指定从第四行开始读。
在这里插入图片描述
如下查看前后10行。
在这里插入图片描述
在这里插入图片描述

1.5 head/tail

在这里插入图片描述
如下打印文件最后两行,tail -f 阻塞监控。
在这里插入图片描述
df -h查看磁盘使用,占用率太高就需要使用前面find,grep指令并进行删除。
在这里插入图片描述
题目:输出当前路径及当前路径子路径下所有.txt文件,要求大小超过1M,并且按照从大到小顺序进行排序输出前10个?
先通过find . -name '*.txt' -size +1M -type f 查看是否有大于1M的txt文件,没有的话就不用继续了。
再通过find . -name '*.txt' -size +1M -type f -print0|xargs -0 du -m|sort -nr|head -10

1.6 iNode

linux文件系统中iNode用来存储文件原数据信息,不存储文件内容原数据信息包括:
类型:这个文件是个目录还是普通文件。
拥有者:这个文件是owner还是group owner。
时间ctime:上次inode变动时间。atime:上次访问时间。mtime:上次文件内容发生变动时间。
连接数:有多少文件名同时指向inode。一个文件名只对应一个inode,但一个inode可能被多个文件名同时指向。
文件内容所在的位置:文件真正内容所在磁盘块的标号。

1.文件系统fs在格式化好后,inode以什么样格式存储的呢?整个inode以数组形式存储,每个元素是一个inode,每个inode大小根据当前文件系统以及整个磁盘大小,inode会有一个固定128或256字节大小。

2.除了inode数组,fs初始化好后还会生成一个Map映射关系表(存储filename和inode index)。现在要读取/ect/1.txt,整个过程怎么样先根据文件名到Map中找到inode index,找到下标为假如是3的inode后拿出来如下图左边整个框。当前在读取/ect/1.txt,所以查看是否有读权限,如果有读权限就继续往下,找到文件内容所在位置(磁盘上块的下标)。
在这里插入图片描述
文件内容在磁盘中存储区域如下:以进行分隔,每个块大小也是根据当前fs和整个磁盘大小决定,并不是一个特定大小【扇区在磁盘生产时有多少个扇区,每个大小是定的,早期扇区512byte,现在4k】。文件系统fs在文件访问过程中不可能直接使用扇区,扇区是硬件的概念,所以抽象出一个概念:fs角度去看最小文件存储单元就是块,一个块可以有一个或多个扇区组成(2的幂次方即1,2,4…个扇区)。
在这里插入图片描述
一个块采用多少扇区也是有权衡的,比如一个块有好几兆,存一个1k文件也要占一个文件块,造成磁盘空间浪费。块选择过小的话也不好,如果一个块大小1bit,导致一个文件假如是1kb,它所在的块由1千个块组成,在inode中存储文件内容所在位置这个字段时候造成存1千个块信息(1千个块下标),一个inode(存1千个块下标)不可能128/256字节大小了,一个inode会很大,进而导致inode数组会很大,整个inode区大,这样导致磁盘损耗大量空间存储inode信息,较少的空间存储真正文件内容。

即使进行权衡,目前存在问题,如经常听到inode用完了即inode数组初始化大小用完了,声明完数组大小后不能增加或减少了。inode数组用完了即使磁盘还有额外空间也不能存储文件了,常见特别零碎文件数量又特别多占据磁盘大量inode导致整个inode用完。如早期docker采用overlay文件存储格式导致镜像的碎文件很多,导致inode用尽这样问题,后面采用overlay2文件存储格式一定程度上解决了这问题。

查看linux系统中inode数组以及每个文件所对应inode标号:df -i(inode),查看当前文件夹下文件所在的inode标号是什么ls -il。访问1.txt先查文件名和inode标号映射即Map,1.txt能找到270306这个标号。根据这个标号到1183200这个数组中拿取第270306个标号的inode。根据这个inode信息查看权限,最终找到1.txt在磁盘中存储位置,最后把这些磁盘块进行读取,最终读取到1.txt这个文件。
在这里插入图片描述
在这里插入图片描述
如果是一块移动硬盘,在其他设备上创建了文件,把这个移动硬盘拿到linux上面,有没有inode呢?
1.os可以支持多种fs。2.inode是在ext2/3/4等linux支持的文件系统(fs)有的。所以移动硬盘看是什么文件系统了,如果是ntfs或者exfat、fat32等等就是另一种访问形式了,inode其实是文件系统里的概念,而不是linux的概念。
在这里插入图片描述

#include <stdio.h>
#include <dirent.h>
int main() {
    DIR *dir;
    struct dirent *node;
    dir = opendir("."); // 打开当前目录
    if (dir == NULL) {
        printf("无法打开目录\n");
        return 1;
    }
    while ((node = readdir(dir)) != NULL) {  // 遍历目录, node->d_name是文件或目录名
        if (node->d_type == DT_REG) {
            printf("文件: %s,%d\n", node->d_name, DT_REG);    // DT_REG:8
        } else if (node->d_type == DT_DIR) { 
            printf("目录: %s,%d\n", node->d_name, DT_DIR);    // DT_DIR:4
        } else if (node->d_type == DT_LNK) { 
            printf("符号链接: %s,%d\n", node->d_name,DT_LNK); // DT_LNK:10
        } else {
            printf("其他类型: %s\n", node->d_name);
        }
    }
    closedir(dir);
    return 0;
}

1.7 打包和解压

# tar只是打包,并不压缩或解压
-f:--file
-c: 建立,create
-x:解压,eXtract
-t:查看内容
-j:--bzip2
-z:--gzip
-v:--verbose,详细列出处理过的文件

在这里插入图片描述

1.8 正则

^[]$:中括号内部只匹配一个字符。\d,?* +这些是[a-z]{m,n}这些的简写。
在这里插入图片描述
\d:相等于[0- 9],中括号里是什么或什么。\D:相等于[^0- 9],除了0到9外的任意字符。如下匹配数字\d 数字外任意字符\D(也就是匹配任意字符)。
在这里插入图片描述
\w:字母,数字或下划线,常用于用户名的命名上。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
组group:如上只想获取@前面的用户名,上面中括号,大括号都出现了,就差如下小括号。first就是组名,右边是js语法,underfined因为没命名。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.9 sed

如下将逗号替换为空格。s表示替换,g表示全局,即行中所有匹配项都被替换。sed -i ‘s/sys_led/sys_url/g’ /home/sysfs1/s3ip_sysfs_frame/sysurl_sysfs.c。
在这里插入图片描述
^匹配行首,$匹配行尾,如下d删除空行或只包含空格的行(因为行首行尾中间为空)。
在这里插入图片描述
sed常用于管道过滤,如下把x替换成y。
在这里插入图片描述
如下-r打开扩展正则,将逗号换成TAB。sed -n ‘60,70p’ a.txt :查看文件第60-70行。
在这里插入图片描述

1.10 awk

如下按逗号分隔并打印分割后的第三列和第四列,默认用空格/制表符/换行符作为字段分隔符。-F指定分隔符,-V设置变量,NF列数,$NF是一行数据最后一列的值,多用于对字段(像数据库中的字段)。
在这里插入图片描述
如下BEGIN指定了处理文本之前需要执行的操作。END指定了处理完所有行之后所需要执行的操作。
在这里插入图片描述
如下按逗号分隔并打印最后一列内容。
在这里插入图片描述
在这里插入图片描述
对比上面,如下一行一行读取并打印,列数>0打印。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下-c统计个数。
在这里插入图片描述
如下2是个数,不是序号。
在这里插入图片描述
在这里插入图片描述

2.samba服务器

@market指market组。文件传输协议:ftp,http,SMB(Samba)。
在这里插入图片描述
在这里插入图片描述
如下将本地用户转变为samba用户即共享用户。通过如下转变可实现该用户通过客户端访问服务器时提供验证标准了。
在这里插入图片描述
如下都是在文件末尾新添加的内容,都是逗号,writeable=no指除了下行外都不能写。[manager]是共享名即对方能看到的网络文件夹名称,comment是可共享目录的描述信息(可加可不加),valid_users指谁可以访问。
在这里插入图片描述
在这里插入图片描述
1.隐藏共享和拒绝访问:无法在网上邻居看到我们所共享的文件夹,但是通过unc路径做具体指定,我们可以访问到该文件夹下
windows里只需在共享文件夹名后面加一个$符号就能实现隐藏共享了。linux的samba中需修改主配置文件。如下将manager目录做一个隐藏。
在这里插入图片描述
2.别名:别名配置文件要自己建立
在这里插入图片描述
3.免登陆名:启用share级别(安全性最低,不需要通过用户名认证)
在这里插入图片描述
4.linux访问windows共享目录:mount
在这里插入图片描述
在这里插入图片描述
如上操作后share文件夹就有读写权限了。如下设置win账号,因为默认禁止空密码登录。
在这里插入图片描述

3.工具

su root(需输入root密码)。sudo su/-i(当前用户暂时申请root权限,需输入当前用户密码)。https://smallpdf.com/pdf-to-jpg。选择文件夹右击"授权访问权限",选择"特定用户",添加"所有人",权限改为"读取与写入",以共享方式访问,就可删除文件夹了,还有删除里面文件就可删除文件夹。
在这里插入图片描述
curl ipinfo.io 查公网出口ip。
在这里插入图片描述
https://www.usb-drivers.org/ft232r-usb-uart-driver.html。
在这里插入图片描述
1.内存卡插入读卡器再插入电脑的usb接口,将u盘格式化为FAT32格式。如果右击格式化没有FAT32则用格式化fat32工具:http://www.ridgecrop.demon.co.uk/guiformat.exe。树莓派系统官网:https://www.raspberrypi.org/downloads/raspbian/。下载系统(1.9G)用写盘工具(https://www.balena.io/etcher/或win32diskimager)将系统写入u盘,写完后不要格式化其他盘。

2.树莓派插上内存卡,接上网线(网络认证)或连上wifi(连wifi,eth0信息为空,因为没有连接网线,wlan0显示内网ip)用ifconfig查看网络。service ssh start开启ssh服务,树莓派默认用户名pi,密码raspberry,sudo netstat -antp可查看到当前有22端口即ssh端口被监听,这时可关闭显示器。如果忘了树莓派内网ip,可用win下cmd中输入arp -a查看局域网下所有ip和mac对应。本电脑就可以ssh连接树莓派再通过picocom -b 115200 /dev/ttyUSB0(有实际的线连)连接到机器终端,minicom -D /dev/ttyUSB0 -b登不上时进入/var/lock,删除lockfile,minicom又可正常启动。

Ubuntu镜像网站http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/。软碟通Ultraiso将从itellyou下载的win10或ubuntu镜像写入U盘。
在这里插入图片描述
bios启动过程按F7进入如下设置,UEFI启动U盘如下(legacy为老版本不用)。进入u盘引导选择install ubutu:安装过程如果出现/dev/sda一般是U盘,SSD一般为/dev/nvmeon1。设置时间,联网,apt-get install vim。bios启动依赖cpu和dimm。
在这里插入图片描述
vscode连接远程服务器报XHR failed:https://update.code.visualstudio.com/commit:d037ac076cee195194f93ce6fe2bdfe2969cc82d/server-linux-x64/stable (切换浏览器下载),拷贝进远程服务器解压如下:
在这里插入图片描述

3.1 pip换源

pip install速度慢,用pip换源:进入python,看os在哪个py脚本里即python工作路径在1下,所以在1下建pip文件夹可以执行。
在这里插入图片描述
在桌面新建pip文件夹再拖进1,在pip里新建.txt,再改为.ini文件,点击打开输入下面代码保存。
在这里插入图片描述
apt install python3-pip --fix-missing(断开vpn,cp /etc/apt/sources.list /etc/apt/sources.list.bak,python3 -m pip install --upgrade pip,apt-get update,pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com)
在这里插入图片描述
三个源:https://pypi.tuna.tsinghua.edu.cn/simple,https://pypi.douban.com/simple,https://mirrors.aliyun.com/pypi/simple,upgrade升级下numpy,看下载速度:pip install numpy -U

以上为windows换源,下面为ubuntu换源同理:cd ~mkdir .pipcd .pipgedit pip.conf,将以下内容复制到pip配置文件pip.conf中,保存退出即可。

[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host = mirrors.aliyun.com (上面http地址中间一部分,这行为了获取ssl证书,不然会报错)

4.并发/IO/内存

4.1 并发

并发对应硬件是cpu,线程是操作系统如何利用cpu资源的一种抽象,是cpu调度的最小单位。一个进程的内存空间是一套完整的虚拟内存地址空间,这个进程中所有线程都共享这一套地址空间。cpu并不在意是哪个进程,左边单核cpu(不是单线程),3个线程(任务都是读取文件)交叉运行完,通过以下两点大大提高了cpu利用率:1.DMA过程中cpu一段时间不被线程阻塞。2.DMA进行数据读取时可复用,因为cpu的总线程具有多条线路,所以DMA可充分利用这些线路,实现并行读取这些文件。多线程需调用系统底层API才能开辟(线程本质向cpu申请计算资源),在多线程开辟过程中浪费时间,并且在线程运行中上下文切换部分(左边切换多次,右边切换三次)有用户态和内核态转换浪费在cpu切换时间点上。所以服务端连接的客户端不活跃多(即io次数少)时用单线程。
在这里插入图片描述
如下是cpu常见参数:6种指令集即架构(方框),soc是A系列高端,ARM/MIPS都是公司名。
在这里插入图片描述
在这里插入图片描述
如下2个物理cpu,1个物理cpu有38个逻辑核【76个线程/频率/处理单元processor)】。CPU(S):所有cpu的总逻辑核数。socket:物理cpu数量。top -d 1。
在这里插入图片描述

可见性

c语言中也有volatile:一般用于中断程序,寄存器内存映射场景。
在这里插入图片描述
在这里插入图片描述
如下第一个core为主线程,第二个core为开辟的线程。
在这里插入图片描述
在这里插入图片描述
如上线程2不能立即读到线程1写后的最新变量值(线程1写,线程2读),多线程不可见性。如何解决多线程不可见性:加volatile关键字使a在主存和localcache间强制刷新一致。
在这里插入图片描述

原子性

如果线程1和2都进行基于读的变量再对读的变量再进行写,最典型操作i++,T1和T2都进行i++操作。读写原子AtomicInteger/synchronized
在这里插入图片描述
一开始i=0,经过两个线程两次i++操作结果变成了1,这显然是不对的,并且这种情况下不能用volatile保证这样操作的正确性(两个线程既有读操作,又有基于读操作的写操作,可见性只保证一个线程写另一个线程读是正确的,这里可见性不适用)。
在这里插入图片描述
现在想做的是将读操作和写操作合为一步,要么同时发生要么同时不发生(原子性)。在保证原子性同时一定以保证可见性为前提(不是并列关系,AtomicInteger类里本质上就是volatile),本身不可见的话没办法保证原子性。
在这里插入图片描述
也可用synchronized同步关键字来保证原子性发生,同步关键字同一时间只有一个线程进入代码段。
在这里插入图片描述
volatile可见性关键字最轻量级(保证一个线程写,一个线程读能读到最新的值),AtomicInteger(保证既有读操作又有写操作如i++这种场景下能保证操作的原子性)基于volatile,synchronized最重量级(能保证整个代码块中所有操作都是原子性的)。多线程情况下需要自增请使用Atomicxxx类来实现

4.2 IO多路复用

如下A,B…都是客户端,方框是服务端。首先想到应对并发,写一个多线程程序,每个传上来的请求都是一个线程,线程弊端cpu上下文切换,转回单线程。如下while(1)…for…就是单线程。
在这里插入图片描述

select

在这里插入图片描述
while(1)中FD_ZERO将rset初始化0,用FD_SET将有数据的fd插个旗子,并赋给rset。
在这里插入图片描述

poll

pollfds数组替代bitmap。
在这里插入图片描述

epoll

epoll_wait和前面select和poll不一样,有返回值。最后只遍历nfds,不需要轮询,时间复杂度为O(1)。epoll解决select的4个缺点。
在这里插入图片描述
阻塞:发起io读取数据的线程中函数不能返回。同步:拿到io读取完的数据之后,对数据的处理是在接收数据线程的上下文后紧接着处理。异步:回调函数中进行数据处理。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如上看出java比C语言系统调用多的多,因为java要启动jvm虚拟机,jvm要读jdk的lib库等很多操作。如上并没有发现open…xml操作,因为java程序主要启动jvm进程,jvm进程可能又起了很多线程去真正运行main函数,所以加-f。
在这里插入图片描述

4.3 内存管理

dma访问的物理内存不经过cpu cache,假设cpu写一段数据,数据还缓存在cache中,dma从内存中搬运,此时数据不对,所以要将cpu cache刷新到内存。同样,假设网卡发了一段数据到内存,dma去读,此时不能将cpu cache刷新到内存,在dma中断时将cpu cache无效掉。
在这里插入图片描述
cpu在保护模式下,内存访问不再是直接通过物理内存,而是基于虚拟内存,虚拟内存模式下,很多空间被分成连续的内存页,每个内存页大小固定,比如64k,这样cpu访问内存中数据时,都要先计算出先访问哪个内存页,cpu再通过一个地址映射表把虚拟的内存地址转化为物理的内存地址。地址映射表是一个数组,下标是内存页的页号,值是该内存页对应物理内存的首地址,也有可能某个内存页对应物理内存地址不存在,cpu就会发起缺页的中断请求。
在这里插入图片描述
2个插口是sata,1个是pcie,都叫m.2。引脚是cpu引到m.2上,m.2兼容sata,pcie,usb,uart,smbus等,mini pcie没有pcie。
在这里插入图片描述
如下m.2也是走pcie协议,m.2有的管脚,pcie插槽都有。pcie m.2里面有4个config管脚,4个管脚全部接地0000代表什么设备,0001代表什么设备,物理定死了。
在这里插入图片描述
读写文件和申请内存是用户态转内核态的两个例子:malloc的两种实现方式brk和mmap,两者只选一种。brk和mmap申请的都是虚拟内存,不是物理内存,想真拿到物理内存空间还要第一次访问时发现虚拟内存地址未映射到物理内存地址,于是促发一个缺页中断(也叫缺页异常,os中异常和中断有很多类似地方)。C语言是malloc,而java和c++中new对象申请内存空间,也是经过这么过程。
在这里插入图片描述
查看linux内核中有多少系统调用:man syscalls如下。
在这里插入图片描述
逻辑地址(逻辑/虚拟/进程内存):逻辑地址需映射到物理内存才能完成对内存操作,那为什么程序操作是虚拟的逻辑地址,不能直接操作物理地址即对内存条操作?因为程序是写死的(操作的地址是固定的),而硬件内存条哪些地址被占用了一直变化,因为os是多进程的,当前进程需要操作的地址,其他进程在使用,这样不能使用这块地址了,所以说除非是单进程机器,否则为了进程安全必须做出逻辑地址和物理地址的映射。

如下固定偏移量映射:程序1的偏移量(初始位置)是0,程序2的偏移量(初始位置)200:如果程序1操作的逻辑地址是100,那么映射的物理地址也100(因为偏移量0);如果程序2操作的逻辑地址是50,映射到物理内存250(因为偏移量200),存在两个缺陷:

第一个缺陷:程序使用的内存无法计算的,随时间推移,进程使用的内存不断变化。这里我们说程序1使用200的内存,这种说法本身不太对的,因为我们没法去限定一个程序使用的内存大小,当然你可以说我估算了这程序使用的最大内存就是200,但这也代表整个200的一段内存中,程序使用的内存绝大多数时间都小于200。蓝色区域中内存使用率并不高,其中存在很多没有利用起来的内存,我们把没利用起来的内存叫内碎片
在这里插入图片描述
第二个缺陷:当程序运行完,内存被释放,比如程序1执行完后,0-200这块地址被释放出来了,此时程序3使用了内存大小是201,这时程序3没法直接使用0-200这段内存了,假设很长一段时间内都没有占用200以内的内存这样的程序被创建,那么0-200一直被闲置,称这段内存为外碎片
在这里插入图片描述

分页

页表存在我们主存中即存在内存中,先读取页表,从页表中拿到对应帧号,再拿帧号去内存中再查询一遍,对内存操作有两次读取【时间上要优化(将页表集成到cpu中的mmu硬件中称为快表,先查快表,查不到查页表)】。页表存在主存中占空间【空间上要优化(多级页表)】。

将内存空间包括逻辑内存(左,页,地址连续)和物理内存(右,帧,地址不连续)都进行切分,分成固定大小很多片,每一片称它为页,降低了内存碎片问题。
在这里插入图片描述
页表是每个进程都需要维护的,因为每个进程映射关系是互相独立的,所以不能共用映射表,每个进程有自己的pagetable。
在这里插入图片描述
32位os物理地址有2的32次方个即4000000000个地址(内存的一个地址里住着一字节Byte数据)即4GB。32位程序以为自己拥有4GB内存,如两个32位程序,一个使用了2GB内存,另一个使用了3GB内存。但整个物理机只有4GB内存,造成虚拟地址可能比物理地址大,多出来部分可将虚拟地址的页映射到磁盘上。但映射到磁盘上导致下一次映射到磁盘上这一页内存时会触发一个缺页中断进入到内核态,整个会产生一个大(major)错误。linux下这磁盘部分又叫swapping(与物理帧交换)。
在这里插入图片描述

分段

对虚拟地址分成多个段:堆区heap和栈区stack也是程序的段,text(代码段,存程序本身二进制字节码),data(数据段,存程序中一些静态的变量)。不同程序共享内核(kernel space)这1G空间,共享内存如Libraries函数库(so/dll文件)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下free206M和available1.6G能用的是哪个?是1.6G。used包含shared,free是真正的空闲,没有任何东西在使用的大小。文件磁盘缓存指读过的文件暂时帮我们缓存到内存中下次再读的时候直接从内存中拿出来就能加速对文件读写操作。比如说现在free的空间只有206M,我有个程序要用1G内存,能用吗?,buffer/cache这边1.6G中有800M扔出去释放掉+206M=1G给程序。

buff/cache中间为什么有个/,较早内核中free-h看分buffcache(以磁盘扇区【硬件扇区】为单位直接对磁盘缓存)和pagecache(以页【文件系统】为单位对磁盘文件缓存)两项。两项有重复的地方,文件本质也是磁盘。
在这里插入图片描述

brk

C语言中有sbrk库函数是对brk的一个封装,如下brk申请内存,内存是连续的,并不是说在堆空间随便找内存就把空间给你。用户无法操作硬件如内存条,必须交给内核帮我们操作完了再把结果给我们
在这里插入图片描述
当前我们对第5,6,7,8四个字节赋int值123。只有第一个字节通brk申请出,却给第5-8字节赋值,这样会不会报错呢?不会,主要原因是在上节讲到的操系内存的分页管理所导致的,也就是说brk申请内存申请最小单位为1页,一般系统中页大小4k,所以brk看似申请1字节其实申请了一页(4096个字节),所以第5-8字节也属于4096字节里,也是当前进程所能支配的内存,所以不报错。
在这里插入图片描述
如下+号相当于向后移动1024个int,如下报段错误。
在这里插入图片描述

mmap

在这里插入图片描述
mmap还有直接将磁盘文件映射到内存作用,类似read,不是malloc。
在这里插入图片描述
如下触发大错误因为对文件的映射,将文件映射到内存,也是惰性的,这文件没有直接读到内存里,而是当真正需读文件里内容时才会映射到内存里。第一次触发是上面for循环里打印文件内容时到内存中读,发现这一页在查页表时对应是磁盘就触发一个缺页错误,对应是磁盘,触发majflt,将磁盘内容加载到内存中,之后就是一些小错误了。-p:指定进程号。-r:显示各个进程的内存使用统计。grep -v grep过滤掉包含grep的行。最后1是输出1次信息。
在这里插入图片描述
read系统调用进入内核态,内核态将文件内容加载到内核空间(如下kernel space),内核空间给它复制到用户空间,再从内核态切换到用户态,然后用户的程序就可读到文件的内容了,有个文件-内核空间-用户空间周转过程。

mmap直接将文件进行了映射,一开始在页表中填充的是磁盘disk即FILE文件,一开始mmap是惰性的直接对应磁盘文件,真正读取时触发缺页将文件加载到内存。

mmap这么牛干嘛还用read函数?mmap虽减少了内核空间到用户空间拷贝(0拷贝),但mmap没法利用前面讲的buffer/cache对文件缓冲这么一块空间,而且mmap第一次触发的缺页异常耗时不一定比read少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

43435675

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值