LINUX 内核设计于实现 阅读记录(2025.01.14)

文章目录

  • 一、内核历史
    • 1、内核简介
    • 2、LINUX 内核与 UNIX 内核比较
    • 3、LINUX内核版本命名
  • 二、从内核出发
    • 1、获取内核源码
      • (1)查看Linux内核版本 uname -r
      • (2)下载源码 https://www.kernel.org/
      • (3)编译内核
    • 2、内核源码树
    • 3、编译源码
    • 4、内核开发的特点
      • (1)GNU C 和 ANSI C
      • (2)内核没有内存保护机制,而且不分页
      • (3)最好不要在内核中使用浮点数
      • (4)内核程序的栈空间比较小,在编译时设置
      • (5)内核支持抢占式调度
      • (6)内核应该又高度的可移植性
    • 5、C语言扩展的特性
      • (1)内联函数 inline
      • (2)内联汇编
      • (3)分支声明
  • 三、进程管理
    • 1、进程描述符和任务结构
      • (1)进程描述符:task_struct
      • (2)内核中任务的组织结构
      • (3)进程状态
      • (4)进程上下文(待补充,理解不到位)
      • (5)进程家族树
    • 2、进程 与线程的创建(理解linux中线程与进程的重点)
    • 3、孤儿进程
  • 四、进程调度
    • 1、多任务
    • 2、LINUX的进程调度
    • 3、策略
      • (1)IO消耗型进程和CPU消耗型进程
      • (2)进程优先级
      • (3)时间片
    • 4、LINUX调度算法
      • (1)调度器类
      • (2)CFS
    • 5、调度的实现
      • (1)时间记账
      • (2)进程选择
      • (3)调度器入口
      • (4)进程的休眠
      • (5)抢占和上下文切换
      • (6)实时调度策略
      • (7)调度器相关的系统调用
  • 五、系统调用
    • 1、与内核通信
    • 2、使用API而不是直接使用系统调用
    • 3、系统调用
      • (1)系统调用号
      • (2)系统调用过程
    • 4、如何实现一个系统调用
      • (1)<asm/unistd.h> 中添加一个系统调用号
      • (2)在系统调用表添加系统调用
      • (3)实现系统调用函数
  • 问题记录
    • 1、用户进程和内核进程有什么区别?用户进程可以被直接调度吗?是否也存在与用户进程对应绑定的内核进程。
    • 2、实时进程和普通进程有什么区别?如何创建一个实时进程
    • 3、如何理解接口设计--->提供机制而不是策略?
    • 4、cortex-m3/4 执行一个函数时 他的寄存器中是啥内容?

一、内核历史

1、内核简介

LINUX内核是一个大的完整的C程序,提供可热插拔的模块。

2、LINUX 内核与 UNIX 内核比较

3、LINUX内核版本命名

主版本号 次版本号 修订版本号

二、从内核出发

1、获取内核源码

(1)查看Linux内核版本 uname -r

在这里插入图片描述

(2)下载源码 https://www.kernel.org/

(3)编译内核

解压 xz 包

xz -d linux-5.15.176.tar.xz

解压 tar 包

tar xvf linux-5.15.176.tar

依赖库下载

sudo apt install make gcc libncurses-dev flex bison libssl-dev libelf-dev

清理源码

make mrproper

清理目标文件

make clean

配置内核选项
编译、安装

2、内核源码树

3、编译源码

4、内核开发的特点

(1)GNU C 和 ANSI C

(2)内核没有内存保护机制,而且不分页

(3)最好不要在内核中使用浮点数

(4)内核程序的栈空间比较小,在编译时设置

(5)内核支持抢占式调度

(6)内核应该又高度的可移植性

LINUX作为一个可移植的操作系统,其实现代码大部分应该是于体系结构无关的,于体系结构相关的代码应该分离出来。

5、C语言扩展的特性

(1)内联函数 inline

C99 和 CNU C 均支持 内联函数,内联函数在函数调用处展开,可以消除函数调用和返回带来的开销(寄存器的恢复和存储)。但这会增加程序占用的空间和指令缓存。
一般在要求时间、简短的函数定义为nline。
语法

static inline fun(){}

需要static修饰,必须在使用之前定义好否则无法展开,内核中优先使用内联函数而不是宏定义

(2)内联汇编

gcc支持汇编代码,用 asm声明

(3)分支声明

gcc 将分支声明封装成宏 ==》likely() unlikely(),表明一个分支是经常出现还是极少出现。
在这里插入图片描述

