PooledByteBuf分配及回收之十五PooledByteBuf的回收

2023-05-16

PooledByteBufAllocator初始化

PoolThreadCache初始化

PoolAerna初始化

PoolChunk初始化

PoolSubpage初始化

PooledUnsafeDirectByteBuf初始化

分配微小型PooledByteBuf(未命中缓存场景)

分配小型PooledByteBuf(未命中缓存场景)

分配普通型PooledByteBuf(未命中缓存场景)

PoolChunkList源码解析

ReferenceCountUpdater源码解析

Recycler及基内部类初始化

Recycler.Stack<T> 压入对象

Recycler.Stack<T> 弹出对象

PooledByteBuf的回收

PoolSubpage  boolean free(PoolSubpage<T> head, int bitmapIdx)

   //subpage在使用中(在链表中)则返回true,否则返回false    
   boolean free(PoolSubpage<T> head, int bitmapIdx) {
        if (elemSize == 0) {
            return true;
        }
        //计算bitmap下标
        int q = bitmapIdx >>> 6;
        //计算在位图中的下标
        int r = bitmapIdx & 63;
        assert (bitmap[q] >>> r & 1) != 0;
        //将位图中对应的位置为0
        bitmap[q] ^= 1L << r;
        //设置下一个可用
        setNextAvail(bitmapIdx);
        //可用数量为0的时候subpage已经不在链表中,需要将其加入链表中
        if (numAvail ++ == 0) {
            addToPool(head);
            return true;
        }

        if (numAvail != maxNumElems) {
            return true;
        } else {
            // Subpage 未被使用 (numAvail == maxNumElems)
            if (prev == next) {
                // 如果链表中只有一个subpage,那么不要删除它
                return true;
            }

            // 如果链表中还有其它subpage,那么从链表中删除当前subpage
            doNotDestroy = false;
            removeFromPool();
            return false;
        }
    }

    private void addToPool(PoolSubpage<T> head) {
        assert prev == null && next == null;
        prev = head;
        next = head.next;
        next.prev = this;
        head.next = this;
    }

    private void removeFromPool() {
        assert prev != null && next != null;
        prev.next = next;
        next.prev = prev;
        next = null;
        prev = null;
    }

 

PoolChunk  free(long handle, ByteBuffer nioBuffer)

    void free(long handle, ByteBuffer nioBuffer) {
        //handle的低32位是memoryMapIdx
        int memoryMapIdx = memoryMapIdx(handle);
        //handle的高32们是bitmapIdx
        int bitmapIdx = bitmapIdx(handle);
        // bitmapIdx !=0 表明分配的是subpage
        if (bitmapIdx != 0) {
            //根据 memoryMapIdx 获取subpages中的某个subpage
            PoolSubpage<T> subpage = subpages[subpageIdx(memoryMapIdx)];
            assert subpage != null && subpage.doNotDestroy;

            // 获取PoolArena拥有的PoolSubPage池的头并在其上进行同步。
            // 这是必需的,因为我们可能会重新添加它,从而更改链表的结构。
            PoolSubpage<T> head = arena.findSubpagePoolHead(subpage.elemSize);
            synchronized (head) {
                //前面已分析过 注意如果subpage已经不在链表中,那么接着处理下面的逻辑
                if (subpage.free(head, bitmapIdx & 0x3FFFFFFF)) {
                    return;
                }
            }
        }
        //当前chunk的可用字节数增加
        freeBytes += runLength(memoryMapIdx);
        //设置当前节点为可用
        setValue(memoryMapIdx, depth(memoryMapIdx));
        //设置当前节点的父节点为可用
        updateParentsFree(memoryMapIdx);

        if (nioBuffer != null && cachedNioBuffers != null &&
                cachedNioBuffers.size() < PooledByteBufAllocator.DEFAULT_MAX_CACHED_BYTEBUFFERS_PER_CHUNK) {
            cachedNioBuffers.offer(nioBuffer);
        }
    }

    private static int memoryMapIdx(long handle) {
        return (int) handle;
    }

    private static int bitmapIdx(long handle) {
        return (int) (handle >>> Integer.SIZE);
    }

    private int subpageIdx(int memoryMapIdx) {
        return memoryMapIdx ^ maxSubpageAllocs; // remove highest set bit, to get offset
    }
    
    //PoolArena的findSubpagePoolHead  
    //根据elemSize获取某个PoolSubpage
    PoolSubpage<T> findSubpagePoolHead(int elemSize) {
        int tableIdx;
        PoolSubpage<T>[] table;
        if (isTiny(elemSize)) { // < 512
            tableIdx = elemSize >>> 4;
            table = tinySubpagePools;
        } else {
            tableIdx = 0;
            elemSize >>>= 10;//除以1024
            while (elemSize != 0) {
                elemSize >>>= 1;
                tableIdx ++;
            }
            table = smallSubpagePools;
        }

        return table[tableIdx];
    }

    private int runLength(int id) {
        // represents the size in #bytes supported by node 'id' in the tree
        return 1 << log2ChunkSize - depth(id);
    }

    private void setValue(int id, byte val) {
        memoryMap[id] = val;
    }


    private void updateParentsFree(int id) {
        int logChild = depth(id) + 1;
        while (id > 1) {
            int parentId = id >>> 1;
            byte val1 = value(id);
            byte val2 = value(id ^ 1);
            logChild -= 1; // 在第一个迭代中等于log,随后在向上遍历时从logChild中减少1

            //如果val1 == val2 == logChild,则表明两个子节点均可用,那么父节点的值就是其depth
            if (val1 == logChild && val2 == logChild) {
                setValue(parentId, (byte) (logChild - 1));
            } else {
                //否则存在一个子节点不可用,父节点的值就是可用子节点的depth
                byte val = val1 < val2 ? val1 : val2;
                setValue(parentId, val);
            }

            id = parentId;
        }
    }

 

