【Linux之升华篇】Linux内核锁、用户模式与内核模式、用户进程通讯方式

文章目录

  • Linux 中主要几种内核锁
  • Linux 中的用户模式和内核模式
  • 申请大块内核内存
  • 用户进程间通信的几种方式
  • 通过伙伴系统申请内核内存的函数
  • Linux 虚拟文件系统的关键数据结构
  • 对文件或设备的操作函数的数据结构
  • Linux 中的文件
  • 创建进程的系统调用
  • 调用 schedule()进行进程切换的方式
  • Linux 调度程序是根据进程的动态优先级还是静态优先级来调度进程的?
  • 进程调度的核心数据结构
  • 加载、卸载模块
  • 模块和应用程序分别运行在什么空间
  • Linux 中的浮点运算
  • 模块程序能否使用可链接的库函数
  • TLB 中缓存的内容
  • Linux 中的几种设备
  • 字符设备驱动程序的关键数据结构是哪个
  • 设备驱动程序包括哪些功能函数
  • 如何唯一标识一个设备
  • Linux 现系统调用

Linux 中主要几种内核锁

Linux 的同步机制从 2.0 到 2.6 以来不断发展完善。从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。这些同步机制的发展伴随 Linux 从单处理器到对称多处理器的过渡;伴随着从非抢占内核到抢占内核的过度。Linux 的锁机制越来越有效,也越来越复杂。Linux 的内核锁主要是自旋锁和信号量。自旋锁最多只能被一个可执行线程持有,如果一个执行线程试图请求一个已被争用(已经被持有)的自旋锁,那么这个线程就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的执行线程便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的执行线程同时进入临界区。
Linux 中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。Linux 内核中的同步机制:原子操作、信号量、读写信号量和自旋锁的 API,另外一些同步机制,包括大内核锁、读写锁、大读者锁、RCU (Read-Copy Update,顾名思义就是读-拷贝修改),和顺序锁。

Linux 中的用户模式和内核模式

MS-DOS 等操作系统在单一的 CPU 模式下运行,但是一些类 Unix 的操作系统则使用了双模式,可以有效地实现时间共享。在 Linux 机器上,CPU 要么处于受信任的内核模式,要么处于受限制的用户模式。除了内核本身处于内核模式以外,所有的用户进程都运行在用户模式之中。
内核模式的代码可以无限制地访问所有处理器指令集以及全部内存和 I/O 空间。如果用户模式的进程要享有此特权,它必须通过系统调用向设备驱动程序或其他内核模式的代码发出请求。另外,用户模式的代码允许发生缺页,而内核模式的代码则不允许。
在 2.4 和更早的内核中,仅仅用户模式的进程可以被上下文切换出局,由其他进程抢占。除非发生以下两种情况,否则内核模式代码可以一直独占 CPU:(1) 它自愿放弃 CPU;(2) 发生中断或异常。2.6 内核引入了内核抢占,大多数内核模式的代码也可以被抢占。

申请大块内核内存

在 Linux 内核环境下,申请大块内存的成功率随着系统运行时间的增加而减少,虽然可以通过vmalloc 系列调用申请物理不连续但虚拟地址连续的内存,但毕竟其使用效率不高且在 32 位系统上 vmalloc 的内存地址空间有限。所以,一般的建议是在系统启动阶段申请大块内存,但是其成功的概率也只是比较高而已,而不是 100%。如果程序真的比较在意这个申请的成功与否,只能退用“启动内存”

(Boot Memory)。下面就是申请并导出启动内存的一段示例代码:
void* x_bootmem = NULL;
EXPORT_SYMBOL(x_bootmem);
unsigned long x_bootmem_size = 0;
EXPORT_SYMBOL(x_bootmem_size);
static int __init x_bootmem_setup(char *str)
{
x_bootmem_size = memparse(str, &str);
x_bootmem = alloc_bootmem(x_bootmem_size);
printk(“Reserved %lu bytes from %p for x\n”, x_bootmem_size, x_bootmem);
return 1;
}
__setup(“x-bootmem=”, x_bootmem_setup);

