关于linux内核模块:SCE-内核态接口使用手册

1.介绍SCE部件作为飞腾平台的平安组件,提供了对称算法加速器(SCA)、哈希算法加速器(HASH)、非对称算法加速器(ACA)和真随机数生成器(TRNG)。 用户通过Linux Kernel Crypto API框架实现内核对各种算法驱动的反对,目前内核态已实现SCA、HASH、TRNG反对的算法驱动。通过装置SCE内核层驱动可查看已反对的算法驱动,利用开发者可通过相应的内核态接口实现对算法模块的调用。 2.装置与测试2.1硬件及零碎要求硬件要求如下表所示。 我的项目阐明CPU飞腾平台CPU已支持系统1、Ubuntu 22.04(kernel 4.19.0)存储无要求内存无要求2.2软件目录架构软件目录架构如图所示: 1.src文件夹:驱动模块源码。2.include文件夹:驱动模块头文件。3.test文件夹:内核层驱动测试代码。 2.3内核驱动算法概述目前反对的内核态驱动算法如下表所示。 加速器算法算法名驱动名对称引擎SM4ecb(sm4)cbc(sm4)ctr(sm4)ofb(sm4)ecb(sm4)-phytiumcbc(sm4)phytiumctr(sm4)-phytiumofb(sm4)-phytium对称引擎AESecb(aes)cbc(aes)ctr(aes)ofb(aes)ecb(aes)-phytiumcbc(aes)phytiumctr(aes)-phytiumofb(aes)-phytium对称引擎DESecb(des)cbc(des)ctr(des)ofb(des)ecb(des3_ede)cbc(des3_ede)ctr(des3_ede)ofb(des3_ede)ecb(aes)-phytiumcbc(aes)phytiumctr(aes)-phytiumofb(aes)-phytiumecb(des3_ede)-phytiumcbc(des3_ede)-phytiumctr(des3_ede)-phytiumofb(des3_ede)-phytium哈希引擎DESecb(des)cbc(des)ctr(des)ofb(des)ecb(des3_ede)cbc(des3_ede)ctr(des3_ede)ofb(des3_ede)ecb(des)-phytiumcbc(des)-phytiumctr(des)-phytiumofb(des)-phytiumecb(des3_ede)-phytiumcbc(des3_ede)-phytiumctr(des3_ede)-phytiumofb(des3_ede)-phytium哈希引擎SHAsha1sha224sha256sha384sha512md5hmac(sha1)hmac(sha224)hmac(sha256)hmac(sha384)hmac(sha512)hmac(md5)sha1-phytiumsha224-phytiumsha256-phytiumsha384-phytiumsha512-phytiummd5-phytiumhmac(sha1)-phytiumhmac(sha224)-phytiumhmac(sha256)-phytiumhmac(sha384)-phytiumhmac(sha512)-phytiumhmac(md5)-phytium哈希引擎SM3sm3hmac(sm3)sm3-phytiumhmac(sm3)-phytium真随机数生成器TRNGTRNGtrng-phytium2.4内核层编译、装置与测试1.SCE内核层内核驱动编译装置步骤 进入驱动代码目录cd driver# 编译驱动模块make# 加载驱动模块sudo insmod phytium_sce.ko# 抉择应用内核层驱动模块# 驱动模块反对用户态和内核态切换# 通过操作/proc/sce_dir/sce_work_state管制# 输出1启用内核态模块,输出2启用用户态模块,输出0敞开所有模块sudo echo 1 > /proc/sce_dir/sce_work_state# 查看驱动模块以后模式cat /proc/sce_dir/sce_work_state# 查看内核反对的SCE算法驱动cat /proc/crypto | grep phytium2.SCE内核态接口编译装置 #进入内核态测试代码目录cd driver/test# 编译测试模块make# 在执行mtest.ko前必须先加载好内核驱动模块# 执行mtest.ko时通过传入参数可反对对不同算法进行功能性测试# 倡议关上两个终端窗口A和B,其中可在A终端输出测试命令,B终端执行命令“sudo dmesg -w”sudo insmod mtest.ko #当在终端A执行该命令之后,可在终端B查到到内核打印信息,其中表明须要传入的参数信息#示例命令,对hash进行功能测试sudo insmod mtest.ko alg=sm3 mode=hash3 SCE内核态API阐明该章节介绍SCE内核态API接口,接口的应用示例可浏览参考kernel/test目录下的测试用例。 3.1哈希算法3.1.1调配哈希算法对象函数原型struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type, u32 mask)函数性能调配一个新创建的异步哈希算法实例输出阐明alg_name - 算法名type - 算法类型mask - 算法类型屏蔽字输入阐明无返回值阐明新创建的异步哈希算法对象应用阐明 注意事项hash算法能够是同步形式实现或异步形式实现,但算法利用不关注hash算法的实现形式,而是关注hash算法提供的算法接口。为实现对立治理,加密框架默认hash算法的实现形式为异步形式,将哈希算法的内部接口对立定义为异步哈希算法接口3.1.2调配哈希算法数据申请对象函数原型struct ahash_request *ahash_request_alloc(struct crypto_ahash *tfm, gfp_t gfp)函数性能调配申请数据结构输出阐明tfm - 算法实例gfp - API调用传递给kmalloc的内存调配标记输入阐明无返回值阐明胜利时返回调配的申请句柄,如果内存不足则返回NULL应用阐明 注意事项若为同步调用的形式,则不须要调配创立req对象3.1.3设置异步回调函数原型void ahash_request_set_callback(struct ahash_request *req, u32 flags,crypto_completion_t compl, void *data)函数性能用于设置加解密实现后须要调用的回调函数输出阐明req - 申请句柄flags -标记位,指定为0或ORingcompl -注册到申请句柄的回调函数指针data - 指向内核加密API不应用的内存输入阐明无返回值阐明无应用阐明 注意事项 3.1.4设置密钥函数原型int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen)函数性能设置密钥输出阐明tfm - 算法实例key - 密钥数据keylen - 密钥数据长度输入阐明无返回值阐明胜利时返回调配的申请句柄,如果内存不足则返回NULL应用阐明 注意事项 3.1.5设置数据函数原型void ahash_request_set_crypt(struct ahash_request *req, struct scatterlist *src, u8 *result, unsigned int nbytes)函数性能设置数据内存输出阐明req - 申请句柄src - 源扩散/收集列表result - 由音讯摘要填充的缓冲区nbytes - 从@src解决的字节数输入阐明无返回值阐明无应用阐明 注意事项 3.1.6性能接口函数原型int crypto_ahash_init(struct ahash_request *req)int crypto_ahash_digest(struct ahash_request *req)int crypto_ahash_update(struct ahash_request *req)int crypto_ahash_finup(struct ahash_request *req)int crypto_ahash_final(struct ahash_request *req)函数性能init:初始化音讯摘要digest:计算缓冲区的音讯摘要update:向音讯摘要中增加数据以进行解决finup:更新和实现音讯摘要final:计算音讯摘要输出阐明req - ahash_request句柄输入阐明无返回值阐明胜利计算音讯摘要返回0,非0为 失败应用阐明hash算法最终摘要值生成接口能够有多种调用形式,如crypto_ahash_digest示意在该接口中会实现生成摘要相干的所有流程。当然该操作也可拆分为init、update、final或init、update、finup类型的步骤,步骤拆分当前就能够反对在init之后执行屡次update,以间断为hash操作提供数据,并在数据更新实现后调用final操作获取所有数据的最终hash值注意事项 3.1.7开释req资源函数原型void ahash_request_free(struct ahash_request *req)函数性能开释req资源输出阐明req - ahash_request句柄输入阐明无返回值阐明无应用阐明注意事项3.1.8开释tfm资源函数原型void crypto_free_ahash(struct crypto_ahash *tfm)函数性能开释tfm资源输出阐明tfm -算法实例输入阐明无返回值阐明无应用阐明 注意事项 3.2对称算法3.2.1调配对称算法对象函数原型struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, u32 type, u32 mask)函数性能调配一个新创建的对称算法实例输出阐明alg_name - 算法名type - 算法类型mask - 算法类型屏蔽字输入阐明无返回值阐明新创建的算法实例应用阐明 注意事项 3.2.2调配对称算法数据申请对象函数原型struct skcipher_request *skcipher_request_alloc(struct crypto_skcipher *tfm, gfp_t gfp)函数性能调配req输出阐明tfm - 算法实例gfp - API调用传递给kmalloc的内存调配标记输入阐明无返回值阐明胜利时返回调配的申请句柄,如果内存不足则返回NULL应用阐明 注意事项 3.2.3设置异步回调函数原型void skcipher_request_set_callback(struct skcipher_request *req, u32 flags, crypto_completion_t compl, void *data)函数性能用于设置加解密实现后须要调用的回调函数输出阐明req - 申请句柄flags -标记位,指定为0或ORingcompl -注册到申请句柄的回调函数指针data - 指向内核加密API不应用的内存输入阐明无返回值阐明无应用阐明 注意事项 3.2.4设置密钥函数原型int crypto_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen)函数性能设置密钥输出阐明tfm - 算法实例key - 密钥数据keylen - 密钥数据长度输入阐明无返回值阐明胜利时返回调配的申请句柄,如果内存不足则返回NULL应用阐明 注意事项 3.2.5设置数据函数原型void skcipher_request_set_crypt(struct skcipher_request *req, struct scatterlist *src, struct scatterlist *dst, unsigned int cryptlen, void *iv)函数性能设置数据内存输出阐明req - 申请句柄src - 源扩散/收集列表dst - 指标扩散/收集列表cryptlen - 从@src解决的字节数iv - IV数据,必须合乎crypto_skcipher_ivsize定义的IV大小输入阐明无返回值阐明无应用阐明 注意事项 3.2.6加密函数原型int crypto_skcipher_encrypt(struct skcipher_request *req)函数性能加密流程输出阐明req - 申请句柄输入阐明无返回值阐明胜利加密返回0,非0为失败应用阐明 注意事项 3.2.7解密函数原型int crypto_skcipher_decrypt(struct skcipher_request *req)函数性能解密流程输出阐明req - 申请句柄输入阐明无返回值阐明胜利解密返回0,非0为失败应用阐明 注意事项 3.2.8开释req资源函数原型void skcipher_request_free(struct skcipher_request *req)函数性能开释req资源输出阐明req - 申请句柄输入阐明无返回值阐明无应用阐明 注意事项 3.2.9开释tfm资源函数原型void crypto_free_skcipher(struct crypto_skcipher *tfm)函数性能开释tfm资源输出阐明tfm -算法实例输入阐明无返回值阐明无应用阐明 注意事项 3.3真随机数生成器3.3.1调配真随机数生成器对象函数原型struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)函数性能调配一个新创建的TRNG实例输出阐明alg_name - 算法名type - 算法类型mask - 算法类型屏蔽字输入阐明无返回值阐明新创建的算法实例应用阐明 注意事项 3.3.2获取随机数函数原型int crypto_rng_get_bytes(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen)函数性能获取随机数输出阐明tfm - 算法实例rdata - 保留随机数的输入缓冲区dlen - 输入缓冲区的长度输入阐明无返回值阐明0为胜利,非0为失败应用阐明 注意事项 3.3.3开释tfm资源函数原型void crypto_free_rng(struct crypto_rng *tfm)函数性能开释tfm资源输出阐明tfm -算法实例输入阐明无返回值阐明无应用阐明 注意事项 4 算法应用示例4.1哈希算法应用示例4.1.1定义构造定义多个构造体变量,其中:struct crypto_wait:异步操作期待对象 struct ahash_request:异步操作申请对象struct crypto_ahash:哈希算法对象(上下文)struct scatterlist:用来保留加/解密缓冲区的构造 ...