三、进程管理

  1. 进程 (任务) 是处于执行期间的程序、是正在执行的程序的实时结果。
  2. 线程是在进程中活动的对象,线程拥有独立的计数器、栈、和寄存器。
  3. 内核调度的线程而不是进程。 Linux对线程和进程并不特别区分,线程是特殊的进程(轻量进程)。
  4. 进程提供两种虚拟机制:虚拟处理器和虚拟内存,虚拟处理器使得进程感觉自己独享处理器,虚拟内存使进程感觉自己独享整个内存。
  5. 线程共享进程的虚拟空间,但是线程有自己的虚拟处理器(线程1v1模型的原理)
  6. fork()系统调用从内核返回两次,一次返回父进程,一次返回主进程。

1、进程描述符和任务结构

(1)进程描述符:task_struct

结构体描述符存放在 /linux/sched.h

(2)内核中任务的组织结构

  1. 内核把进程存放在任务队列中,这个任务队列是双向循环链表的结构。
  2. task_struct比较大,在32位机中大约为1.7KB,它完整的描述了一个进程的所有状态。
  3. 通过预先分配和重复使用task_struct避免动态分配和释放带来的资源消耗
  4. Linux 通过slab分配器来分配task_struct,达到对象复用和缓存着色
  5. 在栈顶创建一个 thread_info的结构体,该结构体中有指向tsak_struct的指针。通过计算栈偏移量来寻找
  6. 内核通过PID标识一个进程。
  7. 通过current宏查找当前执行的进程的进程描述符

(3)进程状态

进程描述符的state域描述了进程的当前状态。
进程有5个状态
TASK_RUNNING:运行或就绪
TASK_INTERRUPTIBLE:可中断(阻塞)
TASK_UNINTERRUPTIBLE:不可中断(阻塞),但不可被唤醒,例如sleep期间
__TASK_TRACED:被其他进程追踪
__TASK_STOPPED:进程停止,如收到STOP信号。
在这里插入图片描述
设置进程状态

set_task_state(task,state)  == set_current_state(state)

(4)进程上下文(待补充,理解不到位)

系统调用和异常是内核留给用户的接口,当系统调用时,陷入内核,内核代表进程执行,并处于进程的上下文中。
上下文:进程程序执行的环境(CPU寄存器保存的值)
上下文切换:将不通进程的内容写入寄存器并保存旧的寄存器值到前一个进程的栈中。
内核代表进程执行:内核访问内核资源,并将结果通过系统调用传递给用户进程。
https://blog.csdn.net/zysharelife/article/details/7276998

(5)进程家族树

  1. 所有的进程都是PID为1 的进程(init)的后代,内核在启动的最后阶段启动init进程。该进程读取系统的初始化脚本
    在这里插入图片描述
  2. 进程间的关系存放在进程描述符中,通过parent指针指向父进程,通过children链表指向子进程

2、进程 与线程的创建(理解linux中线程与进程的重点)

在LINUX的内核中不分进程或者线程,在创建进程时调用clone函数,为进程分配资源,通过exec函数族加载一个程序到进程的地址空间,并采用写时拷贝来加快进程的创建速度。
在创建线程时 调用pthread_create,这个函数还是调用了clone函数。
创建进程和创建线程最终都是调用了clone函数,不同之处在于调用时的参数不通,在创建线程时
在这里插入图片描述
共享父进程的内存、文件描述都、信号等
在创建进程时
在这里插入图片描述
所以由此来看,线程和进程没有本质上的区别,在内核中都是以task_struct标识,不同之处在于task_struct的域信息不同。
这也是linux中线程也可以参加系统调度的原因。线程可以看作共享父进程一些资源的进程。

在不同的系统中实现多线程的机制是不同的。
一个进程的创建分为fork和exec两步,一个进程的回收也分为资源回收和进程描述符回收两部分。

3、孤儿进程

父进程先于自己终结的进程叫做孤儿进程,系统会为孤儿进程找一个同组进程或init进程作为新的父进程。
这个过程为

  1. 先在同组遍历
  2. 找不到合适进程,就将父进程设置为init进程,找到则将找到的进程设置为父进程。
  3. 遍历所有子进程,设置父进程

四、进程调度

进程调度程序可以看作内核的子系统,负责为可运行程序分配CPU时间。
调度器的通用概念:时间片 和 优先级

1、多任务

