这里首先给出编写的源代码程序,后面对每行代码进行一一说明。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static char * cmd = "";
module_param(cmd, charp, S_IRUGO);
static int __init helloworld_init(void)
{
printk(KERN_ALERT "Hello world module init with cmd %s\n", cmd);
return 0;
}
static void __exit helloworld_exit(void)
{
printk(KERN_ALERT "Hello world module exit\n");
}
module_init(helloworld_init);
module_exit(helloworld_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("o_o");
MODULE_DESCRIPTION("Hello World Module");
MODULE_VERSION("0.0.1");
MODULE_ALIAS("Hi");
包含这个库,在一般的编译器程序中会报错。
原因是因为linux的/usr/include/linux/
目录中并没有init.h这个头文件,但是这对我们kernel内核编程时不影响的。
因为后面我们并不是直接使用gcc对该ker_HelloWorld.c文件进行编译。
static char * cmd = "";
module_param(cmd, charp, S_IRUGO);
声明了一个静态字符指针变量 cmd
,使用 module_param
宏将其注册为内核参数,charp是一个数据类型,表示字符指针类型,权限为 S_IRUGO,即允许读取。
使得内核中的其他函数能够调用该内核参数cmd
static int __init helloworld_init(void)
{
printk(KERN_ALERT "Hello world module init with cmd %s\n", cmd);
return 0;
}
定义一个静态函数,将相应的信息Hello world module init with cmd %s\n
输出到系统日志中。
printk是Linux内核中用于输出信息的一种函数。它的作用类似于用户空间中的printf函数,但它输出的信息不是直接出出到终端等设备,而是通过内核日志缓冲区
输出到系统日志
中。
__init和__initdata告诉内核这些函数和数据只在初始化期间使用,一旦初始化完成,它们就不再需要,从而可以释放掉它们占用的内存,从而提高系统的性能和效率。
所以该函数名称中的__init关键字表示这是一个初始化函数。
static void __exit helloworld_exit(void)
{
printk(KERN_ALERT "Hello world module exit\n");
}
定义一个静态函数,将相应的信息Hello world module exit\n
输出到系统日志中。
__exit告诉内核这些函数只在模块卸载时使用,一旦模块被卸载,它们就不再需要,从而可以释放掉它们占用的内存,从而提高系统的性能和效率。
所以该函数名称中的__exit关键字表示这是一个清理函数,该函数在模块卸载时被调用。
将函数helloworld_init注册为当前内核模块的初始化函数,当这个内核模块被加载到系统中时,内核会自动调用这个函数来完成其初始化工作。
将函数helloworld_exit注册为当前内核模块的退出函数,当这个内核模块被卸载时,内核会自动调用这个函数来完成其退出工作。
MODULE_LICENSE()
是一个 Linux 内核模块中的宏,用于声明模块的许可证信息。
表示该模块的许可证是 GPL(GNU通用公共许可证)。
MODULE_AUTHOR()
是一个 Linux 内核模块中的宏,用于声明模块的作者信息。
表示模块的作者是 “o_o”。
MODULE_DESCRIPTION()
是一个 Linux 内核模块中的宏,用于声明模块的描述信息。
表示该模块的描述信息为 “Hello World Module”。
MODULE_VERSION()
是一个 Linux 内核模块中的宏,用于声明模块的版本号。
表示该模块的版本号为 “0.0.1”。
# Makefile 4.0
obj-m := ker_HelloWorld.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
在Makefile文件中,obj-m是指要编译成内核模块的目标文件名。它通常用于构建Linux内核模块。obj-m表示目标是一个模块,而不是一个可执行文件。该目标文件名的扩展名通常是“.ko”。
第一行指定了要编译的内核模块的文件名,这里是ker_HelloWorld.o。
CURRENT_PATH变量指定了当前目录的路径,它使用shell命令pwd来获取当前路径。
LINUX_KERNEL变量指定了当前系统的内核版本号,它使用uname命令获取。
LINUX_KERNEL_PATH变量指定了Linux内核源代码的路径,它使用Linux内核版本号拼接而成。
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
all规则使用make命令在$LINUX_KERNEL_PATH目录下构建内核模块,M参数指定了模块代码所在的目录是$(CURRENT_PATH)。
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
在上述工作均完成以后,我们在当前目录执行make
命令生成内核模块module
make
在文件目录中看到的一个以.ko
后缀结尾的文件即为内核模块
通过以下命令加载该内核模块
sudo insmod ker_HelloWorld.ko
在通过lsmod
命令查看加载的内核模块,即可发现我们已经将编写的模块加入到内核中
在通过dmesg
查看内核相关信息,可以发现系统内核中打印出来了我们helloworld_init(void)函数打印的内容。
通过以下命令将模块从内核中删除
sudo rmmod ker_HelloWorld
sudo insmod ker_HelloWorld.ko cmd="o_o'"
通过以下指令即可将当前目录所生成的相应模块删除
make clean
这些问题标志着我后续研究的重点方向,需要我继续深入学习AVFoundation框架的使用,特别是其控制摄像头的具体方法,并探索如何将这些控制整合到机械臂的运动调整中,以确保最终拍摄出的视频质量符合预期。尽管目前市场上有许多稳定设备如平衡环架(gimbal)来辅助拍摄,以求达到稳定和多角度的拍摄效果,但在此篇文章中,我将探索一种独特的解决方案:通过将手机安装在机械臂的末端来进行拍摄,以实现那些传统方法难以捕捉的特殊视角。随着人工智能技术的不断进步和普及,AI与机器人的结合无疑将成为未来技术发展的重要趋势。
文章浏览阅读342次,点赞6次,收藏8次。党员之家服务系统小程序的功能已基本实现,主要包括首页、个人中心、学生管理、教师管理、任务信息管理、报名信息管理、任务排名管理、学习资料管理、每日打卡管理、交流信息管理、回复信息管理、积极分子管理、党员信息管理、交流论坛、系统管理等。论文主要从系统的分析与设计 、数据库设计和系统的详细设计等几个方面来进行论述,系统分析与设计部分主要论述了系统的功能分析、系统的设计思路,数据库设计主要论述了数据库的设计,系统的详细设计部分主要论述了几个主要模块的详细设计过程。
文章浏览阅读8.3k次,点赞5次,收藏12次。作为 admin 用户,请求认证令牌,输入如下命令openstack --os-auth-url http://controller:35357/v3 --os-project-domain-name default --os-user-domain-name default --os-project-name admin --os-username admin token issue报错Failed to discover available identity versions whe._caused by newconnectionerror('
文章浏览阅读4.5k次。可以在桌面安装云顷还原系统软件,利用软件中的网络对拷功能部署批量对拷环境,进行电脑教室软件的批量对拷安装与增量对拷安装。_教室电脑 一起装软件
文章浏览阅读3.1k次,点赞5次,收藏7次。原文链接:https://www.ikaze.cn/article/43写这篇博文的起因是,我在论坛宣传我开源的新项目YTask(go语言异步任务队列)时,有小伙伴在下面回了一句“为什么不用nsq?”。这使我想起,我在和同事介绍celery时同事说了一句“这不就是kafka吗?”。那么YTask和nsq,celery和kafka?他们之间到底有什么不同呢?下面我结合自己的理解。简单的分析一..._任务队列和消息队列
文章浏览阅读1.5k次。1,MyUtuils.kt将被调用的文件class MyUtils { fun show(info:String){ println(info) }}fun show(info:String){ println(info)}2,Java文件调用该类,ClientJava.javapublic class ClientJava { public static void main(String[] args) { /** _java 调用kt 对象
文章浏览阅读1.2k次。1第一步:搭建NFS服务器关于NFS服务器的搭建请参考http://blog.csdn.net/qq_30256711/article/details/78463940第二步:rsync同步实现关于rsync同步请参考http://blog.csdn.net/qq_30256711/article/details/78539342第三步:inotify结合rsync实现实时同步_centos6.5 rsync ino
2.可重复级:建立了基本的项目管理过程和实践来跟踪项目费用,进度,功能特性。5.优化级:加强了定量分析,通过过程质量反馈,新观念,新技术的反馈。1.初始级:软件过程杂乱无章,没有明确定义的步骤,英雄式核心人物。定量管理(CL4):已定量管理的过程的制度化。已管理(CL2):已管理的过程的制度化。已定义(CL3):已定义的过程的制度化。3.已定义级:过程文档化,标准化。4.已管理级:软件过程和产品质量。定量管理的:已度量和控制。优化的:集中于过程改进。已管理的:为项目服务。已定义的:为组织服务。
标准的知识蒸馏(KD)方法将笨重的教师模型的知识蒸馏到具有预定义架构的学生模型的参数中。然而,神经网络的知识,即网络在给定输入条件下的输出分布,不仅取决于其参数,还取决于其架构。因此,对于KD的一种更广义的方法是将教师的知识蒸馏到学生的参数和架构中。为了实现这一点,我们提出了一种新的基于架构的知识蒸馏(AKD)方法,该方法找到最适合蒸馏给定教师模型的学生模型(对于教师来说是珍珠)。具体来说,我们利用带有我们的KD引导奖励的神经架构搜索(NAS)来搜索最适合给定教师模型的学生架构。
Docker知识比较全面的总结,使用表格总结结合示例,一目了然,运维参考以及面试参考皆可
文章浏览阅读174次。用Python的人总少不了与Matplotlib接触,可是我们在引入时Python少不了报错。此时,我们就需要在错误中寻找线索。_如何导入 matplotlib.pyplot 导入失败
文章浏览阅读8.5k次,点赞2次,收藏11次。使用uni-ui UI框架实现表格加分页功能,uni-table 和uni-pagination 组件的使用示例加完整代码。_uniapp table