PoolChunkList       free(PoolChunk<T> chunk, long handle, ByteBuffer nioBuffer)

    boolean free(PoolChunk<T> chunk, long handle, ByteBuffer nioBuffer) {
        //前面已分析
        chunk.free(handle, nioBuffer);
        //如果chunk的使用率小于当前chunkList的使用率
        if (chunk.usage() < minUsage) {
            //将chunk从链表中删除
            remove(chunk);
            // 将PoolChunk向下移动到PoolChunkList链接列表中。
            return move0(chunk);
            
        }
        return true;
    }

    
    private void remove(PoolChunk<T> cur) {
        if (cur == head) {
            head = cur.next;
            if (head != null) {
                head.prev = null;
            }
        } else {
            PoolChunk<T> next = cur.next;
            cur.prev.next = next;
            if (next != null) {
                next.prev = cur.prev;
            }
        }
    }

    private boolean move0(PoolChunk<T> chunk) {
        if (prevList == null) {
            // 前面没有PoolChunkList,所以返回false会导致PoolChunk被销毁,并且与PoolChunk关联的所有内存都将被释放。
            assert chunk.usage() == 0;
            return false;
        }
        return prevList.move(chunk);
    }


    private boolean move(PoolChunk<T> chunk) {
        assert chunk.usage() < maxUsage;

        if (chunk.usage() < minUsage) {
            // 将PoolChunk向下移动到PoolChunkList链接列表中。
            return move0(chunk);
        }

        // PoolChunk fits into this PoolChunkList, adding it here.
        add0(chunk);
        return true;
    }


     void add0(PoolChunk<T> chunk) {
        chunk.parent = this;
        if (head == null) {
            head = chunk;
            chunk.prev = null;
            chunk.next = null;
        } else {
            chunk.prev = null;
            chunk.next = head;
            head.prev = chunk;
            head = chunk;
        }
    }

