LINUX 内核编写基础

http://blog.chinaunix.net/uid-20564848-id-73208.html

内核文档:[[email protected] Documentation]# pwd
/usr/src/kernels/linux-2.6.32/Documentation
[[email protected] Documentation]# ls
00-INDEX                      i2o                        parport.txt
ABI                           ia64                       PCI
accounting                    ics932s401                 pcmcia
acpi                          ide                        pi-futex.txt
aoe                           infiniband                 pnp.txt
applying-patches.txt          initrd.txt                 power
arm                           input                      powerpc
atomic_ops.txt                Intel-IOMMU.txt            pps
auxdisplay                    intel_txt.txt              prctl
bad_memory.txt                ioctl                      preempt-locking.txt
basic_profiling.txt           io-mapping.txt             printk-formats.txt
binfmt_misc.txt               IO-mapping.txt             prio_tree.txt
blackfin                      io_ordering.txt            rbtree.txt
block                         iostats.txt                RCU
blockdev                      IPMI.txt                   rfkill.txt
braille-console.txt           IRQ-affinity.txt           robust-futex-ABI.txt
bt8xxgpio.txt                 irqflags-tracing.txt       robust-futexes.txt
btmrvl.txt                    IRQ.txt                    rtc.txt
BUG-HUNTING                   isapnp.txt                 rt-mutex-design.txt
c2port.txt                    isdn                       rt-mutex.txt
cachetlb.txt                  ja_JP                      s390
cdrom                         java.txt                   SAK.txt
cgroups                       kbuild                     scheduler
Changes                       kdump                      scsi
CodingStyle                   kernel-doc-nano-HOWTO.txt  SecurityBugs
connector                     kernel-docs.txt            SELinux.txt
console                       kernel-parameters.txt      serial
cpu-freq                      keys-request-key.txt       serial-console.txt
cpu-hotplug.txt               keys.txt                   sgi-ioc4.txt
cpuidle                       kmemcheck.txt              sgi-visws.txt
cpu-load.txt                  kmemleak.txt               sh
cputopology.txt               kobject.txt                slow-work.txt
credentials.txt               ko_KR                      SM501.txt
cris                          kprobes.txt                Smack.txt
crypto                        kref.txt                   sound
dcdbas.txt                    kvm                        sparc
debugging-modules.txt         laptops                    sparse.txt
debugging-via-ohci1394.txt    ldm.txt                    spi
dell_rbu.txt                  leds-class.txt             spinlocks.txt
development-process           leds-lp3944.txt            stable_api_nonsense.txt
device-mapper                 lguest                     stable_kernel_rules.txt
devices.txt                   local_ops.txt              SubmitChecklist
DMA-API.txt                   lockdep-design.txt         SubmittingDrivers
DMA-attributes.txt            lockstat.txt               SubmittingPatches
dmaengine.txt                 logo.gif                   svga.txt
DMA-ISA-LPC.txt               logo.txt                   sysctl
DMA-mapping.txt               m68k                       sysfs-rules.txt
DocBook                       magic-number.txt           sysrq.txt
dontdiff                      make                       telephony
driver-model                  Makefile                   thermal
dvb                           ManagementStyle            timers
dynamic-debug-howto.txt       mca.txt                    tomoyo.txt
early-userspace               md.txt                     trace
edac.txt                      memory-barriers.txt        uml
eisa.txt                      memory-hotplug.txt         unaligned-memory-access.txt
email-clients.txt             memory.txt                 unicode.txt
fault-injection               mips                       unshare.txt
fb                            misc-devices               usb
feature-removal-schedule.txt  mn10300                    vgaarbiter.txt
filesystems                   mono.txt                   VGA-softcursor.txt
firmware_class                mtd                        video4linux
flexible-arrays.txt           mutex-design.txt           video-output.txt
frv                           namespaces                 vm
futex-requeue-pi.txt          netlabel                   volatile-considered-harmful.txt
gcov.txt                      networking                 voyager.txt
gpio.txt                      nmi_watchdog.txt           w1
highuid.txt                   nommu-mmap.txt             watchdog
HOWTO                         numastat.txt               wimax
hwmon                         oops-tracing.txt           x86
hw_random.txt                 parisc                     zh_CN
i2c                           parport-lowlevel.txt       zorro.txt
内核书籍:

LDK:LINUX内核设计与实现

ULK:深入理解LINUX内核

LDD:LINUX 设备驱动程序

LVMM:深入理解LINUX 虚拟内存管理

深入理解LINUX网络内幕
内核社区:

http://vger.kernel.org/vger-lists.html#linux-kernel

http://dir.gmane.org/gmane.linux.usb.general

https://www.kernel.org/

http://linux.chinaunix.net/
printk小结

1 printk 消息级别定义

    #define KERN_EMERG   "<0>"   /*紧急事件,一般是系统崩溃之前的提示消息*/
    #define KERN_ALERT   "<1>"   /*必须立即采取行动*/
    #define KERN_CRIT    "<2>"   /*临界状态,通常涉及严重的硬件或者软件操作失败*/
    #define KERN_ERR     "<3>"   /*用于报告错误状态,设备驱动会经常使用KERN_ERR来报告硬件错误*/
    #define KERN_WARNING "<4>"   /*对可能出现问题的情况进行警告,这类情况通常不会对系统造成严重问题 */
    #define KERN_NOTICE  "<5>"   /*有必要进行提示的正常情形,许多与安全相关的状况用这个级别进行汇报*/
    #define KERN_INFO    "<6>"   /*内核提示性信息,很多驱动程序在启动的时候以这个级别打印找到的硬件信息*/
    #define KERN_DEBUG   "<7>"   /*用于调试信息*/

2  使用方法
    printk(KERN_ALERT "XXXXXX",XXXX);
3 /proc/sys/kernel/printk
     该文件可以调节printk的输出等级,文件中有四个数字值。
    (1)  控制台日志级别:优先级高于该值的消息将被打印至控制台。
    (2)  默认的消息日志级别:用该优先级来打印未定义优先级的消息。
    (3) 最低的控制台日志级别:控制台日志界别可被设置的最小值。
    (4) 默认的控制台日志级别:控制台日志级别的默认值。
4 通过如下命令可以使得Linux内核的任何printk都被输出到控制台
    #echo 8 > /proc/sys/kernel/printk

 5. cat /proc/kmsg    这个文件用于检索用printk生成的内核消息。任何时刻只能有一个具有超级用户权限的进程可以读取这个文件。也可以用系统调用syslog检索这些消息。    通常使用工具dmesg或守护进程klogd检索这些消息。
hello.c 内核模块编绎

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int init_hello_4(void)
{
   printk(KERN_ALERT "Hello, world 4 ");
   return 0;
}

static void cleanup_hello_4(void)
{
   printk(KERN_ALERT "Goodbye, world 4 ");
}

module_init(init_hello_4);
module_exit(cleanup_hello_4);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Playmud");
MODULE_DESCRIPTION("Test only!");

配置Makefile和执行ko编译

[[email protected] ~]#  echo "obj-m:=hello.o" > Makefile

[[email protected] ~]# make -C /lib/modules/`uname -r`/build M=`pwd` modules
  make: Entering directory `/usr/src/kernels/2.6.32-431.23.3.el6.x86_64‘
  Building modules, stage 2.
  MODPOST 1 modules
  make: Leaving directory `/usr/src/kernels/2.6.32-431.23.3.el6.x86_64‘

/lib/modules/`uname -r`/build就是本地机子的module编译配置目录

不是为正在运行的内核编译模块:
make -C M=`pwd`
为正在运行的内核编译模块:
make -C /lib/modules/`uname -r`/build M=`pwd` modules

printk没有在console上打印出提示,通过

[[email protected] ~]# dmesg |tail -1
  Hello, world

可以查到,具体配置可以查看
vim /etc/syslog.conf
sysrq
     常使用的魔术键:
     echo  1>/proc/sys/kernel/sysrq 打开sysrq功能

     echo ‘t‘ >/proc/sysrq-trigger   打印进程栈,调试时很有用

     echo ‘c‘ >/proc/sysrq-trigger  常常用来测试dump模式