多任务系统分类:

  1. 非抢占式多任务 cooperative multitasking
  2. 抢占式多任务 preemptive multitasking (UNIX 使用):在分配的时间片未耗尽时打断进程的执行,去执行另一个进程。

2、LINUX的进程调度

LINUX 2.5 ==>> O(1)调度程序:静态时间片算法、对于每个CPU的任务队列,但是对时间敏感的(交互进程)响应不理想。所以在服务器运行尚可,在桌面环境运行不太理想。(O1 表示时间复杂度)
LINUX 2.6 ==>> 反转楼梯最后期限调度算法 RSDL,被称为完全公平的算法 CFS。

3、策略

策略决定进程调度的时机,策略决定系统的运行效率。

(1)IO消耗型进程和CPU消耗型进程

IO消耗型进程:处理IO请求,每次运行的时间短,等待的时间长
CPU消耗型进程:多数时间在执行代码或计算数据,对于这种进程应该尽量降低它的调度频率,让其运行时间延长。
调度策略要在两者中寻求一个平衡。
LINUX 更加倾向

(2)进程优先级

LINUX采用两种范围的优先级:nice值实时优先级,两个没有关联。
nice:值范围是 -20 ~ 19 值越低优先级越高,默认0,代表可获得的时间片比例。
实时优先级:0 ~ 99 值越高优先级越高 ,实时进程的优先级高于普通进程。
在这里插入图片描述

(3)时间片

时间片是一个常值,但是这个值的指定却不好确定,时间片太大,就会导致实时性降低,时间片太小就会消耗大量时间在进程的上下文切换中。
但是LINUX的CFS调度算法并不直接将时间片分配到进程,而是将CPU的使用比例分配给进程,这样不同的进程就会的到不通的CPU时间,这个比例的值收到nice值的影响。
LINUX的抢占式调度收到进程优先级和是否有时间片决定,当来了一个新的可运行进程,如果新进程的CPU使用(消耗)比例小于当前进程且优先级更高,当前进程就会被新进程抢占。
CPU使用(消耗)比例:一定时间内进程使用CPU的时间的比值。

4、LINUX调度算法

(1)调度器类

在Linux中调度器以模块的方式提供,被称为调度器类,这样做的目的是为了给内核提供多种不通算法的调度器,每种调度器管理自己范围内的进程,每次有多个可运行进程时,先比较他的调度器的优先级,优先级高的调度器先执行自己的进程。
CFS只是针对普通进程的调度器。

(2)CFS

CFS允许所有进程(n个)平分所有的CPU时间 1/n,循环调度
CFS抢占时以新进程的运行时间是否小于当前进程的运行时间为判断条件。
CFS不是依靠nice值计算时间片,而是用nice值进程获得CPU时间的权重。
CFS规定了获取CPU时间比例的最小标准==>最小粒度
CFS规定目标延迟:每个可运行任务在处理器上至少运行一次所需的最短时间,即最小粒度
在CFS中进程所获得的CPU时间由它自己和其他所有的程的nice值得相对差值决定。

5、调度的实现

(1)时间记账

所有的调度器都必须为进程记录运行时间。
CFS使用调度器实体结构 struct sched_entity 来追踪进程运行记账。

struct sched_entity {/* For load-balancing: */struct load_weight      load;struct rb_node          run_node;struct list_head        group_node;unsigned int            on_rq;u64             exec_start;u64             sum_exec_runtime;u64             vruntime;u64             prev_sum_exec_runtime;u64             nr_migrations;#ifdef CONFIG_FAIR_GROUP_SCHEDint             depth;struct sched_entity     *parent;/* rq on which this entity is (to be) queued: */struct cfs_rq           *cfs_rq;/* rq "owned" by this entity/group: */struct cfs_rq           *my_q;/* cached value of my_q->h_nr_running */unsigned long           runnable_weight;#endif#ifdef CONFIG_SMP/** Per entity load average tracking.** Put into separate cache line so it does not* collide with read-mostly values above.*/struct sched_avg        avg;#endif};

struct sched_entity 作为一个se成员嵌入到 tsak_struct 中。
调度器实体的 vruntime成员以纳秒为单位记录进程运行的虚拟时间(获取cpu的时间),vruntime的更新由系统周期性的调用updata_curr来实现,根据vruntime可以准确的测量出进程的运行时间,确定下一个运行进程是哪一个。

(2)进程选择