PoolThreadCache.add    需要再熟悉PoolThreadCache初始化


    boolean add(PoolArena<?> area, PoolChunk chunk, ByteBuffer nioBuffer,
                long handle, int normCapacity, SizeClass sizeClass) {
        //获取MemoryRegionCache
        MemoryRegionCache<?> cache = cache(area, normCapacity, sizeClass);
        if (cache == null) {
            return false;
        }
        //缓存
        return cache.add(chunk, nioBuffer, handle);
    }


    private MemoryRegionCache<?> cache(PoolArena<?> area, int normCapacity, SizeClass sizeClass) {
        switch (sizeClass) {
        case Normal:
            return cacheForNormal(area, normCapacity);
        case Small:
            return cacheForSmall(area, normCapacity);
        case Tiny:
            return cacheForTiny(area, normCapacity);
        default:
            throw new Error();
        }
    }
  
    //普通型 >=8192 小于16MB
    private MemoryRegionCache<?> cacheForNormal(PoolArena<?> area, int normCapacity) {
        if (area.isDirect()) {
            //numShiftsNormalDirect=13 1<<13 = 8192
            int idx = log2(normCapacity >> numShiftsNormalDirect);
            return cache(normalDirectCaches, idx);
        }
        int idx = log2(normCapacity >> numShiftsNormalHeap);
        return cache(normalHeapCaches, idx);
    }

    //小型 >=512 小于8192 smallSubPageDirectCaches的长度为4 
    private MemoryRegionCache<?> cacheForSmall(PoolArena<?> area, int normCapacity) {
        int idx = PoolArena.smallIdx(normCapacity);
        if (area.isDirect()) {
            return cache(smallSubPageDirectCaches, idx);
        }
        return cache(smallSubPageHeapCaches, idx);
    }

    static int smallIdx(int normCapacity) {
        int tableIdx = 0;
        // 1<<10 = 1024
        int i = normCapacity >>> 10;
        while (i != 0) {
            i >>>= 1;
            tableIdx ++;
        }
        return tableIdx;
    }

    //微小型 小于512 tinySubPageHeapCaches的长度为32 下标的计算为normCapacity >>> 4
    private MemoryRegionCache<?> cacheForTiny(PoolArena<?> area, int normCapacity) {
        int idx = PoolArena.tinyIdx(normCapacity);
        if (area.isDirect()) {
            return cache(tinySubPageDirectCaches, idx);
        }
        return cache(tinySubPageHeapCaches, idx);
    }

    static int tinyIdx(int normCapacity) {
        return normCapacity >>> 4;
    }

    private static <T> MemoryRegionCache<T> cache(MemoryRegionCache<T>[] cache, int idx) {
        if (cache == null || idx > cache.length - 1) {
            return null;
        }
        return cache[idx];
    }


        public final boolean add(PoolChunk<T> chunk, ByteBuffer nioBuffer, long handle) {
            Entry<T> entry = newEntry(chunk, nioBuffer, handle);
            boolean queued = queue.offer(entry);
            if (!queued) {
                // If it was not possible to cache the chunk, immediately recycle the entry
                entry.recycle();
            }

            return queued;
        }

        private static Entry newEntry(PoolChunk<?> chunk, ByteBuffer nioBuffer, long handle) {
            Entry entry = RECYCLER.get();
            entry.chunk = chunk;
            entry.nioBuffer = nioBuffer;
            entry.handle = handle;
            return entry;
        }

        private static final ObjectPool<Entry> RECYCLER = ObjectPool.newPool(new ObjectCreator<Entry>() {
            @SuppressWarnings("unchecked")
            @Override
            public Entry newObject(Handle<Entry> handle) {
                return new Entry(handle);
            }
        });

PoolArena.free

    void free(PoolChunk<T> chunk, ByteBuffer nioBuffer, long handle, int normCapacity, PoolThreadCache cache) {
        //非池化
        if (chunk.unpooled) {
            int size = chunk.chunkSize();
            destroyChunk(chunk);
            activeBytesHuge.add(-size);
            deallocationsHuge.increment();
        } else {
            //池化
            SizeClass sizeClass = sizeClass(normCapacity);
            //先尝试缓存,前面已分析
            if (cache != null && cache.add(this, chunk, nioBuffer, handle, normCapacity, sizeClass)) {
                // cached so not free it.
                return;
            }
            //未缓存则释放
            freeChunk(chunk, handle, sizeClass, nioBuffer, false);
        }
    }