February 23, 2024 · 4 min · jiezi

关于linux内核模块:Linux实现简单的交互式shell

实现步骤: 接管用户输出命令字符串,拆分命令及参数存储。(自行设计数据存储构造)实现一般命令加载性能3.实现输出、输入重定向的性能 4.实现管道 5.反对多重管道这道题感觉本人能力还没齐全看懂,看了大佬的代码https://blog.csdn.net/xiaoan0... #include <stdio.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>#include <fcntl.h> #define MAXLINE 4096#define MAXPIPE 16#define MAXARG 8 struct { char *argv[MAXARG]; char *in, *out;} cmd[MAXPIPE+1]; int parse(char *buf, int cmdnum){ int n = 0; char *p = buf; cmd[cmdnum].in = cmd[cmdnum].out = NULL; //ls -l -d -a -F > out while (*p != '\0') { if (*p == ' ') { //将字符串中所有的空格,替换成'\0',不便后续拆分字符串 *p++ = '\0'; continue; } if (*p == '<') { *p = '\0'; while (*(++p) == ' '); /* cat < file 解决间断多个空格的状况*/ cmd[cmdnum].in = p; if (*p++ == '\0')//输出重定向<前面没有文件名 return -1; continue; } if (*p == '>') { *p = '\0'; while (*(++p) == ' '); cmd[cmdnum].out = p; if (*p++ == '\0') return -1; continue; } if (*p != ' ' && ((p == buf) || *(p-1) == '\0')) { if (n < MAXARG - 1) { cmd[cmdnum].argv[n++] = p++; //"ls -l -R > file" continue; } else { return -1; } } p++; } if (n == 0) { return -1; } cmd[cmdnum].argv[n] = NULL; return 0;} int main(void){ char buf[MAXLINE]; pid_t pid; int fd, i, j, pfd[MAXPIPE][2], pipe_num, cmd_num; char* curcmd, *nextcmd; while (1) { printf("mysh%% "); if (!fgets(buf, MAXLINE, stdin)) exit(0); // "ls -l\n" if (buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1]='\0'; cmd_num = 0; nextcmd = buf; while ((curcmd = strsep(&nextcmd, "|"))) { if (parse(curcmd, cmd_num++)<0) { cmd_num--; break; } if (cmd_num == MAXPIPE + 1) break; } if (!cmd_num) continue; pipe_num = cmd_num - 1; //依据命令数确定要创立的管道数目 for (i = 0; i < pipe_num; i++) { //创立管道 if (pipe(pfd[i])) { perror("pipe"); exit(1); } } for (i = 0; i < cmd_num; i++) { //管道数目决定创立子过程个数 if ((pid = fork()) == 0) break; } if (pid == 0) { if (pipe_num) { //用户输出的命令中含有管道 if (i == 0) { //第一个创立的子过程 dup2(pfd[0][1], STDOUT_FILENO); close(pfd[0][0]); for (j = 1; j < pipe_num; j++) { //在该子过程执行期间,敞开该过程应用不到的其余管道的读端和写端 close(pfd[j][0]); close(pfd[j][1]); } } else if (i==pipe_num) { //最初一个创立的子过程 dup2(pfd[i-1][0], STDIN_FILENO); close(pfd[i-1][1]); for (j = 0; j < pipe_num-1; j++) { //在该子过程执行期间,敞开该过程不应用的其余管道的读/写端 close(pfd[j][0]); close(pfd[j][1]); } } else { dup2(pfd[i-1][0], STDIN_FILENO); //重定两头过程的规范输出至管道读端 close(pfd[i-1][1]); //close管道写端 dup2(pfd[i][1], STDOUT_FILENO); //重定两头过程的规范输入至管道写端 close(pfd[i][0]); //close管道读端 for (j = 0; j < pipe_num; j++) //敞开不应用的管道读写两端 if (j != i || j != i-1) { close(pfd[j][0]); close(pfd[j][1]); } } } if (cmd[i].in) { /*用户在命令中应用了输出重定向*/ fd = open(cmd[i].in, O_RDONLY); //关上用户指定的重定向文件,只读即可 if (fd != -1) dup2(fd, STDIN_FILENO); //将规范输出重定向给该文件 } if (cmd[i].out) { /*用户在命令中应用了输入重定向*/ fd = open(cmd[i].out, O_WRONLY|O_CREAT|O_TRUNC, 0644); //应用写权限关上用户指定的重定向文件 if (fd != -1) dup2(fd, STDOUT_FILENO); //将规范输入重定向给该文件 } execvp(cmd[i].argv[0], cmd[i].argv); //执行用户输出的命令 fprintf(stderr, "executing %s error.\n", cmd[i].argv[0]); exit(127); } /* parent */ for (i = 0; i < pipe_num; i++) { /*父过程不参加命令执行,敞开其把握的管道两端*/ close(pfd[i][0]); close(pfd[i][1]); } for (i = 0; i < cmd_num; i++) { /*循环回首子过程*/ wait(NULL); } }}第一个函数parse()是用来解决输出格局的,如空格多输出了,重定向符号><与文件之间的书写标准等问题,前面的临时还在思考! ...

