:Linux内核模块的创建)
操作系统一Linux内核模块的创建初入操作系统的坑作为小白的我既忐忑又兴奋希望能把课上的一些习题记录下来一来可以让自己以后也回顾一下二来也算是一个小小的教程适合初学者看看因为本人也是小白如果有不严谨的地方欢迎指正。这次的project主要是写Linux内核话不多说先上题目。一、作业题目Design a kernel module that creates a /proc file named /proc/jiffiesthat reports the current value of jiffies when the /proc/jiffies fileis read, such as with the commandcat /proc/jiffiesBe sure to remove /proc/jiffies when the module is removed.第一题大概意思就是创建一个模块名字为“jiffies”然后在命令行中输入“cat /proc/jiffies”就可以显示当前的jiffies值至于jiffies是什么后面再讲。Design a kernel module that creates a proc file named /proc/secondsthat reports the number of elapsed seconds since the kernel module wasloaded. This will involve using the value of jiffies as well as the HZrate. When a user enters the commandcat /proc/secondsyour kernel module will report the number of seconds that haveelapsed since the kernel module was first loaded. Be sure to remove/proc/seconds when the module is removed.第二题大概意思就是创建一个模块名字为“seconds”然后在命令行中输入“cat /proc/seonds”就可以输出HZ.二、开始做啦1.首先了解一下jiffies和Hz是个什么玩意儿jiffies是linux中一个与中断次数相关的值而Hz是一秒内时钟中断的次数jiffies与hz的关系就是两个时间的jiffies之差除以频率数可以得到经过的时间即公式(jiffiesl−jiffiesf)/Hzseconds (jiffiesl-jiffiesf)/Hz seconds(jiffiesl−jiffiesf)/Hzseconds2.直接开始做题吧《1》作业一1在主机编写一个jiffies.c文件/*Create a proc named jiffies*/#includelinux/init.h#includelinux/kernel.h#includelinux/module.h#includelinux/proc_fs.h#includelinux/jiffies.h#includeasm/uaccess.h#defineBUFFER_SIZE128#definePROC_NAMEjiffiesssize_tproc_read(struct file*file,char __user*usr_buf,size_t count,loff_t*pos);/*forward declartion*//*Declare the ower and read function*/staticstruct file_operations proc_ops{.ownerTHIS_MODULE,/*proc所有者*/.readproc_read,/*访问proc时需要调用的函数(即cat /proc/jiffies时访问proc_read函数*/};/*要记得proc_init始终返回0proc_exit没有返回值。*//*Begin call this function when the module loaded*/intproc_init(void){proc_create(PROC_NAME,0666,NULL,proc_ops);/*创建一个proc*/printk(KERN_INFOThe /proc/jiffies loaded!\n);return0;}voidproc_exit(void){remove_proc_entry(PROC_NAME,NULL);/*删除该proc*/printk(KERN_INFOThe /proc/jiffies unloaded!\n);}/*Implemention of proc_readload模块后用cat /proc/jiffies即可查看buffer中的str*/ssize_tproc_read(struct file*file,char __user*usr_buf,size_t count,loff_t*pos){int rv0;/*显示的信息的长度*/char buffer[BUFFER_SIZE];/*信息缓冲区*/staticint completed0;if(completed){completed0;return0;}completed1;/*下面这行将“”中的字符存入bufferrv为写入的字符总数不包括字符串追加在字符串末尾的空字符*/rvsprintf(buffer,Now the jiffies value is %lu\n,jiffies);copy_to_user(usr_buf,buffer,rv);/*从内核的buffer拷贝到用户的usr_buf*/returnrv;}module_init(proc_init);module_exit(proc_exit);MODULE_LICENSE(GPL);/*许可*/MODULE_DESCRIPTION(Display the jiffies value);/*模型描述*/MODULE_AUTHOR(Lily);/*作者*/2打开linux虚拟机此处用osc10ecd final-src-osc10e #进入这个文件夹 mkdir ch1 #创建ch1文件夹3将主机中的jiffies文件传到虚拟机打开主机win的cmd注意查看是否下载了openSSH客户端然后输入scp-P2222source target #source是本地文件的目录,target是远程机子的目录/*例如*/scp-P2222C:\Users\lenovo\Desktop\jiffies.c osc127.0.0.1:~#传送到虚拟机的根目录 scp-P2222C:\Users\lenovo\Desktop\jiffies.c osc127.0.0.1:~/final-src-osc10e/ch1 #传送到ch1文件夹中4打开虚拟机写Makefilecd final-src-osc10e #进入这个文件夹 mkdir ch1 #创建ch1文件夹 cd ch1 #进入ch1文件夹 vim Makefile #在vim中创建并编写Makefile文件打开后按“i”切换为可写模式 写完后按“Esc”然后按“wq”最后按回车即保存完毕 不想保存则按“q”Makefile文件代码如下注意Tab缩进obj-mjiffies.o #换文件名的话替换这里的“jiffies”就行 all:make-C/lib/modules/$(shell uname-r)/buildM$(PWD)modules clean:make-C/lib/modules/$(shell uname-r)/buildM$(PWD)clean保存完了以后就ok啦回到ch1文件夹中#以下命令可能用得上 cd..#返回上一级可能会用上 mv source target #移动文件例如 mv~/ch1/1.c~/ch2 即把1.c文件从ch1移到ch2 重命名文件如 mv ch1 ch2 将ch1重命名为ch2 rm ch1 #删除ch1文件夹 rm-rf ch1 #强行删除ch1文件夹5开始测试sudo dmesg-c #定期清除缓存区 make #编译 sudo insmod jiffies.ko #加载jiffies内核模块 dmesg #显示proc_init函数中要打印的东西即The/proc/jiffies loaded!cat/proc/jiffies #显示proc_read函数中要打印的东西 sudo rmmod jiffies #删除jiffies内核模块 dmesg #显示proc_exit函数中要打印的东西检测是否正常删除测试效果如下《2》作业二1在主机编写一个seconds.c文件/*Create a proc named seconds*/#includelinux/init.h#includelinux/kernel.h#includelinux/module.h#includelinux/proc_fs.h#includeasm/uaccess.h#includelinux/jiffies.h/*For jiffies*/#includeasm/param.h/*For HZ*/#defineBUFFER_SIZE128#definePROC_NAMEseconds/*volatile:每次都实时读取该变量的值,而不是读取该变量在寄存器中的值, volatile为了防止那些非线程安全的变量的变更导致的结果错误,比如多个线程竞争a变量的修改 得到的某个时刻的a变量的值就不一定是当前的a变量了,而有可能是某一时刻a变量的值*/unsigned long int volatile f_jiffies,l_jiffies;constint hzHZ;ssize_tproc_read(struct file*file,char __user*usr_buf,size_t count,loff_t*pos);/*forward declartion*//*Declare the ower and read function*/staticstruct file_operations proc_ops{.ownerTHIS_MODULE,.readproc_read,/*.read is the name of thefunction proc read() that is to be called whenever /proc/hello is read.*/};/*Begin call this function when the module loaded*/intproc_init(void){proc_create(PROC_NAME,0666,NULL,proc_ops);f_jiffiesjiffies;#f_jiffies赋值printk(KERN_INFOThe /proc/seconds loaded!\n);return0;}voidproc_exit(void){remove_proc_entry(PROC_NAME,NULL);printk(KERN_INFOThe /proc/seconds unloaded!\n);}/*Implemention of proc_read*/ssize_tproc_read(struct file*file,char __user*usr_buf,size_t count,loff_t*pos){l_jiffiesjiffies;#l_jiffies赋值 int rv0;char buffer[BUFFER_SIZE];staticint completed0;if(completed){completed0;return0;/*proc_read逢0才停止因此这个return 0保证只输出一次值否则将无限循环输出*/}completed1;rvsprintf(buffer,The running time is %d s\n,((l_jiffies-f_jiffies)/hz));/*将jiffies的值存入bufferrv为写入的字符总数不包括字符串追加在字符串末尾的空字符*/copy_to_user(usr_buf,buffer,rv);/*从内核的buffer拷贝到用户的usr_buf*/returnrv;}module_init(proc_init);module_exit(proc_exit);MODULE_LICENSE(GPL);MODULE_DESCRIPTION(Show the program execution time);MODULE_AUTHOR(Lily);2打开linux虚拟机此处用osc10ecd final-src-osc10e #进入这个文件夹 mkdir ch1 #创建ch1文件夹3将主机中的jiffies文件传到虚拟机打开主机win的cmd注意查看是否下载了openSSH客户端然后输入scp-P2222source target #source是本地文件的目录,target是远程机子的目录/*例如*/scp-P2222C:\Users\lenovo\Desktop\seconds.c osc127.0.0.1:~#传送到虚拟机的根目录 scp-P2222C:\Users\lenovo\Desktop\seconds.c osc127.0.0.1:~/final-src-osc10e/ch1 #传送到ch1文件夹中4打开虚拟机写Makefilecd final-src-osc10e #进入这个文件夹 mkdir ch1 #创建ch1文件夹 cd ch1 #进入ch1文件夹 vim Makefile #在vim中创建并编写Makefile文件打开后按“i”切换为可写模式 写完后按“Esc”然后按“wq”最后按回车即保存完毕 不想保存则按“q”Makefile文件代码如下obj-mseconds.o #换文件名的话替换这里的“seconds”就行 all:make-C/lib/modules/$(shell uname-r)/buildM$(PWD)modules clean:make-C/lib/modules/$(shell uname-r)/buildM$(PWD)clean保存完了以后就ok啦回到ch1文件夹中#以下命令可能用得上 cd..#返回上一级可能会用上 mv source target #移动文件例如 mv~/ch1/1.c~/ch2 即把1.c文件从ch1移到ch2 rm ch1 #删除ch1文件夹5开始测试sudo dmesg-c #定期清除缓存区 make #编译 sudo insmod seconds.ko #加载jiffies内核模块 dmesg #显示proc_init函数中要打印的东西即The/proc/jiffies loaded!cat/proc/seconds #显示proc_read函数中要打印的东西 sudo rmmod seconds #删除jiffies内核模块 dmesg #显示proc_exit函数中要打印的东西检测是否正常删除作业二和作业一就差不多了就多用了一个公式而已~第一次over~