PoolArena freeChunk

    void freeChunk(PoolChunk<T> chunk, long handle, SizeClass sizeClass, ByteBuffer nioBuffer, boolean finalizer) {
        final boolean destroyChunk;
        synchronized (this) {
            我们仅在由于PoolThreadCache终结器而未调用freeChunk的情况下才调用此方法,否则由于延迟类加载而可能失败,例如tomcat。
            if (!finalizer) {
                switch (sizeClass) {
                    case Normal:
                        ++deallocationsNormal;
                        break;
                    case Small:
                        ++deallocationsSmall;
                        break;
                    case Tiny:
                        ++deallocationsTiny;
                        break;
                    default:
                        throw new Error();
                }
            }
            // PoolChunkList.free 前面已分析
            destroyChunk = !chunk.parent.free(chunk, handle, nioBuffer);
        }
        if (destroyChunk) {
            // 保持同步锁时不需要调用destroyChunk。
            destroyChunk(chunk);
        }
    }

protected abstract void destroyChunk(PoolChunk<T> chunk);  PoolArena子类实现此方法

DirectArena

        
        @Override
        protected void destroyChunk(PoolChunk<ByteBuffer> chunk) {
            if (PlatformDependent.useDirectBufferNoCleaner()) {
                PlatformDependent.freeDirectNoCleaner(chunk.memory);
            } else {
                PlatformDependent.freeDirectBuffer(chunk.memory);
            }
        }

 HeapArena

        @Override
        protected void destroyChunk(PoolChunk<byte[]> chunk) {
            // 依靠GC.
        }

 

 

PooledByteBuf父类AbstractReferenceCountedByteBuf 

初始化

属性
 

static final long REFCNT_FIELD_OFFSET
ReferenceCountUpdater.getUnsafeOffset(AbstractReferenceCountedByteBuf.class, "refCnt")
AbstractReferenceCountedByteBuf类refCnt属性的偏移量
static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> AIF_UPDATER
AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt")
AbstractReferenceCountedByteBuf类refCnt属性的原子性操作updater
static final ReferenceCountUpdater<AbstractReferenceCountedByteBuf> updater
        
new ReferenceCountUpdater<AbstractReferenceCountedByteBuf>() {
    @Override
    protected AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater() {
        return AIF_UPDATER;
    }
    @Override
    protected long unsafeOffset() {
        return REFCNT_FIELD_OFFSET;
    }
};
一个引用计数器,若真实的引用计数=1 则回收此ByteBuf
volatile int refCnt
updater.initialValue()
引用计数,初始值为2

 

 构造方法

    protected AbstractReferenceCountedByteBuf(int maxCapacity) {
        super(maxCapacity);
    }

 

回收

    @Override
    public boolean release() {
        return handleRelease(updater.release(this));
    }

updater.release(this)  参考 ReferenceCountUpdater源码解析

    private boolean handleRelease(boolean result) {
        if (result) {
            deallocate();
        }
        return result;
    }

    //抽象方法,在子类PooledByteBuf中实现
    protected abstract void deallocate();

 

 

PooledByteBuf  deallocate() 解除分配

    @Override
    protected final void deallocate() {
        if (handle >= 0) {
            final long handle = this.handle;
            this.handle = -1;
            memory = null;
            //前面已分析
            chunk.arena.free(chunk, tmpNioBuf, handle, maxLength, cache);
            tmpNioBuf = null;
            chunk = null;
            //回收对象
            recycle();
        }
    }

 