February 3, 2022 · 3 min · jiezi

关于linux内核模块:网易数帆内核团队memory-cgroup-泄漏问题的分析与解决

memory cgroup 泄露是 K8s(Kubernetes) 集群中普遍存在的问题,轻则导致节点内存资源缓和,重则导致节点无响应只能重启服务器复原;大多数的开发人员会采纳定期 drop cache 或者敞开内核 kmem accounting 进行躲避。本文基于网易数帆内核团队的实际案例,对 memory cgroup 泄露问题的根因进行剖析,同时提供了一种内核层面修复该问题的计划。 背景运维监控发现局部云主机计算节点,K8s(Kubernetes) 节点都有呈现负载异样冲高的问题,具体表现为零碎运行十分卡,load 继续在 40+,局部的 kworker 线程 cpu 使用率较高或者处于 D 状态,曾经对业务造成了影响,须要剖析具体的起因。 问题定位景象剖析对于 cpu 使用率异样的问题,perf 是必不可少的工具。通过 perf top 察看热点函数,发现内核函数 cache_reap 使用率会间歇性冲高。 打开对应的内核代码,cache_reap 函数实现如下: 不难看出,该函数次要是遍历一个全局的 slab_caches 链表,该链表记录的是零碎上所有的 slab 内存对象相干信息。 通过剖析 slab_caches 变量相干的代码流程发现,每一个 memory cgroup 都会对应一个 memory.kmem.slabinfo 文件。 该文件外面记录的是各个 memory cgroup 组过程申请的 slab 相干信息,同时该 memory cgroup 组的 slab 对象也会被对立增加到全局的 slab_caches 链表中,莫非是因为 slab_caches 链表数据太多,导致遍历工夫比拟长,进而导致 CPU 冲高? slab_caches 链表数据太多,那么前提必定是 memory cgroup 数量要特地多,自然而然也就想到要去统计一下零碎上存在多少个 memory cgroup,但当咱们去统计/sys/fs/cgroup/memory 目录下的 memory cgroup 组的数量时发现也就只有一百个不到的 memory cgroup,每个 memory cgroup 外面 memory.kmem.slabinfo 文件最多也就蕴含几十条记录,所以算起来 slab_caches 链表成员个数最多也不会超过一万个,所以怎么看也不会有问题。 ...