printk打印不能显示到终端的问题
  【原型】
  int printk(const char * fmt,…);
  【示例】
  与大多数展示printf的功能一样,我们也用一个helloworld的程序来演示printk的输出:
  编写一个内核模块:
  #include
  #include
  #if CONFIG_MODVERSIONS==1
  #define MODVERSIONS
  #include
  #endif
  MODULE_LICENSE("GPL");
  int init_module()
  {
  printk("hello.word-this is the kernel speaking\n");
  return 0;
  }
  void cleanup_module()
  {
  printk("Short is the life of a kernel module\n");
  }
  保存为文件hello.c
  编写一个Makefile:
  CC=gcc
  MODCFLAGS:=-O6 -Wall -DMODULE -D__KERNEL__ -DLINUX
  hello.o:hello.c /usr/include/linux/version.h
  $(CC) $(MODCFLAGS) -c hello.c
  echo insmod hello.o to turn it on
  保存为文件Makefile
  执行make
  我们可以看到生成了一个hello.o的内核模块,我们想通过这个模块在插入内核的时候输出
  "hello.word-this is the kernel speaking"
  这样一条信息。
  然后我们开始:
  [[email protected] root]# insmod hello.o
  [[email protected] root]#
  并没有输出任何消息。why?
  这也是printf和printk的一个不同的地方
  用printk,内核会根据日志级别,可能把消息打印到当前控制台上,这个控制台通常是一个字符模式的终端、一个串口打印机或是一个并口打印机。这些消息正常输出的前提是──日志输出级别小于console_loglevel(在内核中数字越小优先级越高)。
  没有指定日志级别的printk语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到
  日志级别一共有8个级别,printk的日志级别定义如下(在include/linux/kernel.h中):
  #define KERN_EMERG    0
  #define KERN_ALERT    1
  #define KERN_CRIT     2
  #define KERN_ERR      3
  #define KERN_WARNING  4
  #define KERN_NOTICE   5
  #define KERN_INFO     6
  #define KERN_DEBUG    7
  现在我们来修改hello.c程序,使printk的输出级别为最高:
  printk("<0>""hello.word-this is the kernel speaking\n");
  然后重新编译hello.o,并插入内核:
  [[email protected] root]# insmod hello.o
  [[email protected] root]#
  Message from [email protected] at Sat Aug 15 05:32:22 2009 ...
  localhost kernel: hello.word-this is the kernel speaking
  hello,world信息出现了。
  其实printk始终是能输出信息的,只不过不一定是到了终端上。我们可以去
  /var/log/messages这个文件里面去查看。
  如果klogd没有运行,消息不会传递到用户空间,只能查看/proc/kmsg
  通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日志级别。查看这个文件的方法如下:
  #cat /proc/sys/kernel/printk 6 4 1 7
  上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别。
  可用下面的命令设置当前日志级别:
  # echo 8 > /proc/sys/kernel/printk
  这样所有级别<8,(0-7)的消息都可以显示在控制台上. 
时间: 2024-08-29 06:35:21

LINUX 内核编写基础的相关文章

Linux 脚本编写基础

1. Linux 脚本编写基础1.1 语法基本介绍1.1.1 开头程序必须以下面的行开始(必须放在文件的第一行):#!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例子中我们使用/bin/sh来执行程序. 当编辑好脚本时,如果要执行该脚本,还必须使其可执行. 要使脚本可执行:编译 chmod +x filename 这样才能用./filename 来运行1.1.2 注释 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束.我们真诚地建议您在程序中使用

Linux内核开发基础