先看recycle()    stack.push(this) 参考 Recycler及基内部类初始化  Recycler.Stack<T> 压入对象

    private void recycle() {
        recyclerHandle.recycle(this);
    }
        //DefaultHandle的recycle方法
        @Override
        public void recycle(Object object) {
            if (object != value) {
                throw new IllegalArgumentException("object does not belong to handle");
            }

            Stack<?> stack = this.stack;
            if (lastRecycledId != recycleId || stack == null) {
                throw new IllegalStateException("recycled already");
            }

            stack.push(this);
        }

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PooledByteBuf分配及回收之十五PooledByteBuf的回收 的相关文章

  • DataX 学习笔记

    一 DataX简介 1 1 DataX概述 DataX 是阿里巴巴开源的一个异构数据源离线同步工具 xff0c 致力于实现包括关系型数据库 MySQL Oracle等 HDFS Hive ODPS HBase FTP等各种异构数据源之间稳定
  • linux查看整个机器内存使用情况

    1 free命令 参数介绍 xff1a total 内存总数 used 已经使用内存数 free 完全空闲内存 shared 多个进程共享的内存 buffers 用于块设备数据缓冲 xff0c 记录文件系统metadata xff08 目录
  • Docker 学习笔记

    第1章 docker简介 1 1 什么是docker 1 Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目 xff0c 它是基于 dotCloud 公司多年云服务技术的一次革新
  • TiDB 学习笔记

    第一章 TiDB概述 TiDB官网 https pingcap com index html TiDB可以理解为是MySQL的加强版 分布式MySQL MySQLPlus TiDB 简介 TiDB 是 PingCAP 公司设计的开源分布式
  • SeaTunnel 学习笔记

    第1章 Seatunnel概述 官网地址 xff1a https seatunnel apache org 文档地址 xff1a https interestinglab github io seatunnel docs 1 1 SeaTu
  • Snake-SLAM:VIO、解耦化优化、延迟建图、图优化、鲁棒性初始化

    本来想写一篇文章 xff0c 但是这篇已经写的很好了 xff0c 不再赘述 xff1a 一种解耦非线性优化的高效VI SLAM系统 Snake SLAM
  • PooledByteBuf分配及回收之六PooledUnsafeDirectByteBuf初始化

    PooledByteBufAllocator初始化 PoolThreadCache初始化 PoolAerna初始化 PoolChunk初始化 PoolSubpage初始化 PooledUnsafeDirectByteBuf初始化 分配微小型
  • CubeMx工程增加FreeRtos支持

    对于stm32一些ram和flash相对大一些的mcu xff0c 增加一个实时操作系统 xff0c 会使程序控制更加灵活 本文阐述一下通过CubeMx自动添加FreeRtos的方法 xff0c 和使用visualgdb加载CubeMx生成
  • 整理leetcode刷题过程中遇到的常用库函数(c++)

    整理leetcode刷题过程中遇到的常用库函数 xff08 c 43 43 xff09 如果有额外的了解需求 xff0c 可以在微软c 43 43 库函数进行了解 以下按照我理解的刷题顺序整理 xff1a 数组 数组是刷题的开始 xff0c
  • s5pv210开发与学习:1.3之SD卡学习

    目录 拓展阅读 SD卡 内存 RAM 与外存 ROM 的区别 RAM random access memory 随机访问存储器 特点是任意字节读写 随机访问 xff0c 掉电丢失 ROM read only memory 只读存储器 用于存
  • RT-Thread 开发者能力认证考试样题(RCEA)

    V1 0 RT Thread 开发者能力认证考试样题 RCEA xff09 注 xff1a 样题仅为部分题目 第一小卷 单选题 40 题 40 分钟 40 0 分 1 对两个字符 a 和 b 进行初始化 xff1a char a 61 34
  • Android开发中为什么有些变量会以m开头

    平常在看Android代码和看别人敲代码的时候经常看到有些变量会以m开头 xff0c 这到底是什么样的命名规则呢 xff1f 首先看官网的答案 xff1a Follow Field Naming Conventions Non public
  • Ubuntu 串口设备 USB tty

    Ubuntu 串口设备 USB tty 概述USB查看详细信息 概述 研究Ubuntu下串口设备的连接 xff0c 简单的讲就是看有没有连接上 xff0c 至于使用后面再说 USB 使用命令如下可以查看USB接口的信息 xff0c dmes
  • Nooploop UWB LinkTrack ROS下配置

    Nooploop LinkTrack ROS 1 概述2 ROS下配置3 ROS系统安装4 串行库安装 5 ROS包的配置5 1 找不到libserial so文件5 2 解决办法 6 消息格式7 参考8 延伸阅读传感器配置节点程序分析经典
  • 相机标定之使用Kalibr工具箱

    相机标定之使用Kalibr工具箱 1 概述2 准备3 步骤4 参考链接5 相关链接 1 概述 简单介绍如何使用Kalibr工具箱进行针孔模型相机标定的步骤 xff0c 供自己以后参考 xff0c 同时希望给大家带来帮助 2 准备 提前准备好
  • 机器人学中的状态估计学习笔记(一)第二章 概率论基础

    机器人学中的状态估计学习笔记 xff08 一 xff09 第二章 概率论基础 2 1 概率密度函数2 1 1 定义2 1 2 贝叶斯公式及推断2 1 3 矩2 1 5 统计独立性和不相关性2 1 6 归一化积 2 2 高斯概率密度函数2 2
  • 机器人学中的状态估计学习笔记(二)第三章线性高斯系统的状态估计

    机器人学中的状态估计学习笔记 xff08 二 xff09 第三章线性高斯系统的状态估计 3 1 离散时间的批量估计问题3 1 1 问题定义3 1 2 最大后验估计3 1 3 贝叶斯推断3 1 4 存在性 唯一性与能观性情况1 xff1a 有
  • PooledByteBuf分配及回收之十PoolChunkList源码解析

    PooledByteBufAllocator初始化 PoolThreadCache初始化 PoolAerna初始化 PoolChunk初始化 PoolSubpage初始化 PooledUnsafeDirectByteBuf初始化 分配微小型
  • 机器人学中的状态估计学习笔记(三)第四章 非线性非高斯系统的状态估计

    机器人学中的状态估计学习笔记 xff08 三 xff09 第四章 非线性非高斯系统的状态估计 4 1 引言4 2 离散时间的递归估计问题4 3 离散时间的批量估计问题 4 1 引言 本小节主要是从一个简化的 一维度的非线性状态估计问题 估计
  • Camera-IMU联合标定原理

    Camera IMU联合标定原理 一 相机投影模型二 IMU 模型三 Camera IMU标定模型 一 相机 IMU旋转 二 相机 IMU平移 三 视觉惯性代价函数 四 camera imu联合标定 一 粗略估计camera与imu之间时间