January 10, 2022 · 2 min · jiezi

关于linux内核模块:linux内核精讲-内核学习-视频笔记一

https://www.bilibili.com/vide... 操作系统构造 1 11 1 中断体系结构111 中断实现过程1 过程初始化和创立11P4:14: 22

May 11, 2021 · 1 min · jiezi

关于linux内核模块:Linux-HugePages大内存页-原理与使用

在介绍 HugePages 之前,咱们先来回顾一下 Linux 下 虚拟内存 与 物理内存 之间的关系。 物理内存:也就是装置在计算机中的内存条,比方装置了 2GB 大小的内存条,那么物理内存地址的范畴就是 0 ~ 2GB。虚拟内存:虚构的内存地址。因为 CPU 只能应用物理内存地址,所以须要将虚拟内存地址转换为物理内存地址能力被 CPU 应用,这个转换过程由 MMU(Memory Management Unit,内存治理单元) 来实现。在 32 位的操作系统中,虚拟内存空间大小为 0 ~ 4GB。咱们通过 图1 来形容虚拟内存地址转换成物理内存地址的过程: 如 图1 所示,页表 保留的是虚拟内存地址与物理内存地址的映射关系,MMU 从 页表 中找到虚拟内存地址所映射的物理内存地址,而后把物理内存地址提交给 CPU,这个过程与 Hash 算法类似。 内存映射是以内存页作为单位的,通常状况下,一个内存页的大小为 4KB(如图1所示),所以称为 分页机制。 一、内存映射咱们来看看在 64 位的 Linux 零碎中(英特尔 x64 CPU),虚拟内存地址转换成物理内存地址的过程,如图2: 从图2能够看出,Linux 只应用了 64 位虚拟内存地址的前 48 位(0 ~ 47位),并且 Linux 把这 48 位虚拟内存地址分为 5 个局部,如下: PGD索引:39 ~ 47 位(共9个位),指定在 页全局目录(PGD,Page Global Directory)中的索引。PUD索引:30 ~ 38 位(共9个位),指定在 页下级目录(PUD,Page Upper Directory)中的索引。PMD索引:21 ~ 29 位(共9个位),指定在 页两头目录(PMD,Page Middle Directory)中的索引。PTE索引:12 ~ 20 位(共9个位),指定在 页表(PT,Page Table)中的索引。偏移量:0 ~ 11 位(共12个位),指定在物理内存页中的偏移量。把 图1 中的 页表 分为 4 级:页全局目录、页下级目录、页两头目录 和 页表 目标是为了缩小内存耗费(思考下为什么能够缩小内存耗费)。 ...