  1. CFS选择进程时选择vruntime最小的进程,以达到公平。
  2. CFS使用红黑树 rbtree(自平衡二叉查找树) 来存储可运行的进程队列,利用红黑树迅速寻找最小的vruntime。
  3. 最小的vruntime就是最左边的叶子节点,并将该节点存储,这样每次不用查找直接获取它就可以了。
  4. 在进程变为可运行状态或fork后被加入CFS的红黑树。
  5. 在进程变为阻塞或终止时从CFS红黑树删除。

(3)调度器入口

linux内核调度器入口为 schedule() 函数,schedule()通常要和一个调度类关联,每个调度器有一个自己的任务队列。
在schedule内调用pick_next_task() 函数一次从优先级高到优先级低访问每个调度类,询问最高优先级的进程,最后选择最高优先级的调度类的最高优先级的进程。

(4)进程的休眠

进程休眠时将自己设置为阻塞状态,并将自己移除可执行进程红黑树,并加入等待队列。TASK_INTERRUPTIBLE和
TASK_UNINTERRUPTIBLE两种阻塞函数存放在同一个等待队列上。
等待队列由一个简单的链表实现,等待队列有多种,不同的事件发生时唤醒不同的进程等待队列。

(5)抢占和上下文切换

切换上下文
进程上下文的切换调用contex_switch()函数实现,contex_switch内调用两个函数分步骤完成切花

  1. switch_mm()函数将虚拟内存从上一个进程映射到新进程。
  2. switch_to() 函数负责将处理器状态从上一个进程切换到新进程,包括旧现场的保存和新现场的恢复。

抢占

  1. 内核提供一个标志need_reched ,内核通过检查need_reched 标志来表明是否需要调用schedule()切换进程
  2. need_reched 标志存放在task_strucr中(不是全局的,应为当前task_struct存放在高速缓存中,访问更快)
  3. 内核抢占和用户抢占不同

(6)实时调度策略

  1. LINUX提供两种实时调度策略SCHED_FIFO SCHED_RR,有对应的调度类
  2. 普通的线程使用 SCHED_NORMAL 调度策略(CFS)
  3. 实时策略的调度类优先级永远比SCHED_NORMAL高
  4. SCHED_FIFO策略:不基于时间片,直到显示的调用schedule或阻塞后才会让出CPU,只能被优先级更高的SCHED_FIFO打断。
  5. SCHED_RR策略:带时间片的SCHED_FIFO。时间片耗尽也会调用同优先级的SCHED_RR。
  6. 实时调度策略永远不可能被优先级低的进程抢占成功。

(7)调度器相关的系统调用

sched函数组
在这里插入图片描述
优先级函数
在这里插入图片描述
在这里插入图片描述

五、系统调用

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

1、与内核通信

系统调用在用户进程和硬件设备之间添加了一个中间层,这个中间层的作用有:

  1. 为用户进程提供硬件的抽象访问接口(一切皆文件)
  2. 保证系统的稳定,裁决访问
    系统调用是用户空间访问内核的唯一手段,也是唯一的内核访问的合法入口

2、使用API而不是直接使用系统调用

使用C口提供的API,API内部进行系统调用与内核交互。
使用API可以提高程序的可移植性。
C库提供相同的API,在不同架构上API内部实现各不相同。

3、系统调用

  1. 通过C库API访问系统调用
  2. 系统调用通常返回一个long型,表示调用结果 负值表示失败,并将结果写入C的全局errno
  3. 必须保证系统调用是可重入的,应为不同的进程可能会调用同一个系统调用。
  4. 定义系统调用,getpid的系统调用的实现
    在这里插入图片描述
    SYSCALL_DEFINE0 是一个宏,原型是这样的
    在这里插入图片描述
    asmlinkage 是一个编译指令,它要求从栈中提取该函数的参数,(cortex-m3/4 执行一个函数时 他的寄存器中是啥内容?)
    所有系统调用都要用asmlinkage 修饰
    为了兼容32和64位机,系统调用在内核返回long型,在用户返回int型。
    所有系统调用以 sys_XXX 开头。

(1)系统调用号