随机推荐

  • 里程计及基于双目视觉的视觉里程计(stereo visual odometry)

    里程计在slam算法中扮演的作用不言而喻 xff0c 通常里程计可以分为轮子编码器的里程计 wheel odometry 和视觉里程计 visual odometry 而视觉里程计又可分为基于单目的视觉里程计 monocular odome
  • WIN7镜像中增加USB3.0驱动和语言包

    原版的win7镜像没有集成USB3 0的驱动 xff0c 如今的电脑主板基本是XHCI主控 xff08 以前是EHCI的 xff09 xff0c 这一变动导致在安装Win7的过程中会出现USB接口全部失灵的状况 xff0c 所以在安装时无法
  • Linux静态库与动态库示例之hello world

    Linux静态库与动态库示例之hello world 1 Linux动态库与静态库的基本概念 linux下有两种库 动态库和静态库 共享库 xff0c 二者的不同点在于代码被载入的时刻不同 静态库的代码在编译过程中已经被载入可执行程序 因此
  • 卡尔曼滤波原理及其在RSSI测距中的应用

    nbsp nbsp nbsp nbsp 卡尔曼滤波 Kalman filter 是一种高效的自回归滤波器 它能在存在诸多不确定性情况的组合信息中估计动态系统的状态 是一种强大的 通用性极强的工具 它的提出者 鲁道夫 E 卡尔曼 在一次访问N
  • cmakelist基本语法

    一 几个基本概念 xff1a 1 GCC a 由GUN 开发的编译器 支持C C 43 43 Java等语言 b 项目简单时 可以使用gcc g 43 43 来进行编译 c 项目复杂时 只使用gcc来进行编译会变得非常复杂 2 make a
  • LIST_ENTRY(item, type, member)详解

    64 brief Obtain the pointer to a structure that contains a list 64 param item IN Current node 39 s pointer to the next n
  • esp32 freertos backtrace问题定位

    log xff1a 17 42 41 320 收 TRAN OpenDataBusRequest ok TRAN Trans Srv Recv Data ret 0 TRAN TransDelSessionConnById channelI
  • 【荐书】李彦宏《智能革命》:技术是时代的信仰

    我来了 xff0c 天上的云乘着风飞翔 xff0c 心中的梦占据一个反向 xff0c 方舟扬帆起航 xff0c 一路带着我们纵情歌唱 xff0c 方舟扬帆起航 xff0c 脉络就在大海之上 xff0c 进步的时光 xff0c 迎着你看涛浪潮
  • PooledByteBuf分配及回收之十一ReferenceCountUpdater源码解析

    PooledByteBufAllocator初始化 PoolThreadCache初始化 PoolAerna初始化 PoolChunk初始化 PoolSubpage初始化 PooledUnsafeDirectByteBuf初始化 分配微小型
  • 在Windows环境下备份当前树莓派系统到IMG镜像

    2020年3月28日补充 写文章时采用的版本见图 xff0c 目前本人采用的DiskGenus版本为v5 0 0 589 xff0c 由于本人不使用gui界面 xff0c 将运行级别改为了3 针对Starting Show Plymouth
  • IMU+GPS

    GPS 43 IMU 介绍 xff08 熟悉的略过 xff09 IMU校准姿态估算数据融合 介绍 xff08 熟悉的略过 xff09 GPS GlobalPositioningSystem xff1a 指美国国防部研制的全球定位系统 用户设
  • Xinetd服务的安装与配置

    一 Linux守护进程与初始化进程 什么是守护进程 Linux服务器的主要任务就是为本地或远程用户提供各种服务 通常Linux系统上提供服务的程序是由运行在后台的守护进程 xff08 Daemon xff09 来执行 一个实际运行中的Lin
  • c++学习总结(4):继承与多态

    C 43 43 学习总结 xff08 4 xff09 xff1a 继承与多态 一 继承和派生二 子类与父类之间的构造函数与析构函数三 子类与父类成员重名四 多继承五 虚继承 virtual六 多态七 虚析构函数八 重载 xff0c 重写 x
  • Jenkins介绍和安装及配合GitLab代码自动部署

    Jenkins介绍和安装及配合GitLab代码自动部署 https www cnblogs com xiewenming p 7490828 html 一 xff0c 安装docker ce版本 1 1 删除之前版本的Docker sudo
  • 树莓派Raspberry 3b+ 搭建服务器全能环境+web控制面板+外网快速访问

    1 pi账户登录下 xff1b sudo wget O install sh http download bt cn install install ubuntu sh sudo bash install sh 注意 xff0c 记下提示的
  • 树莓派 frp内网穿透

    使用树莓派当服务器 无法在外网访问 需要用一台公网的服务器 将树莓派的 端 A 映射到服务器的 端 B 上 到时候访问端口B 就可以访问到树莓派的端口A 软件名称 frp 官 网 https github com fatedier frp
  • 广东IPTV 第三方APP应用安装(超简单)

    1 需要安装的APP软件先行下载到U盘或microSD卡 xff1b 2 插入盒子打开 xff0c 安装并打开文件管理软件 xff0c 把APP复制或移动到盒子的系统卡上 xff1b 3 直接双击安装APP即可 注意APP不能安装太多 xf
  • win10空间爆满,问题排查,从AppData \ Local \ Packages中删除数据

    问题 xff1a C盘139G xff0c 只剩2 8G可用 xff0c 生产很多问题 xff0c 导致很多软件无法正常安装和运行 xff0c 360常规清理了垃圾 xff0c 还是没什么改善 xff0c 于是排查大容量文件和文件夹 xff
  • 基于声音和视频的人跟随自动驾驶汽车- smart_car PC端 python环境搭建

    PC端环境和代码 1 先测试代码 xff0c 缺啥安装啥模块 xff1a 测试环境 ubuntu 16 04 desktop amd64 python2 7 sudo pip install pygame 注意要用root权限 pip安装O
  • PooledByteBuf分配及回收之十五PooledByteBuf的回收

    PooledByteBufAllocator初始化 PoolThreadCache初始化 PoolAerna初始化 PoolChunk初始化 PoolSubpage初始化 PooledUnsafeDirectByteBuf初始化 分配微小型