April 21, 2021 · 2 min · jiezi

关于linux内核模块:310内核上rmmod失败处理

前几天在一台测试机器上遇到了rmmod失败的景象,通过lsmod能够看到它的援用计数为1。然而我能够确定曾经没有被应用了,所以这应该是一个代码中的bug。从网上能够找到一篇写得十分好的rmmod失败的剖析文章,外面还提供了一段代码,能够编译出一个ko文件,通过加载这个module并且传入有问题的module名字,能够达到强行问题module援用计数的成果,而后就能够应用rmmod命令来删除它了。这篇文章的地址是 https://blog.csdn.net/gatieme...作者也给出了代码的github地址https://github.com/gatieme/LD...可是外面提供的源代码对应的内核版本是4以上的,我的机器是3.10,所以在编译的时候会遇到语法问题 [root@controller22860 force_rmmod]# makeecho /root/force_rmmod/root/force_rmmodecho 3.10.0-957.10.2.el7.x86_643.10.0-957.10.2.el7.x86_64echo /lib/modules/3.10.0-957.10.2.el7.x86_64/build/lib/modules/3.10.0-957.10.2.el7.x86_64/buildmake -C /lib/modules/3.10.0-957.10.2.el7.x86_64/build M=/root/force_rmmod modulesmake[1]: Entering directory `/usr/src/kernels/3.10.0-957.10.2.el7.x86_64' CC [M] /root/force_rmmod/force_rmmod.o/root/force_rmmod/force_rmmod.c: In function ‘force_cleanup_module’:/root/force_rmmod/force_rmmod.c:85:17: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 4 has type ‘long unsigned int’ [-Wformat=] mod->name ,mod->state, module_refcount(mod)); ^In file included from /root/force_rmmod/force_rmmod.c:6:0:/root/force_rmmod/force_rmmod.c:110:46: error: ‘struct module’ has no member named ‘refcnt’ local_set((local_t*)per_cpu_ptr(&(mod->refcnt), cpu), 0); ^include/asm-generic/local.h:29:43: note: in definition of macro ‘local_set’ #define local_set(l,i) atomic_long_set((&(l)->a),(i)) ^include/asm-generic/percpu.h:46:2: note: in expansion of macro ‘__verify_pcpu_ptr’ __verify_pcpu_ptr((__p)); \ ^include/linux/percpu.h:149:31: note: in expansion of macro ‘SHIFT_PERCPU_PTR’ #define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))) ^/root/force_rmmod/force_rmmod.c:110:29: note: in expansion of macro ‘per_cpu_ptr’ local_set((local_t*)per_cpu_ptr(&(mod->refcnt), cpu), 0); ^compilation terminated due to -Wfatal-errors.于是我简略剖析了一下3.10的代码,发现它的 struct module 外面的确是没有定义 refcnt 这个成员的。所以须要批改一下 force_rmmod.c 的代码,我把报错那段改成了上面这样: ...

February 3, 2021 · 1 min · jiezi

关于linux内核模块:LINUX输入子系统使用简介

Linux输出子系统简略上手:1 驱动程序probe接口中 .新建input_dev my_input_dev = input_allocate_device(); .配置反对的事件:依据事件抉择input_dev成员变量,一个设施能够抉择 一个或多个事件类型上报给输出子系统 set_bit(EV_KEY,my_input_dev.evbit) or set_bit(EV_KEY,my_input_dev.keybit) .注册 input_register_device(my_input_dev) 2 中断处理函数中上报:此处模仿按键 .上报按下:input_report_key(gh_input_dev, KEY_POWER, 1); .上报松开:input_report_key(gh_input_dev, KEY_POWER, 0); .同步用于通知input core子系统报告完结: input_sync(gh_input_dev); 参考链接:https://www.cnblogs.com/zhaob...