  1. 每个系统调用有一个系统调用号,内核记录系统调用号表,存储在sys_call_table中。(感觉像stm32的中断号和中断向量表),从0 开始。
  2. 系统调用号是每个体系结构的ABI(应用程序二进制接口)
  3. 系统调用号必须定义在**<asm/unistd.h>**中
  4. 系统调用必须被编译进内核,编译之前放进 kernel/ 下的特定文件syss.c
    在这里插入图片描述

(2)系统调用过程

1、在用户进程调用API
2、API中调用系统调用
3、通过内核陷入指令产生异常,进入系统调用处理函数。(处于内核态)
4、提取系统调用号参数
5、判断参数有效性、合法性。内核根据系统调用号执行系统调用函数 ==> 这就是所说的内核代替用户执行
6、系统调用函数返回结果
7、返回系统调用处理函数
8、返回用户进程

4、如何实现一个系统调用

(1)<asm/unistd.h> 中添加一个系统调用号

在这里插入图片描述

(2)在系统调用表添加系统调用

(3)实现系统调用函数

问题记录

1、用户进程和内核进程有什么区别?用户进程可以被直接调度吗?是否也存在与用户进程对应绑定的内核进程。

进程 == 单线程

2、实时进程和普通进程有什么区别?如何创建一个实时进程

3、如何理解接口设计—>提供机制而不是策略?

4、cortex-m3/4 执行一个函数时 他的寄存器中是啥内容?

cortex-m3/4寄存器有一下
在这里插入图片描述
在函数执行时
在这里插入图片描述
各个寄存器的作用
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Phi小模型开发教程:用C#开发本地部署AI聊天工具,只需CPU,不需要GPU,3G内存就可以运行,不输GPT-3.5

大家好&#xff0c;我是编程乐趣。 行业诸多大佬一直在说&#xff1a;“‌2025年将是AI应用元年‌”&#xff0c;虽然说大佬的说法不一定对&#xff0c;但AI趋势肯定没错的。 对于我们程序员来说&#xff0c;储备AI应用开发技能&#xff0c;不管对找工作、接项目、创业肯定是…

Android系统开发(一):AOSP 架构全解析:开源拥抱安卓未来

引言 当我们手握智能手机&#xff0c;流畅地滑动屏幕、切换应用、欣赏动画时&#xff0c;背后其实藏着一套庞大且精密的开源系统——Android AOSP&#xff08;Android Open Source Project&#xff09;。这套系统不仅是所有安卓设备的根基&#xff0c;也是系统开发者的终极 pl…

【机器学习实战入门】基于深度学习的乳腺癌分类

什么是深度学习&#xff1f; 作为对机器学习的一种深入方法&#xff0c;深度学习受到了人类大脑和其生物神经网络的启发。它包括深层神经网络、递归神经网络、卷积神经网络和深度信念网络等架构&#xff0c;这些架构由多层组成&#xff0c;数据必须通过这些层才能最终产生输出。…

ASP .NET Core 学习(.NET9)配置接口访问路由

新创建的 ASP .NET Core Web API项目中Controller进行请求时&#xff0c;是在地址:端口/Controller名称进行访问的&#xff0c;这个时候Controller的默认路由配置如下 访问接口时&#xff0c;是通过请求方法&#xff08;GET、Post、Put、Delete&#xff09;进行接口区分的&…

TextButton组件的功能与用法

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了CircleAvatar Widget,本章回中将介绍Button这种Widget&#xff0c;闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 关于Button相信大家都很熟悉&#xff0c;也就是我们常用的按钮。用户按下按钮后…

3. 后端验证前端Token

书接上回&#xff0c;后端将token返回给前端&#xff0c;前端存入cookie&#xff0c;每次前端给后端发送请求&#xff0c;后端是如何验证的。 若依是用过滤器来实现对请求的验证&#xff0c;过滤器的简单理解是每次发送请求的时候先发送给过滤器执行逻辑判断以及处理&#xff0…

RabbitMQ-消息可靠性以及延迟消息

目录 消息丢失 一、发送者的可靠性 1.1 生产者重试机制 1.2 生产者确认机制 1.3 实现生产者确认 &#xff08;1&#xff09;开启生产者确认 &#xff08;2&#xff09;定义ReturnCallback &#xff08;3&#xff09;定义ConfirmCallback 二、MQ的持久化 2.1 数据持久…

大文件上传服务-后端V1V2

文章目录 大文件上传概述:minio分布式文件存储使用的一些技术校验MD5的逻辑 uploadV1 版本 1uploadv2 版本 2 大文件上传概述: 之前项目做了一个文件上传的功能,最近看到有面试会具体的问这个上传功能的细节&#xff0c;把之前做的项目拿过来总结一下&#xff0c;自己写的一个…

Web小练习01

#制作简易网页# 本章包括主页、注册页面、登陆页面 主页 1.1主页代码如下 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1…

SpringBoot多级配置文件

1.问题先导 有这样的场景&#xff0c;我们开发完毕后需要测试人员进行测试&#xff0c;由于测试环境和开发环境的很多配置都不相同&#xff0c;所以测试人员在运 行我们的工程时需要临时修改很多配置&#xff0c;如下 java –jar springboot.jar –-spring.profiles.activete…

2,Linux文件基本属性(基于Ubuntu示例进行讲解)

创建文件 创建文件touch命令创建文件夹mkdir命令写入文件内容echo命令 # 创建文件夹&#xff0c;文件夹名称为demo_001 mkdir demo_001# 创建文件&#xff0c;文件名称为demo_file_001.py touch demo_file_001.py# 写入内容到文件中&#xff0c;例如写入print("hello wo…

蓝桥杯训练—斐波那契数列

文章目录 一、题目二、解析三、代码 一、题目 求100以内的斐波那契数列 斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列 &#xff0c;因数学家莱昂纳多斐波那契&#xff08;Leonardo Fibonacci&#xff09;以兔子繁殖为例子而引入&…

nginx 配置防爬虫

今天早上查看服务器&#xff0c;发现昨天发布的一个在线解析充电桩协议的网页工具有大量的访问记录&#xff0c;应该是爬虫在爬api接口数据。该工具api接口后台用的是python写的&#xff0c;和大多数项目一样也采用nginx反向代理&#xff0c;由于采用nginx&#xff0c;可以利用…

Mockito+PowerMock+Junit单元测试

一、单元测试用途 1、日常开发团队要求规范&#xff0c;需要对开发需求代码进行单元测试并要求行覆盖率达到要求&#xff0c;DevOps流水线也会开设相关门禁阀值阻断代码提交&#xff0c;一般新增代码行覆盖率80%左右。 二、Mock测试介绍 1、Mock是为了解决不同的单元之间由于…

左神算法基础提升--3

文章目录 Manacher 算法经典算法Manacher算法原理 单调栈或单调队列 Manacher 算法 经典算法 在每学习Manacher算法之前我们可能会使用一种比较经典暴力的算法&#xff1a;遍历str字符串&#xff0c;将字符串中的每个字符作为对称点&#xff0c;向两边扩散找到回文字段&#x…

Android系统开发(八):从麦克风到扬声器,音频HAL框架的奇妙之旅

引言&#xff1a;音浪太强&#xff0c;我稳如老 HAL&#xff01; 如果有一天你的耳机里传来的不是《咱们屯里人》&#xff0c;而是金属碰撞般的杂音&#xff0c;那你可能已经感受到了 Android 音频硬件抽象层 (HAL) 出问题的后果&#xff01;在 Android 音频架构中&#xff0c…

OA-CNN:用于 3D 语义分割的全自适应稀疏 CNN

大家读完觉得有帮助记得及时关注和点赞&#xff01;&#xff01;&#xff01; 1介绍 2相关工作 基于点的学习。 基于 CNN 的学习。 动态卷积。 3全能自适应 3D 稀疏 CNN 3.1空间适应性感受野 赋予动机。 体素网格。 金字塔网格分区。 Adaptive 聚合器。 3.2自适应关…

聊聊如何实现Android 放大镜效果

一、前言 很久没有更新Android 原生技术内容了&#xff0c;前些年一直在做跨端方向开发&#xff0c;最近换工作用重新回到原生技术&#xff0c;又回到了熟悉但有些生疏的环境&#xff0c;真是感慨万分。 近期也是因为准备做地图交互相关的需求&#xff0c;功能非常复杂&#x…

Linux 操作二:文件映射与文件状态

Linux 操作二&#xff1a;文件映射与文件状态查询 文件映射 ​ mmap是一种内存映射文件的方法&#xff0c;即将一个文件或者其它对象映射到进程的地址空间&#xff0c;实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后&#xff0c;进程…

论文阅读:CosAE Learnable Fourier Series for Image Restoration

这是 2024 NeurIPS 上发表的一篇文章&#xff0c;介绍了一种新型的基于傅里叶级数的通用编码器。 Abstract 本文介绍了余弦自动编码器&#xff08;Cosine Autoencoder, CosAE&#xff09;&#xff0c;这是一种新颖的通用自动编码器&#xff0c;它将经典傅里叶级数与前馈神经网…