可见其应用还是比较简单的,不过利弊总是共生的,它不可避免也有其自身的限制:内存申请代码只能连接进内核,不能在模块中使用。
被申请的内存不会被页分配器和 slab 分配器所使用和统计,也就是说它处于系统的可见内存之外,即使在将来的某个地方你释放了它。
一般用户只会申请一大块内存,如果需要在其上实现复杂的内存管理则需要自己实现。
在不允许内存分配失败的场合,通过启动内存预留内存空间将是我们唯一的选择。

用户进程间通信的几种方式

(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的
功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令 mkfifo 或系统调用 mkfifo 来创建。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux 除了支持 Unix 早期信号语义函数 sigal外,还支持语义符合 Posix.1 标准的信号函数 sigaction(实际上,该函数是基于 BSD 的,BSD为了实现可靠信号机制,又能够统一对外接口,用 sigaction 函数重新实现了 signal 函数)。
(4)消息(Message)队列:消息队列是消息的链接表,包括 Posix 消息队列 system V 消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用 IPC 形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(6)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
(7)套接字(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由 Unix 系统的 BSD 分支开发出来的,但现在一般可以移植到其它类 Unix 系统上:Linux 和System V 的变种都支持套接字。

通过伙伴系统申请内核内存的函数

在物理页面管理上实现了基于区的伙伴系统(zone based buddy system)。对不同区的内存使用单独的伙伴系统(buddy system)管理,而且独立地监控空闲页。相应接口alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。

Linux 虚拟文件系统的关键数据结构

struct super_block,struct inode,struct file,struct dentry;

对文件或设备的操作函数的数据结构

struct file_operations

Linux 中的文件

执行文件,普通文件,目录文件,链接文件和设备文件,管道文件。

创建进程的系统调用

clone(),fork(),vfork();系统调用服务例程:sys_clone,sys_fork,sys_vfork;

调用 schedule()进行进程切换的方式

1.系统调用 do_fork();
2.定时中断 do_timer();
3.唤醒进程 wake_up_process
4.改变进程的调度策略 setscheduler();
5.系统调用礼让 sys_sched_yield();

Linux 调度程序是根据进程的动态优先级还是静态优先级来调度进程的?

Liunx 调度程序是根据根据进程的动态优先级来调度进程的,但是动态优先级又是根据静态优先级根据算法计算出来的,两者是两个相关联的值。因为高优先级的进程总是比低优先级的进程先被调度,为防止多个高优先级的进程占用 CPU 资源,导致其他进程不能占有 CPU,所以引用动态优先级概念

进程调度的核心数据结构

struct runqueue

加载、卸载模块

insmod 加载,rmmod 卸载

模块和应用程序分别运行在什么空间

模块运行在内核空间,应用程序运行在用户空间

Linux 中的浮点运算

应用程序实现,Linux 中的浮点运算是利用数学库函数实现的,库函数能够被应用程序链接后调用,不能被内核链接调用。这些运算是在应用程序中运行的,然后再把结果反馈给系统。
Linux 内核如果一定要进行浮点运算,需要在建立内核时选上 math-emu,使用软件模拟计算浮点运算,据说这样做的代价有两个:用户在安装驱动时需要重建内核,可能会影响到其他的应用程序,使得这些应用程序在做浮点运算的时候也使用 math-emu,大大的降低了效率。

模块程序能否使用可链接的库函数

模块程序运行在内核空间,不能链接库函数。

TLB 中缓存的内容

TLB,页表缓存,当线性地址被第一次转换成物理地址的时候,将线性地址和物理地址的对应放到 TLB 中,用于下次访问这个线性地址时,加快转换速度。

Linux 中的几种设备

字符设备和块设备。网卡是例外,他不直接与设备文件对应,mknod 系统调用用来创建设备文件。

字符设备驱动程序的关键数据结构是哪个

字符设备描述符 struct cdev,cdev_alloc()用于动态的分配 cdev 描述符,cdev_add()用于注册一个 cdev 描述符,cdev 包含一个 struct kobject 类型的数据结构它是核心的数据结构

设备驱动程序包括哪些功能函数

open(),read(),write(),llseek(),realse();

如何唯一标识一个设备

Linux 使用一个设备编号来唯一的标示一个设备,设备编号分为:主设备号和次设备号,一般主设备号标示设备对应的驱动程序,次设备号对应设备文件指向的设备,在内核中使用 dev_t 来表示设备编号,一般它是 32 位长度,其中 12 位用于表示主设备号,20 位用于表示次设备号,利用 MKDEV(int major,int minor);用于生成一个 dev_t 类型的对象。

Linux 现系统调用

靠软件中断实现的,首先,用户程序为系统调用设置参数,其中一个编号是系统调用编号,参数设置完成后,程序执行系统调用指令,x86 上的软中断是有 int 产生的,这个指令会导致一个异常,产生一个事件,这个事件会导致处理器跳转到内核态并跳转到一个新的地址。并开始处理那里的异常处理程序,此时的异常处理就是系统调用程序。
Linux 软中断和工作队列的作用是什么?
Linux 中的软中断和工作队列是中断处理。
1.软中断一般是“可延迟函数”的总称,它不能睡眠,不能阻塞,它处于中断上下文,不能进城切换,软中断不能被自己打断,只能被硬件中断打断(上半部),可以并发的运行在多个 CPU 上。所以软中断必须设计成可重入的函数,因此也需要自旋锁来保护其数据结构。
2.工作队列中的函数处在进程上下文中,它可以睡眠,也能被阻塞,能够在不同的进程间切换。已完成不同的工作。
可延迟函数和工作队列都不能访问用户的进程空间,可延时函数在执行时不可能有任何正在运行的进程,工作队列的函数有内核进程执行,他不能访问用户空间地址。

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

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

相关文章

阿里云域名备案流程

阿里云域名备案流程大致可以分为以下几个步骤,这些信息综合了不同来源的最新流程说明,确保了流程的时效性和准确性: UP贴心的附带了链接: 首次备案流程:ICP首次备案_备案(ICP Filing)-阿里云帮助中心 (aliyun.com) …

政安晨:【Keras机器学习示例演绎】(四十三)—— 使用 KerasNLP 实现英语到西班牙语的翻译

目录 简介 设置 下载数据 解析数据 数据标记化 格式化数据集 建立模型 训练我们的模型 解码测试句子(定性分析) 解码测试句子(定性分析) 评估我们的模型(定量分析) 10 个轮次后,得分…

事务-MYSQL

目录 1.事务操作演示 2.事务四大特性ACID 3.并发事务问题 4. 并发事务演示及隔离级别​编辑​编辑​编辑​编辑​编辑​编辑​编辑 1.事务操作演示 默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。 方式二 2.事务四大特性ACID 原子…

多线程-线程安全

目录 线程安全问题 加锁(synchronized) synchronized 使用方法 synchronized的其他使用方法 synchronized 重要特性(可重入的) 死锁的问题 对 2> 提出问题 对 3> 提出问题 解决死锁 对 2> 进行解答 对4> 进行解答 volatile 关键字 wait 和 notify (重要…

LeetCode例题讲解:844.比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。 注意:如果对空文本输入退格字符,文本继续为空。 示例 1: 输入:s "ab#c&qu…

AtCoder Beginner Contest 310 D题 Peaceful Teams

D题:Peaceful Teams 标签:深搜 d f s dfs dfs、状压 d p dp dp题意:给定 n n n个运动员要分成 t t t只队伍(每只队伍至少 1 1 1人),并且给定 m m m个矛盾关系 a i a_i ai​运动员和 b i b_i bi​运动员&am…

llm.c的Makefile

源码 CC ? clang CFLAGS -Ofast -Wno-unused-result -Wno-ignored-pragmas -Wno-unknown-attributes LDFLAGS LDLIBS -lm INCLUDES CFLAGS_COND -marchnative# Find nvcc SHELL_UNAME $(shell uname) REMOVE_FILES rm -f OUTPUT_FILE -o $ CUDA_OUTPUT_FILE -o $# N…

vue.js 介绍

Vue.js 是一种流行的前端 JavaScript 框架,主要用于构建网页和单页应用程序(SPA)。它由前谷歌工程师尤雨溪(Evan You)于2014年开发。Vue.js 设计目标是通过简单的 API 提供高效的数据绑定和灵活的组件系统,…

springboot项目打包部署

springboot打包的前提条件jdk必须17以后不然本地运行不来(我用的jdk是22) 查看自己电脑jdk版本可以参考(完美解决Windows10下-更换JDK环境变量后,在cmd下执行仍java -version然出现原来版本的JDK的问题-CSDN博客) 1、…

六级翻译笔记

理解加表达 除了专有名词不能自己理解翻译,其它都可以 时态一般唯一 题目里出现有翻译为 客观存在: there be 单词结尾加er和ee的区别:er是主动,ee是被动 中文句子没有被动,也可以英文翻译为被动 中文的状语可以不是…

【无标获取S4与ECC的具体差异的方法题】

首先我们需要对ECC vs S4的差异这个课题要有一个深刻的理解,这不是一个简单并能准确说清楚的课题。 我们需要结合实际项目的具体情况去回答这个问题,因为这个问题本身是没有标准答案的。 首先要了解SAP本身ERP产品线的发展概况,其次我们要…

GitHub操作

远程库-GitHub GitHub网址 GitHub是全球最大的远程库 1. 创建远程库 2. 远程仓库操作 2.1 创建远程仓库别名 git remote -v 查看当前所有远程库地址别名 git remote add 别名 远程地址 设置远程库地址别名 案例操作 起一个别名会出现两个别名,是因为既可以拉取…

Set和Map有什么相同和不同之处?

Set 和 Map 都是 ES6(ECMAScript 2015)中引入的两种新的数据结构,它们都属于集合类型,但各自有各自的特点和用法。 相同点: 键的唯一性:无论是 Set 还是 Map,它们的键(在 Set 中&a…

若依前端分离版-APP(UNI APP)表单添加验证

1.在page页面中onReady事件添加如下代码 onReady() {this.$refs.form.setRules(this.rules)}, 2.在data中添加ruels这个对象 rules: {nickName: {rules: [{required: true,errorMessage: 用户昵称不能为空}]},phonenumber: {rules: [{required: true,errorMessage: 手机号码不…

Rust :如何累计时间长度?

在Rust中,如果你想要记录累计时间,通常可以使用标准库中的std::time::Duration类型。Duration类型表示一个时间段,并且它可以很容易地进行加法和减法操作,从而用于累计时间。 下面是一个简单的例子,展示了如何使用Dur…

C语言 | Leetcode C语言题解之第84题柱状图中最大的矩形

题目&#xff1a; 题解&#xff1a; int largestRectangleArea(int* heights, int heightsSize) {int st[heightsSize];int p[2];p[0]-1,p[1]heightsSize;int size0,result0;st[size]0;for(int i1;i<heightsSize;i){ while(size!0&&heights[i]<heights[st[size-1…

动态规划解决回文子串问题

前言&#xff1a; 回文串相关问题在我们的算法题中算是老生常谈&#xff0c;本文主要介绍如何使用动态规划的思路去解决回文串系列问题。 总体思路&#xff1a; 能够将所有的子串是否是回文的信息&#xff0c;存储在二维dp表中。有了这个dp表&#xff0c;就可以将hard难度转…

Vue3实战笔记(07)— Axios进阶与提高

文章目录 前言一、创建自定义配置的实例二、掌握返回的结果结构三、拦截器相关用法四、异常处理相关五、取消请求的方式总结 前言 书接上文&#xff0c;目标对Axios的更多功能和特性熟练与提高。 一、创建自定义配置的实例 axios可以创建自定义配置的实例&#xff0c;可以试试…

密钥变更检查导致VScode远程SSH时无法连接服务器

报错 使用vscode的Remote - SSH插件远程连接不同服务器时报错如下 [11:42:51.784] Log Level: 2 [11:42:51.792] SSH Resolver called for "ssh-remote27.23.24.103", attempt 1 [11:42:51.793] "remote.SSH.useLocalServer": false [11:42:51.793] &quo…

使用vue3以及原生input实现一个可复用的组件(包括各种数组类型,手机号类型,小数类型)

看标题要实现可复用 那我就注册到全局组件里面 在component.ts //注册全局公共组件 import MxInput from /components/common/MxInput.vue const commonComponents {install(Vue) {Vue.component(MxInput, MxInput)} }; export default commonComponents;子组件&#xff1a;…