January 21, 2021 · 1 min · jiezi

关于linux内核模块:Linux-内核及-GNULinux-操作系统的基本体系结构

1. Linux 内核简介内核:在计算机科学中是一个用来管理软件收回的数据 I/O(输出与输入)要求的计算机程序,将这些要求转 译为数据处理的指令并交由中央处理器(CPU)及计算机中其余电子组件进行解决,是古代操作系统中最根本 的局部。它是为泛滥应用程序提供对计算机硬件的平安拜访的一部分软件,这种拜访是无限的,并由内核决定 一个程序在什么时候对某局部硬件操作多长时间。间接对硬件操作是非常复杂的。所以内核通常提供一种硬件 形象的办法,来实现这些操作。通过过程间通信机制及零碎调用,利用过程可间接管制所需的硬件资源(特地 是处理器及 IO 设施)。 2. GNU/Linux 操作系统与 Linux 内核关系咱们通常说的 Linux 实际上指的是内核,即 Linux 内核。而 Linux 的操作系统理论是 GNU/Linux 操作系统, 即应用 Linux 内核的 GNU 零碎。 3.GNU/Linux 操作系统的根本体系结构3.1 用户空间 最下面是用户(或应用程序)空间。 这是用户应用程序执行的中央。用户空间之下是内核空间,Linux 内核正是位于这里。GNU C Library (glibc)也在这里。它提供了连贯内核的零碎调用接口,还提供了在用户空间应用程序和内核之间进行转换 的机制。这点十分重要,因为内核和用户空间的应用程序应用的是不同的爱护地址空间。每个用户空间的过程 都应用本人的虚拟地址空间,而内核则占用独自的地址空间。 3.2 Linux 内核的体系结构 内核是操作系统的外围,具备很多最基本功能,它负责管理系统的过程、内存、设施驱动程序、文件和网络系统,决定着零碎的性能和稳定性。 Linux 内核由如下几局部组成:内存治理、过程治理、文件系统、设施驱动程序和网络接口程序等。 3.2.1 零碎调用接口(System Call Interface 简称 SCI) SCI 层提供了某些机制执行从用户空间到内核的函数调用。这个接口依赖于体系结构,甚至在雷同的处 理器家族内也是如此。 SCI 实际上是一个十分有用的函数调用多路复用和多路合成服务。 在 ./linux/kernel 中您能够找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的局部。 3.2.2 内存治理 ...

November 11, 2020 · 1 min · jiezi

关于linux内核模块:大牛的学习笔记深入理解Linux内核完整版

