linux内核编程

这些天在学习linux内核编程,就在这里小小的show以下。

首先编写如下的linux代码。并命名为hello.c

这里你应该注意亮点:

第一、linux内核编程,不同于普通的用户态下的编程;有一个入口的main函数;这里的“main”函数是module_init();同时还有一个善后处理的函数:module_exit()。

第二、linux内核编程在编译的时候,不同于用户态下的编程;可以直接使用gcc编译器编译链接,就能够成为可执行的;而是需要编写一个Makefile文件,不是makefile!!这里牵扯到很多的内核态下的东西,具体的我也没弄清楚!详细的会在后面和大家分享。

hello.c  文件

  1. 1 #include <linux/module.h>
  2. 2 #include <linux/kernel.h>
  3. 3 #include <linux/init.h>
  4. 4 static int __init lkp_init(void);
  5. 5 static int __exit lkp_exit(void);
  6. 6
  7. 7
  8. 8 static int __init lkp_init(void)
  9. 9 {
  10. 10 printk("<1>Hello ,Word!\n");
  11. 11 return 0;
  12. 12 }
  13. 13
  14. 14 static int __exit lkp_exit(void)
  15. 15 {
  16. 16 printk("<2>Hello,Word exit\n");
  17. return 0;
  18. 17 }
  19. 18 module_init(lkp_init);
  20. 19 module_exit(lkp_exit);

并在hello.c的同一目录下建立Makefile文件。

Makefile文件:

  1. 1 ifneq ($(KERNELRELEASE),)
  2. 2 mymodule-objs:= hello.c
  3. 3 obj-m += hello.o
  4. 4
  5. 5 else
  6. 6 PWD :=$(shell
    pwd)
  7. 7 KVER := $(shell uname -r)
  8. 8 KDIR :=/lib/modules/$(KVER)/build
  9. 9
  10. 10 all:
  11. 11 $(MAKE) -C $(KDIR) M=$(PWD)
  12. 12 clean:
  13. 13 rm -rf *.o *.mod.c *.ko *.symvers *order *.markers *-
  14. 14 endif

说明:

当命令在执行make时,将调用Makefile文件。KERNELRELEASE 是在内核源代码的顶层/usr/src/linux-headers-2.6.32-33/Makefile 文件中定义的一个变量。读者如果下载的是linux-3.0的内核的话在**/linux-3.0/Makefile。当中的380行。如下:

  1. 379 # Read KERNELRELEASE from include/config/kernel.release (if it
    exists)
  2. 380 KERNELRELEASE = $(shell cat include/config/kernel.release
    2> /dev/null)
  3. 381 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL) ,.$(SUBLEVEL)))$(EXTRAVERSION)

在第一次读取执行此Makefile时,变量$(KERNELRELEASE) 并没有被设置,因此第一行ifneq的条件失败,从else后面的开始执行,设置PWD、KVER、KDIR等变量。

当make遇到标号all时,-C$(KDIR)指名跳转到内核源码目录下读取那里的Makefile。M=$(PWD),表明返回到当前的目录进行继续读入,执行当前的Makefile,也就是第二次调用make。这时的变量$(KERNELRELEASE)
已经被定义,因此ifneq成功,make将继续读取紧接在ifneq后面的内容。ifneq的内容为kbuild语句,指名模块源码中个文件之间的依赖关系和要生成的目标模块

语句  2 mymodule-objs:= hello.c
 表是mymodule.o 由hello.c生成。 语句3 obj-m += hello.o表是链接后将生成mymodule.ko模块,这个文件就是要插入内核的模块文件。

如果make的目标是clean,直接执行clean标号之后的操作,删除 一大堆的东西!执行文clean后面的rm命令之后,make整个工作就结束了!