1.Linux内核简介 1.1.Linux系统如何构成 内核空间(Kernel Space)+用户空间(User Space) 用户空间 = 用户程序 + C语言库(例如:GNC C Library) 内核空间 = Kernel + 系统调用接口(System Call Interface) + 体系结构相关代码 Linux系统被划分用户空间 内核空间 原因? 现在CPU实现不同的工作模式,以ARM为例 A.用户模式(usr) B.系统模式(sys) C.外部中断模式(irq) D.管理模式(s

Linux shell脚本基础学习详细介绍(完整版)一

Linux shell脚本基础学习这里我们先来第一讲,介绍shell的语法基础,开头.注释.变量和 环境变量,向大家做一个基础的介绍,虽然不涉及具体东西,但是打好基础是以后学习轻松地前提.1. Linux 脚本编写基础◆1.1 语法基本介绍 1.1.1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例子中我们使用/bin/sh来执行程序. 当编辑好脚本时,如果要执行该脚本,还必须使其可执行. 要使脚本可执

Linux内核的基本概念

Linux内核学习,推荐的书籍: <linux设备驱动开发详解第二版>.<Linux内核设计与实现第三版>.<嵌入式Linux应用开发完全手册> 第一篇:讲解Linux内核的基础知识,先有一个整体的框架,后续会逐步讲解,一步步深入. 1.物理地址和虚拟地址 地址转换:内核所使用的地址一定是虚拟地址,但是CPU真正最后使用或者访问的是物理地址,所以,必须有一个转换过程.内核的虚拟地址和物理地址之间只是一个差值0xc0000000的区别,所以从物理地址求虚拟地址或从虚拟地址

在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序(老罗学习笔记3)

在Android硬件抽象层(HAL)概要介绍和学习计划一文中,我们简要介绍了在Android系统为为硬件编写驱动程序的方法.简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中.接着,在Ubuntu上为Android系统编写Linux内核驱动程序一文中举例子说明 了如何在Linux内核编写驱动程序.在这一篇文章中,我们将继续介绍Android系统硬件驱动程序的另一方面实现,即如何在硬件抽象层中增加硬件模块来和内核驱动程序交互.在这篇文章中,我们还将学习到如何在

shell 脚本编写基础

在进行Linux测试时编写脚本是必不可少的,Shell脚本的名称可以随便定义,也不要什么后缀名,例如可以写abc,smartzip这类名称,运行时只要键入 ./smartzip就能运行脚本了.. 每行命令开头处不用就空格也行.. 第1部分. linux 脚本编写基础 1.1 语法基本介绍1.1.1 开头程序必须以下面的行开始(必须方在文件的第一行):#!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在这个例子中我们使用/bin/sh来执行程序. 当编辑好脚本时,如果要执

Linux 内核管理

Linux内核基础:Linux Kernel:  Linux内核的体积结构是单内核的,但充分借鉴了微内核设计体系的优点,为内核引入模块化机制,使得虽然是单内核,但工作在模块化的方式下,并且模块可以动态装载或卸载:Linux内核负责管理系统的进程.内存.设备驱动程序.文件和网络系统,决定着系统的性能和稳定性.如是我们在了解Linux内核的基础上根据自己的需要量身定制一个更高效更稳定的内核,就需要我们手动去编译和配置内核里的各项相关的参数和信息.  内核的组成部分: 1.Kernel:内核核心,一般

Linux内核工程导论——基础架构

基础功能元素 workqueue linux下的工作队列时一种将工作推后执行的方式,其可以被睡眠.调度,与内核线程表现基本一致,但又比内核线程使用简单,一般用来处理任务内容比较动态的任务链.workqueue有个特点是自动的根据CPU不同生成不同数目的队列.每个workqueue都可以添加多个work(使用queue_work函数). 模块支持 模块概述 可访问地址空间,可使用资源, 模块参数 用户空间通过"echo-n ${value} > /sys/module/${modulenam

linux设备驱动辩编写基础

Linux设备驱动辩编写基础 一.linux中的驱动是以模块的形式存在的,这样就大大提高了驱动的灵活性,linux内核模块的程序结构如下: l  模块加载函数(必须):module_init() l  模块卸载函数(必须):module_exit() l  模块许可证声明(必须):MODULE_LECENSE("GPL") l  模块参数(可选):module_param(a,int,0400) l  模块到处符号(可选):EXPORT_SYMBOL_GPL(func) l  模块作者