第一章、绪论1.Unix文件能够是下列类型之一:a.正规文件(regular file)b.目录(directroy)c.符号链(symbolic link)d.块设施文件(block-oriented device file)e.字符设施文件(charactor-oriented device file)f.管道(pipe)命名管道(named pipe)(即FIFO)h.套接字(socket) 2.内核调配给过程的虚拟地址空间由以下内存区域组成:a.程序的可执行代码b.程序的初始化数据c.程序的未初始化数据d.初始程序栈(即用户态栈)e.须要共享的库的可执行代码和数据f.堆(由程序动静申请的内存) 3.设施驱动程序:内核通过设施驱动程序(device driver)与I/O设施打交道。设施驱动程序蕴含在内核中,由管制一个或多个设施的数据结构和函数组成。这些设施包含硬盘、键盘、鼠标和监视器等。通过特定的接口,每个驱动程序与内核中的其余部分(甚至与其余驱动程序)相互作用: 长处:1.能够把特定设施的代码封装在特定的模块中。2.厂商能够不懂内核代码,只晓得接口标准,就能减少新的设施。3.内核以对立的形式看待所有的设施,并且通过雷同的接口拜访这些设施。4.能够把设施驱动程序写成模块,并动静装到内核中,不须要重启零碎,不须要的时候能够卸载模块,以缩小存储在RAM中的内核映像大小。第二章、过程1.过程状态:a.可运行状态b.可中断状态c.不可中断的期待状态d.暂停状态e.僵死状态 第三章、过程调度1.波及过程调度a.I/O范畴(I/O-bound): 频繁地应用I/O设施,并破费很多工夫期待I/O操作的实现。CPU范畴(CPU-bound):须要大量CPU工夫的数值计算应用程序。b.非传统分类: 交互式过程:如命令shell、文本编辑程序及图像应用程序。批处理过程:如编译程序、数据库搜索引擎及科学计算。实时过程:视频和音频应用程序、机器人控制程序及从物理传感器上收集数据的程序。 第四章、内核同步1.内核同步,内核态过程的非抢占性: a.在内核态中运行的过程不会被其余过程取代,除非这个过程被动放弃CPU的控制权b.中断或异样解决能够中断在内核态中运行的过程。然而,在中断处理程序完结时,该过程的内核管制门路被复原c.执行中断或异样解决的内核管制门路只能被执行中断或异样解决的其余内核管制门路所中断2.SMP原子操作 从Intel 80286开始引入lock指令解决这中问题。lock只是一个用于一条汇编指令之前的非凡字节。当管制单元检测到一个lock字节时,就锁定内存总线这样其余处理器就不能存取下一条汇编语言指令的目标操作数所指定的内存单元。只有在这条指令执行实现时总线锁才会被开释。因而,带有lock前缀的读-批改-写指令即便在多处理器环境中也是原子的。 3.内核数据结构进行同步拜访的罕用办法是应用信号量和自旋锁。 第五章、虚构文件系统1.通用文件模型由下列对象类型组成: a.超级块对象(superblock object):寄存已装置文件系统的无关信息。对于基于磁盘的文件系统,这类对象通常对应于寄存在磁盘上的文件系统管制块(filesystem control block)。b.索引节点对象(inode object):寄存对于具体文件的个别信息。对于基于磁盘的文件系统,这类对象通常对应于寄存在磁盘上的文件管制块(file control block)。每个索引节点对象都有一个索引节点号,这个号惟一地标识文件系统中的指定文件。c.文件对象(file object):寄存关上文件与过程之间交互的相干信息。这类信息仅当过程拜访文件期间存在于内核内存中。d.目录项对象(dentry object):寄存目录项与对应文件进行连贯的信息。每个基于磁盘的文件系统都以本人特有的形式将该类信息存在磁盘上。slab调配高速缓存中。e.过程->文件对象->目录项对象->索引节点->(超级块对象)->磁盘文件。2.虚构文件系统,目录项对象属于以下四种状态之一: a.闲暇状态: 还没有被VFS应用,对于德内存区由slab分配器进行治理。b.未应用状态: 该目录项对象以后还没有被内核应用。该对象的援用计数器d_count为NULL。但其d_indoe域只想相干索引节点。为了必要时回收内存,目录项蕴含无效信息,它的内存可能被失落。c.正在应用状态: 该对象被内核应用。d_count的值为负数。目录项蕴含无效的信息,并且不能被抛弃。d.负状态: 与目录项相干的索引节点不复存在,那是因为相应的磁盘索引节点已被删除,d_count域被置NULL。第六章、治理I/O设施1.三类内存地址: a.逻辑地址(CPU外部应用)b.线性地址(CPU外部应用)c.物理地址(CPU从物理上驱动数据总线所用的内存地址)d.总线地址(bus address):除CPU之外的硬件设施驱动数据总线所用的内存地址。2.设施文件(mknod()零碎调用来创立设施文件):用来示意Linux所反对的大部分I/O设施的,除了文件名,每个设施文件都还有三个次要属性。 a.类型(type):块设施或字符设施b.主号(major number):从1到255之间的一个数,用以标识设施的类型,通常,具备雷同主号和雷同类型的所有设施文件共享雷同的文件操作汇合。因为他们是由同一设施驱动程序解决的。c.次号(minor number):在一组主号雷同的设施之间惟一标识特定设施所应用的一个数字。3.没有对应设施文件的I/O设施 比方网卡:网卡把向外发送的数据放入通往近程计算机系统的一条线上,把从近程零碎中承受到的报文装入内核内存。因为没有应用文件系统,所以系统管理员必须建设设施名和网络地址之间的分割。应用程序和网络接口之间的数据通信不是基于规范的无关文件的零碎调用。而是基于socket()、bind()、listen()、accept()和connect()零碎调用。这些零碎调用对网络地址进行操作。这组零碎调用由Unix BSD中首先引入,当初曾经成为网络设备的规范变成模型。 4.VFS对设施文件的解决:设施文件也在零碎的目录数中。 但它们和正规文件及目录有基本的不同。当过程拜访正规文件时,它会通过文件系统拜访磁盘分区的一些数据块;而在过程拜访设施文件时,它只有驱动硬件设施就能够了。VFS的责任是为应用程序暗藏设施文件与正规文件之间的差别。VFS扭转关上的设施文件的缺省文件操作。能够把对设施文件的任一零碎调用转换成对设施相干的函数的调用,而不是对主文件系统对于函数的调用。设施相干的函数对硬件设施进行操作以实现过程所申请的操作。驱动程序:管制I/O设施的一组相干的函数称为设施驱动程序(device driver)。因为每个设施都有一个惟一的I/O控制器,因而也就有惟一的命令和惟一的状态信息,所以大部分I/O设施类型都有本人的驱动程序。5.设施文件调用open()函数执行的操作: a.如果设施驱动程序被蕴含在一个内核模块中,那么把援用计数器的值加1,以便只有把设施文件敞开之后能力卸载这个模块。b.如果设施驱动程序要解决多个同类型的设施,那么就是用次号来抉择适合的驱动程序,如果须要,还要应用专门的文件操作表抉择驱动程序。c.查看该设施是否真正存在,当初是否正在工作。d.如果必要,向硬件设施发送一个初始化命令序列。e.初始化设施驱动程序的数据结构。6.内核反对的级别 a.基本不反对:应用程序应用设当的in和out汇编语言指令间接与设施的I/O端口进行交互。b.最小反对:内核不能设别硬件设施,但能辨认I/O接口。用户程序把I/O接口是为可能读写字符流的程序设施。c.扩大反对:内核设施硬件设施,并解决I/O设施自身,事实上,这种设施可能就没有对应的设施文件。7.拜访I/O设施的地址,能够从/proc/ioports文件中取得。 8.内核对于块设施的反对特点: a.通过VFS提供对立接口b.对磁盘数据进行无效的链接c.为数据提供磁盘高速缓存9.内核基本上把I/O数据传送划分成两类: a.缓冲区I/O操作:所传送的数据保留在缓冲区中,缓冲区是磁盘数据在内核中的一般内存容器。每个缓冲区都和一个特定的块相关联而这个块由一个设施号和一个块号来标识b.页I/O操作:所传输的数据保留在页框中,每个页框蕴含的数据都属于正规文件。因为没有必要把这种数据寄存在相邻的磁盘中。所以就是用文件的索引节点和文件内的偏移量来标识这种数据。次要用于读取正规文件、文件内存映射和替换。10.所谓块(block):就是块设施驱动程序在一次独自操作中所传送的一大块相邻字节。 扇区(sector):扇区是硬件设施传送数据的根本单元。11.块设施驱动程序的两局部: a.高级驱动程序:解决VFS层。b.低级驱动程序:解决硬件设施。第七章、拜访正规文件1.从正规文件读取数据:generic_file_read()函数实现了大部分文件系统的正规文件的read办法。 2.对正规文件进行预读:正规文件的预读须要的算法比物理块的预读须要的算法更简单: a.因为数据是逐页进行读取的,因而预读算法不用思考页内偏移量,只思考所拜访的页在文件外部的地位就能够了。b.以后拜访与上一次拜访不是程序的时,预读就必须从头开始从新执行。c.当过程始终重复地拜访同一页时(该文件只有很少的一部分被应用),应该减慢预读的速度甚至进行执行。d.如果须要,预读算法必须激活低级I/O设施驱动程序来确保新页会被读取。e.内核通过屡次调用一个名为:try_to_read_ahead()的函数来执行预读操作(read ahead operation),一次预读一页。f.对于每个申请页,内核都要调用generic_file_readhead()函数,该函数确定是否要执行预读操作。3.写正规文件:write()零碎调用会波及把数据从调用过程的用户态地址空间中挪动到内核数据结构中,而后再挪动到磁盘上。 文件对象的write办法容许每种文件类型都定义一个专用的写操作。 a.写操作产生时,无效数据是在缓冲区高速缓存中,而不是在页高速缓存中,更确切地说,当write办法批改了文件的任何局部时。与这些局部对应的页高速缓存中的所有页都不再蕴含无效数据。一个过程可能认为本人在读取正确数据,然而却没看到其余过程对这些数据所做的批改。b.所有基于磁盘的文件系统的write办法都要调用update_vm_cache()函数来批改读操作所应用的页高速缓存。c.通过页高速缓存对正规文件执行的写操作,只能用于网络文件系统。文件的write办法是应用generic_file_write()函数实现。4.内存映射:一个线性区能够和基于磁盘的文件系统中的一个文件(或者文件的一部分)相关联。这就是说,内核会把线性区中对一个页中字节的拜访转换成对正规文件中绝对于字节的操作,这种技术成为内存映射。 a.共享的:对线性区中的任何写操作都会批改磁盘上的文件。而且,如果过程对共享内存映射中的一个页进行写,那么这种批改对于其余映射了雷同文件的所有过程来说都是可见的。b.公有的:当过程创立的映射只是为读文件,而不是写文件时才会应用。处于这种目标,公有映射的效率要比共享映射的效率更高。然而公有映射页的意识写操作都会使内核不再映射该文件中的页。一个写操作即不会改磁盘上的文件,对拜访雷同文件的其余过程来说这种扭转也是不可见的。c.应用mmap()零碎调用创立一个新的内存映射。必须指定MAP_SHARED或MAP_PRIVATE标记。第八章、磁盘数据结构1.任何Ext2分区中的第一个块从不受Ext2文件系统的治理,因为这一块是为启动扇区所保留的。Ext2分区的其余部分被分成块组(block group)。 2.块组中的每个块蕴含下列信息之一: a.一个Ext2文件系统超级块的拷贝b.一组块组描述符的拷贝c.一个数据块位图:标识在一组中块的应用和闲暇情况。d.一个索引节点位图e.一组索引节点f.属于文件的一块数据;即一个数据块。3.如果一个块中不蕴含任何有意义的信息,就说这个块是空的。 4.在Ext2文件系统中的所有块组大小雷同并被程序寄存,因而,内核能够从块组的整数索引很容易地失去磁盘中一个块组的地位。 5.超级块与组描述符被复制到每个块组中。只有块组0中所蕴含的超级块和描述符才由内核应用,而其余的超级块和组描述符放弃不变事实上,内核甚至不思考它们。 6./sbin/e2fsck程序对Ext2文件系统的状态执行一致性查看时,就援用寄存在块组0中的超级块和组描述符,而后把它们拷贝到其余所有的块组中。 7.每组之多有8 x b块,b是以字节单位的块大小。 ...

October 24, 2020 · 1 min · jiezi