执行效果:

  1. [#35#[email protected]:~]$cd
    kernel/
  2. [#36#[email protected]:~/kernel]$ls
  3. hello.c Makefile
  4. [#37#[email protected]:~/kernel]$make
  5. make -C /lib/modules/2.6.32-33-generic/build
    M=/home/caopeng/kernel
  6. make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.32-33-generic‘
  7. LD /home/caopeng/kernel/built-in.o
  8. CC [M] /home/caopeng/kernel/hello.o
  9. /home/caopeng/kernel/hello.c: In function ‘lkp_exit’:
  10. /home/caopeng/kernel/hello.c:17: warning: no
    return statement in function returning non-void
  11. /home/caopeng/kernel/hello.c: In function ‘__exittest’:
  12. /home/caopeng/kernel/hello.c:19: warning: return
    from incompatible pointer type
  13. Building modules, stage 2.
  14. MODPOST 1 modules
  15. CC /home/caopeng/kernel/hello.mod.o
  16. LD [M] /home/caopeng/kernel/hello.ko
  17. make[1]:正在离开目录 `/usr/src/linux-headers-2.6.32-33-generic‘
  18. [#38#[email protected]:~/kernel]$

编译成功!!

查看当前目录下的文件,会发现多了很多东西!如下:

  1. [#38#[email protected]:~/kernel]$ls
  2. built-in.o hello.ko
    hello.mod.o Makefile Module.symvers
  3. hello.c hello.mod.c
    hello.o modules.order
  4. [#39#[email protected]:~/kernel]$

这里不知道为什么生成的文件都没有x权限!这里要用到的就是hello.ko给其加上可执行权限。并使用insmod将其插入!然后用命令查看结果!

  1. [#47#[email protected]:~/kernel]$sudo
    rmmod hello.ko
  2. [#48#[email protected]:~/kernel]$sudo
    insmod hello.ko
  3. [#49#[email protected]:~/kernel]$dmesg -c
  4. klogctl: 不允许的操作
  5. [#50#[email protected]:~/kernel]$sudo
    dmesg -c
  6. [14651.331364] Hello,Word exit
  7. [14658.553284] Hello ,
  8. [#51#[email protected]:~/kernel]$

最后要记得rmmod!!!

时间: 2024-10-09 11:38:01

linux内核编程的相关文章

初探linux内核编程,参数传递以及模块间函数调用

一.前言                                  我们一起从3个小例子来体验一下linux内核编程.如下: 1.内核编程之hello world 2.模块参数传递 3.模块间函数调用 二.准备工作                           首先,在你的linux系统上面安装linux头文件,debian系列: 1 $:sudo apt-get install linux-headers-`uname -r` 安装后,在你的/lib/modules/目录下有你刚

Linux内核编程:Linux2.6内核源码解析_进程遍历 &nbsp; &nbsp; &nbsp; &nbsp;

/*     *File    : test.c   *Author  : DavidLin        *Date    : 2014-12-07pm        *Email   : [email protected] or [email protected]        *world   : the city of SZ, in China        *Ver     : 000.000.001        *history :     editor      time    

【转】初探linux内核编程,参数传递以及模块间函数调用

http://www.cnblogs.com/yuuyuu/p/5119891.html ZC: 疑问,最后的 模块kernel_mod 调用 模块kernel_fun的函数fun,是成功的OK的.但是 模块kernel_mod 怎么就知道 它调用的就是 模块kernel_fun的fun函数?如果 又有一个 模块kernel_fun01它也导出了fun函数,此时 模块kernel_mod调用fun的话调用的是哪一个模块的fun函数? (ZC: 测试了一下,两个模块 有相同的导出函数的话,在 加载

Linux 内核编程 or 内核模块编程的文件读写与信号传输问题

Linux内核编程时,内核代码执行只能直接访问内存上的数据,硬盘上的文件系统必须通过间接的方式才能被内核读写.一般内核操作文件读写的方式有三种:1.通过/proc/文件作为桥梁完成硬盘文件系统与内核的交互:2.通过ioctl方式实现交互:3.直接利用虚拟文件系统的函数vfs_read().vfs_write()读写文件.三种方式的具体实现方法网上有很多详细教程,可以参考.这里对三种方法做出比较. proc机制是一种很老的文件读写方式,通用性好,实现也算成熟,使用时需要自己实现内核上层的读写函数,

Linux内核编程-0:来自内核的 HelloWorld

Linux内核编程一直是我很想掌握的一个技能.如果问我为什么,我也说不上来. 也许是希望有一天自己的ID也出现在内核开发组的邮件列表里?或是内核发行文件的CREDITS文件上? 也许是吧.其实更多的,可能是对于底层的崇拜,以及对于内核的求索精神. 想到操作系统的繁杂,想到软件系统之间的衔接,内心觉得精妙的同时,更是深深的迷恋. 所以从这篇文章开始,我要真正的走进Linux内核里了,让代码指引我,去奇妙的世界一探究竟. 在这篇文章中,一起来对内核说Hello World. 本次的编程环境: Cen

Linux内核编程规范与代码风格

source: https://www.kernel.org/doc/html/latest/process/coding-style.html translated by trav, [email protected] 这是一篇阐述Linux内核编程代码风格的文档,译者以学习为目的进行翻译. 1 缩进 Tab的宽度是八个字符,因此缩进的宽度也是八个字符.有些异教徒想让缩进变成四个字符,甚至是两个字符的宽度,这些人和那些把 PI 定义为 3 的人是一个路子的. 注意:缩进的全部意义在于清晰地定义

linux内核编程入门--系统调用监控文件访问

参考的资料: hello world   https://www.cnblogs.com/bitor/p/9608725.html linux内核监控模块——系统调用的截获  https://www.cnblogs.com/lxw315/p/4773566.html 实现: 实验目的: 内核模块的编写:完成一个Linux/Windows内核/驱动模块的编写, 能够实现对文件访问的监控.或者对键盘设备.USB设备.网络设备. 蓝牙设备等的监控. 实验内容: 通过linux内核模块编程,写一个模块使

[linux内核]linux内核编程规范

1,__attrubte__关键字的作用 点击打开链接 __attrubte__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐.struct str_struct{        __u8    a;        __u8    b;        __u8    c;        __u16   d;} __attribute__ ((packed));以上结构体的大小为5/*  当用到typedef时,要特别注意__attribut

[linux内核][LINUX内核编程]学习笔记(二)

linux内核————队列 linux内核——队列 定义: [cpp] view plaincopy struct __kfifo{ unsigned int in;  //入队偏移,写索引 unsigned int out;  //出队偏移,读索引 unsigned int mask; unsigned int esize; void *data; } 使用: 创建一个队列,该函数创建并初始化一个大小为size的kfifo: [cpp] view plaincopy 38 int __kfif