linux 驱动笔记(一)

来源:互联网 发布:java的编译命令是哪个 编辑:程序博客网 时间:2024/05/16 11:20

第一章 驱动概述

1 为什么要学linux驱动?

linux分成内核空间和用户空间,这样对linux内核是一个保护,应用程序不能随便的访问内核,进而访问硬件。

应用程序(linuxIO编程 多进程 多线程 网络编程)---->运行在用户空间(0x0000_0000~0xBFFF_FFFF

驱动程序(在linux系统,只要访问硬件,如:LED显卡 声卡 网卡 串口)--->内核空间(0xC000_0000~0xFFFF_FFFF.

 

linux应用程序如果要访问硬件,必须要经过linux的驱动。

 

linux的驱动编程---->linux内核编程。

 

2 linux驱动学什么内容?

1) linux内核的module--->设备驱动是封装在module中的,在设计一个驱动之前,首先设计一个module

2) linux的字符设备驱动模型 --->如何申请设备号 如何做字符设备的初始化 如何设计应用程序的标准接口

3) IO内存映射 --->驱动如何访问硬件

4) GPIO口驱动设计 --->LED灯 蜂鸣器 按键。

5) 如何将一个驱动程序编译进内核 ---> *.ko放到zImage,在zImage初始化的过程中,自动安装驱动。

6) 混杂设备驱动模型 --->简化字符设备驱动设计。

7) linux中断驱动的设计

8) linux内核的内存分配

9) linux内核的动态定时器

10) 同步与互斥

11) platform 模型

12) 输入子系统模型

 

3 驱动的设计思想

1) 要求简洁 高效 稳定 可移植性

2) 简单的设备驱动程序可以自行设计

3) 复杂的设备驱动程序,一般都是需要移植

4) 学习驱动主要是学习驱动的框架

 

第二章 内核模块

1. 什么是module

   modulelinux的内核模块,linux的设备驱动封装在linux的内核模块中的。这样设备驱动成为linux内核中的独立模块,方便内核来管理驱动。

module存在的两种形式:

1.1 将驱动编译成独立的 内核外部的一个模块

    *.ko ---> 安装驱动 #insmod led_drv.ko --->将驱动装到内核,在内核中创建该驱动的模型,等待应用程序访问。

          卸载驱动 #rmmod led_drv   

insmod --- insert module;

rmmod --- remove module

 

1.2 驱动程序可以编译进linux内核

linux内核在启动的过程中,会自动安装驱动,就不需要手动安装。

如:

[1.048778] s3cfb s3cfb: registered successfully  //显卡驱动,自动注册的

[1.294921] S3C NAND Driver, (c) 2008 Samsung Electronics   //nand flash 驱动

 

内核启动输出,已初始化,

启动界面最后几行,有些是手动安装的一些驱动,

自动运行自定义的脚本,有两个

1. /etc/init.d/rcS  //初始化一些环境,IP

2. /etc/profile  //先执行第一个,再执行到这里,如两个文件里有同的配置,以最后一个为准.

 

source  upiot.sh //up启动 iot互联网,  启动粤嵌互联网实验箱.

 

[root@GEC210 /]# vi upiot.sh

source /IOT/driver/auto.sh   //先执行此脚本

cd  /IOT/       //再到此目录下执行下面的程序

./iot -qws&    //iot 应用程序名字,-qws ,QTwindow窗口soft程序,&后台运行

cd /

 

[root@GEC210 /]# vi /IOT/driver/auto.sh  //这些驱动是独立安装,不合进内核里,可按情况选择加载,前面加#注释掉,即不安装

insmod /IOT/driver/adc_drv.ko

#insmod /IOT/driver/buttons_drv.ko

insmod /IOT/driver/buzzer_drv.ko

#insmod /IOT/driver/led_drv.ko

insmod /IOT/driver/second.ko

insmod /IOT/driver/timer_irq.ko

insmod /IOT/driver/ov9650.ko

#insmod /IOT/driver/keypad.ko

insmod /IOT/driver/humidity.ko

 

2. 设计一个最简单的module

示例

/**********************************************************

#include <linux/module.h>

#include <linux/kernel.h>

 

static int __init gec210_led_init(void)//(入口)驱动的初始化及安装函数

{

printk("hello gec210\n"); //替代printf()

return 0;

}

 

static void __exit gec210_led_exit(void)//()

{

printk("good bye gec210\n");

}

 

module_init(gec210_led_init); //驱动的入口

module_exit(gec210_led_exit); //驱动的出口

 

//内核模块的描述

MODULE_INFO //信息

MODULE_ALLAS //别名

MODULE_PARM_DESC //参数描述

MODULE_DEVICE_TABLE  //设备条

 

//常用以下4

MODULE_AUTHOR("bobeyfeng@163.com"); //作者

MODULE_DESCRIPTION("the first demo of module"); //描述

MODULE_LICENSE("GPL"); //符合GPL协议

MODULE_VERSION("V1.0") //版本

 

*****************************************************************/

 

3. module的分析

3.1 驱动有入口有出口

module_init(gec210_led_init); //驱动的入口

module_exit(gec210_led_exit); //驱动的出口

 

3.2 模块的描述

不是必需的,但是一般都会加上。

驱动编译完成后会生成一个ko,但是我们加了module描述可以使用命令:

#modinfo *.ko

会输出驱动的作者 版本描述符合的协议......

 

3.3 __init__exit

   __init 声明该函数是一个初始化函数,该函数在编译连接的时候会放在init.text,linux执行完该函数后,后释放该函数说占用的内存。

 

/**************************************************************

示例: uboot 启动

[0.000000] Virtual kernel memory layout:

[0.000000] vector  : 0xffff0000 - 0xffff1000   (   4 kB)

[0.000000] fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)

[0.000000] DMA : 0xff000000 - 0xffe00000   (  14 MB)

[0.000000] vmalloc : 0xe0800000 - 0xfc000000   ( 440 MB)

[0.000000] lowmem  : 0xc0000000 - 0xe0000000   ( 512 MB)

[0.000000] modules : 0xbf000000 - 0xc0000000   (  16 MB)

[0.000000] .init : 0xc0008000 - 0xc008e000   ( 536 kB)

[0.000000] .text : 0xc008e000 - 0xc07d5000   (7452 kB)

[0.000000] .data : 0xc07d6000 - 0xc08345a0   ( 378 kB)

 

[   11.135623] Freeing init memory: 536K

*********************************************************************/

 

4 驱动程序的编译

  错误的用法:不要在shell 单个编译

$ arm-linux-gcc -o led_drv.ko led_drv.c

 

4.1 需要一个makefile文件

/***********************************

#Makefile 示例

obj-m += led_drv.o

#将目标文件led_drv.o(led_drv.c编译而来的),链接成一个独立module,即一个ko

 

KERNELDIR := /home/gec/linux-2.6.35.7-gec-v3.0-gt110

#定义的一个变量,该变量是linux内核源码包的路径

 

PWD:=$(shell pwd)

#获取当前Makefile的路径,该路径下有驱动源文件。

 

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

#去内核源码包的路径下找编译工具(Makefile),然后回到当前的目录下将驱动的源文件编译成一个module*.ko

 

clean:

rm -rf *.o *.mod.c *.mod.o *.ko

#删除编译后的过程文件。

*****************************************/

 

4.2 如何编译ubuntu平台使用的ko

4.2.1 Makefile

   /****************************************************

obj-m += led_drv.o

KERNELDIR := /lib/modules/$(shell uname -r)/build   //编译工具在此目录下root@ubuntu: /lib/modules/3.5.0-23-generic

PWD:=$(shell pwd)

 

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -rf *.o *.mod.c *.mod.o *.ko

*****************************************************/

4.2.2 驱动的编译信息

[@gec]$ make

make -C /home/gec/linux-2.6.35.7-gec-v3.0-gt110  M=/mnt/hgfs/driver/1module/demo/demo1  modules

make[1]: Entering directory `/home/gec/linux-2.6.35.7-gec-v3.0-gt110'

  CC [M]  /mnt/hgfs/driver/1module/demo/demo1/led_drv.o

  Building modules, stage 2.

  MODPOST 1 modules

  CC      /mnt/hgfs/driver/1module/demo/demo1/led_drv.mod.o

  LD [M]  /mnt/hgfs/driver/1module/demo/demo1/led_drv.ko

 

4.3 查看驱动的信息

$ file led_drv.ko

led_drv.ko: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), BuildID[sha1]=0x4e9bafa699a0df1eacd709d56f555260d88dd58f, not stripped

 

$ size led_drv.ko

    text     data     bss     dec     hex filename

    309     292       0     601     259 led_drv.ko

 

$ modinfo led_drv.ko

filename:       led_drv.ko

version:        V1.0

license:        GPL

description:    the first demo of module

author:         bobeyfeng@163.com

srcversion:     3B0A4B330C5A695876920D6

depends:        

vermagic:       2.6.35.7-GEC210 preempt mod_unload ARMv7

$ modinfo led_drv.ko

filename:       led_drv.ko

version:        V1.0

license:        GPL

description:    the first demo of module

author:         bobeyfeng@163.com

srcversion:     3B0A4B330C5A695876920D6

depends:        

vermagic:       2.6.35.7-GEC210 preempt mod_unload ARMv7

 

注意:

我们编译好的ko,安装环境:

软件环境:linux内核版本:2.6.35.7-GEC210

硬件环境:ARMv7

 

4.4目标硬件的信息:

# uname -r

# uname -a

Linux GEC210 2.6.35.7-GEC210 #1 PREEMPT Mon Sep 16 17:05:23 CST 2013 armv7l GNU/Linux

 

========================================================

5编译驱动使用的linux内核源码

5.1 为什么要使用内核源码?

1)设计驱动 --->我们可以使内核源码包来查看驱动程序设计过程中使用的函数原型。

2)编译驱动 --->编译驱动过程中,要使用内核源码包提供的编译工具Kbuild,用这个工具来编译驱动。

 

5.2 如何编译粤嵌发布的内核源码?

内核源码文件: linux-2.6.35.7-gec-v3.0-ft5206.tar.bz2 (据三星发布基于kernle2.6.35.7210芯片相关的源码包基础上修改)

5.2.1粤嵌做好的配置文件,解压内核源码文件,在根目录下有以下配置文件

GEC210_1024X768_CONFIG ---> VGA输出

GEC210_4.3INCH_CONFIG ---> 4.3英寸电阻屏

GEC210_7INCH_CONFIG-FT5x06   --->7英寸电容屏,电容屏的控制芯片FT5x06 (ok)

GEC210_7INCH_CONFIG-GT911 --->7英寸电容屏,电容屏的控制芯片GT911

GEC210_7INCH_CONFIG-TSC2007 --->7英寸电阻屏,电阻屏的控制器TSC2007

 

//三星提供的默认配置文件:arch/arm/configs/smdkc110_android_defconfig  (里面有条件编译选项)

 

#cp GEC210_7INCH_CONFIG-FT5x06 .config  //(据当前使用的设备选择)

5.2.2配置

#make menuconfig  //选项面板,此处不做更改,默认按GEC设置的值

注意:

make menuconfig若出现

*** Unable to find the ncurses libraries or the错误,则执行

解决方法:sudo apt-get install libncurses5-dev

 

5.2.3编译

#make -j4

/**********************************

  OBJCOPY arch/arm/boot/Image

  Kernel: arch/arm/boot/Image is ready

  AS      arch/arm/boot/compressed/head.o

  GZIP    arch/arm/boot/compressed/piggy.gzip

  AS      arch/arm/boot/compressed/piggy.gzip.o

  CC      arch/arm/boot/compressed/misc.o

  CC      arch/arm/boot/compressed/decompress.o

  SHIPPED arch/arm/boot/compressed/lib1funcs.S

  AS      arch/arm/boot/compressed/lib1funcs.o

  LD      arch/arm/boot/compressed/vmlinux

  OBJCOPY arch/arm/boot/zImage

  Kernel: arch/arm/boot/zImage is ready

***********************************/

5.2.4生成zImage

arch/arm/boot/zImage  //编译成功在此目录下生成zImage

5.3 编译驱动的内核源码的要求

1)驱动的原码必须要针对硬件平台配置过。 --->设置驱动的硬件平台

2)内核源码包需要编译过 --->内核的信息

最好:驱动安装的目标环境的源码包 (内核相同的版本),用来编译驱动。

 

6 驱动程序和应用程序的差异

6.1 驱动程序是没有main函数的。但是有相应的入口(相当于Cmain函数)

#insmod *.ko  --->系统调用module_init(s3c_adc_init)--->调用s3c_adc_init()--->初始化并安装一个驱动

 

6.2 应用程序是没有出口,但是驱动程序有出口

#rmmod * --->系统调用module_exit(s3c_adc_exit)--->调用s3c_adc_exit()---->释放驱动的资源(设备号,文件操作集,内存等),卸载驱动。

 

6.3 驱动程序的设计不能使用C的库函数

如:

#include <stdio.h>

printf()

只能使用linux内核提供的函数

 

6.4 设计驱动程序使用的头文件在linux内核源码包中。(include/linux

 

6.5 编译驱动的时候要使用linux的内核源码包

 

7 驱动的安装和卸载

7.1 安装 insmod

# insmod led_drv.ko

[  260.996066] hello gec210

 

7.2 查看内核中的驱动模块lsmod

# lsmod

led_drv 568 0 - Live 0xbf038000   -->我们安装的

 

humidity 2560 0 - Live 0xbf032000   -->/etc/profile -->upiot.sh--->/IOT/driver/auto.sh  //粤嵌的脚本

ov9650 8851 0 - Live 0xbf029000

timer_irq 2207 0 - Live 0xbf023000

second 1934 0 - Live 0xbf01d000

buzzer_drv 1414 0 - Live 0xbf017000

adc_drv 3829 0 - Live 0xbf011000

snd_soc_gec210_wm8960 3134 0 - Live 0xbf00b000

snd_soc_wm8960 19792 1 snd_soc_gec210_wm8960, Live 0xbf000000

 

[0.000000] Virtual kernel memory layout:

[0.000000] vector  : 0xffff0000 - 0xffff1000   (   4 kB)

[0.000000] fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)

[0.000000] DMA : 0xff000000 - 0xffe00000   (  14 MB)

[0.000000] vmalloc : 0xe0800000 - 0xfc000000   ( 440 MB)

[0.000000] lowmem  : 0xc0000000 - 0xe0000000   ( 512 MB)

[0.000000] modules : 0xbf000000 - 0xc0000000   (  16 MB)  //放的是ko

[0.000000]   .init : 0xc0008000 - 0xc008e000   ( 536 kB)

[0.000000]   .text : 0xc008e000 - 0xc07d5000   (7452 kB)

[0.000000]   .data : 0xc07d6000 - 0xc08345a0   ( 378 kB)

 

7.3 卸载 rmmod

# rmmod led_drv

[  887.499755] good bye gec210

 

8 printk函数

在内核中,使用printk()从控制台输出字符串,如应用程序的printf()

8.1 printk()有优先级,而printf()没有

 

: 定义一个字符串,并把字符串输出

static char banner[] __initdata = KERN_INFO \

"S5PV210 ADC driver, (c) 2010 Samsung Electronics\n";

 

printk(banner);

 

知识点1 -->static声明一个全局变量

 

知识点2 -->__initdata 修饰初始化数据,该数据使用完以后,会将该数据所占用的内存释放掉。

 

知识点3 --> \ 续行符

 

知识点4 -->KERN_INFOprintk的优先级

 

#define KERN_EMERG "<0>" /* system is unusable */

#define KERN_ALERT "<1>" /* action must be taken immediately */

#define KERN_CRIT "<2>" /* critical conditions */

#define KERN_ERR "<3>" /* error conditions */

#define KERN_WARNING "<4>" /* warning conditions */

#define KERN_NOTICE "<5>" /* normal but significant condition */

#define KERN_INFO "<6>" /* informational */

#define KERN_DEBUG "<7>" /* debug-level messages */

 

 

8.2 查看linux系统默认的优先级。

# cat /proc/sys/kernel/printk

7       4       1       7

 

7--->优先级超过7printk,可以通过控制台输出该信息

4--->printk()默认的优先级

1/7 --->写入日志的优先级范围。

 

8.3 修改linux系统默认的额优先级

#echo 6 3 2 6 >/proc/sys/kernel/printk

 

9 内核符号表

 cd /proc   //目录,动态反映linux工作过程等信息

 :作出了哪些中断,申请了哪些内存,工作了多长时间, cpu信息,内核版本,启动了哪些进程,进程的优先级,进程使用了哪些栈,进程的状态,内核符号表等

   

驱动程序Ako)使用驱动程序Bko)提供的函数。驱动程序B将该函数添加到内核符号表中,内核符号表相当于内核中一个全局的表,驱动A可以从内核符号表中拿到这个函数,使用这个函数。

 

EXPORT_SYMBOL(sym)

EXPORT_SYMBOL_GPL(sym) --->符合GPL协议的module(驱动)才可以使用内核符号表中的该符号

 

# grep add_xy -r /proc/kallsyms   //查看

bf044030 r __kstrtab_add_xy     [add]

bf044058 r __ksymtab_add_xy     [add]

 

 

A作业 //内核模块作业

1,按下开关,累计计数,以下以下哪个可以实现 计数(即变量不能存在栈中)

///-----------可以,静态变量存在内存数据段,不存在栈中--

Static 修饰局部变量,静态,变量放在内存里,不是放在栈里(函数一执行,就使用变量,给分配空间,)函数执行完后,变量的空间就会释放掉.

如用静态,第一次调用,给变量赋初始值,变量的初始值就放在内存里,第二次调用就不会给变量赋初始值,直接使用上一次给这变量赋好的值,不管函数调不调用,这变量一直在内存里.

: 有一个按键的中断服务程序,每次按一下按键中断服务程序执行一次,以下哪个可以记录中断服务次数

 

void key_isr(void)

{

static unsigned int key_cnt = 0;

key_cnt++;

}

//-------------可以,是全局变量,不会被回收

unsigned int key_cnt = 0;

void key_isr(void)

{

key_cnt++;

}

 

//-------------可以,是静态全局变量

static unsigned int key_cnt = 0;

void key_isr(void)

{

key_cnt++;

}

 

//---------------不可以,是局部变量,存在栈中,会被回收

void key_isr(void)

{

unsigned int key_cnt = 0;

key_cnt++;

}

 

//==============================

2.stdio.h  ---->在哪里???

 

 

????

gcc

arm-linux-gcc

 

//=================================

3. uImagezImage的区别????

**************************/

(1)uImage是引导器uboot专用的内核文件格式,uboot目前只能支持uImage启动,不支持zImage启动。uImage是zImage进一步压缩来的。
2)zimage,bzimage,压缩方式不一样。zimage用的zip压缩bzimage用的bzip2压缩,后者的压缩率更高,文件更小。这两种是GRUB引导程序支持的格式,也是linux的标准格式,后者更常用。

/***************************************

//===================================

4. make clean  

 

 

make distclean = make clean + 删除配置文件

 

假如:

make clean  ---> make

 

make distclean ---> #cp GEC210_7INCH_CONFIG-FT5x06 .config

                    #make menuconfig

#make

//================================

5.+= ?= := =

Makefile中的区别

 

 

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
1 =
make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
x = foo
            y = $(x) bar
            x = xyz
  在上例中,y的值将会是 xyz bar ,而不是foo bar
2 :=
:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
x := foo
            y := $(x) bar
            x := xyz
  在上例中,y的值将会是 foo bar ,而不是xyz bar了。

 

 

 

******************=

Makefile中我们经常看到= := ?= +=这几个赋值运算符,那么他们有什么区别呢?我们来做个简单的实验

新建一个Makefile,内容为:
ifdef DEFINE_VRE
    VRE = Hello World!
else
endif

ifeq ($(OPT),define)
    VRE ?= Hello World! First!
endif

ifeq ($(OPT),add)
    VRE += Kelly!
endif

ifeq ($(OPT),recover)
    VRE := Hello World! Again!
endif

all:
    @echo $(VRE)

敲入以下make命令:
make DEFINE_VRE=true OPT=define 输出:Hello World!
make DEFINE_VRE=true OPT=add 输出:Hello World! Kelly!
make DEFINE_VRE=true OPT=recover  输出:Hello World! Again!
make DEFINE_VRE= OPT=define 输出:Hello World! First!
make DEFINE_VRE= OPT=add 输出:Kelly!
make DEFINE_VRE= OPT=recover 输出:Hello World! Again!

从上面的结果中我们可以清楚的看到他们的区别了
= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值

之前一直纠结makefile中“=”和“:=”的区别到底有什么区别,因为给变量赋值时,两个符号都在使用。网上搜了一下,有人给出了解答,但是本人愚钝,看不懂什么意思。几寻无果之下,也就放下了。今天看一篇博客,无意中发现作者对于这个问题做了很好的解答。解决问题之余不免感叹,有时候给个例子不就清楚了吗?为什么非要说得那么学术呢。^_^

      1 =

      make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:

            x = foo
            y = $(x) bar
            x = xyz

      在上例中,y的值将会是 xyz bar ,而不是 foo bar 

      2 :=

      :=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。

            x := foo
            y := $(x) bar
            x := xyz

      在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。

***************************************************************/

 

 

 

 

 

 

 

//===================

6. /proc下各个文件的作用

 

1. /proc目录
Linux 内核提供了一种通过 /proc文件系统,在运行时访问内核内部数据结构 改变内核设置的机制。proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。

用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。下面列出的这些文件或子文件夹,并不是都是在你的系统中存在,这取决于你的内核配置和装载的模块。另外,在/proc下还有三个很重要的目录:netscsisysSys目录是可写的,可以通过它来访问或修改内核的参数,而netscsi则依赖于内核配置。例如,如果系统不支持scsi,则scsi目录不存在。

除了以上介绍的这些,还有的是一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的PID号为目录名,它们是读取进程信息的接口。而self目录则是读取进程本身的信息接口,是一个link

2. 子文件或子文件夹
/proc/buddyinfo 每个内存区中的每个order有多少块可用,和内存碎片问题有关

/proc/cmdline 启动时传递给kernel的参数信息

/proc/cpuinfo cpu 的信息

/proc/crypto 内核使用的所有已安装的加密密码及细节

/proc/devices 已经加载的设备并分类
/proc/dma 已注册使用的ISA DMA频道列表

/proc/execdomains Linux内核当前支持的execution domains

/proc/fb 帧缓冲设备列表,包括数量和控制它的驱动

/proc/filesystems 内核当前支持的文件系统类型

/proc/interrupts x86架构中的每个IRQ中断数

/proc/iomem 每个物理设备当前在系统内存中的映射

/proc/ioports 一个设备的输入输出所使用的注册端口范围

/proc/kcore 代表系统的物理内存,存储为核心文件格式,里边显示的是字节数,等于RAM大小加上4kb

/proc/kmsg 记录内核生成的信息,可以通过/sbin/klogd/bin/dmesg来处理

/proc/loadavg 根据过去一段时间内CPUIO的状态得出的负载状态,与uptime命令有关

/proc/locks 内核锁住的文件列表

/proc/mdstat 多硬盘,RAID配置信息(md=multiple disks)

/proc/meminfo RAM 使用的相关信息

/proc/misc 其他的主要设备(设备号为10)上注册的驱动

/proc/modules 所有加载到内核的模块列表

/proc/mounts 系统中使用的所有挂载

/proc/mtrr 系统使用的Memory Type Range Registers (MTRRs)

/proc/partitions 分区中的块分配信息

/proc/pci 系统中的PCI设备列表

/proc/slabinfo 系统中所有活动的 slab 缓存信息

/proc/stat 所有的CPU活动信息

/proc/sysrq-trigger 使用echo命令来写这个文件的时候,远程root用户可以执行大多数的系统请求关键命令,就好像在本地终端执行一样。要写入这个文件,需要把/proc/sys/kernel/sysrq不能设置为0。这个文件对root也是不可读的

/proc/uptime 系统已经运行了多久

/proc/swaps 交换空间的使用情况

/proc/version Linux 内核版本和gcc版本

/proc/bus 系统总线(Bus)信息,例如pci/usb

/proc/driver 驱动信息

/proc/fs 文件系统信息

/proc/ide ide 设备信息

/proc/irq 中断请求设备信息

/proc/net 网卡设备信息

/proc/scsi scsi 设备信息

/proc/tty tty 设备信息

/proc/net/dev 显示网络适配器及统计信息

/proc/vmstat 虚拟内存统计信息

/proc/vmcore 内核panic时的内存映像

/proc/diskstats 取得磁盘信息

/proc/schedstat kernel 调度器的统计信息

/proc/zoneinfo 显示内存空间的统计信息,对分析虚拟内存行为很有用

 

以下是/proc目录中进程N的信息

/proc/N pid N的进程信息

/proc/N/cmdline 进程启动命令

/proc/N/cwd 链接到进程当前工作目录

/proc/N/environ 进程环境变量列表

/proc/N/exe 链接到进程的执行命令文件

/proc/N/fd 包含进程相关的所有的文件描述符

/proc/N/maps 与进程相关的内存映射信息

/proc/N/mem 指代进程持有的内存,不可读

/proc/N/root 链接到进程的根目录

/proc/N/stat 进程的状态

/proc/N/statm 进程使用的内存的状态

/proc/N/status 进程状态信息,比stat/statm更具可读性

/proc/self 链接到当前正在运行的进程

 

 

 

 

 

 

 

B1代码一 //内核模块

1. Filename: led_drv.c

#include <linux/module.h>

#include <linux/kernel.h>

static int __init gec210_led_init(void) //驱动的初始化及安装函数

{

printk("hello gec210\n"); //替代printf()

return 0;

}

 

static void __exit gec210_led_exit(void)

{

printk("good bye gec210\n");

}

 

module_init(gec210_led_init); //驱动的入口

module_exit(gec210_led_exit); //驱动的出口

 

//内核模块的描述

MODULE_AUTHOR("bobeyfeng@163.com");

MODULE_DESCRIPTION("the first demo of module");

MODULE_LICENSE("GPL"); //符合GPL协议

MODULE_VERSION("V1.0");

//-------------

2. Filename: Makefile

obj-m += led_drv.o

#KERNELDIR := /lib/modules/$(shell uname -r)/build

KERNELDIR := /home/gec/linux-2.6.35.7-gec-v3.0-gt110

PWD:=$(shell pwd)

 

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -rf *.o *.mod.c *.mod.o *.ko

 

B2代码二 //内核模块

一个驱动调用另一个驱动里的函数,生成两个ko,makefile里设置好,要安装两个ko

1. Filename: add.c

#include <linux/module.h>

#include <linux/kernel.h>

int add_xy(int x,int y)

{

return (x+y);

}

EXPORT_SYMBOL(add_xy); //把一个符号出口到内核符号表里,让其它驱动可以调用,

 

static int __init gec210_led_init(void) //驱动的初始化及安装函数

{

printk("hello gec210\n"); //替代printf()

return 0;

}

 

static void __exit gec210_led_exit(void)

{

printk("good bye gec210\n");

}

 

module_init(gec210_led_init); //驱动的入口

module_exit(gec210_led_exit); //驱动的出口

 

//内核模块的描述

MODULE_AUTHOR("bobeyfeng@163.com");

MODULE_DESCRIPTION("the first demo of module");

MODULE_LICENSE("GPL"); //符合GPL协议

MODULE_VERSION("V1.0");

//-------------------------------------

 

2. Filename:  led_drv.c

#include <linux/module.h>

#include <linux/kernel.h>

extern int add_xy(int x,int y);

static int __init gec210_led_init(void) //驱动的初始化及安装函数

{

int a=10,b=20,sum;

sum = add_xy(a,b);

printk("sum=%d\n", sum); //替代printf()

return 0;

}

 

static void __exit gec210_led_exit(void)

{

printk("good bye gec210\n");

}

 

module_init(gec210_led_init); //驱动的入口

module_exit(gec210_led_exit); //驱动的出口

 

//内核模块的描述

MODULE_AUTHOR("bobeyfeng@163.com");

MODULE_DESCRIPTION("the first demo of module");

MODULE_LICENSE("GPL"); //符合GPL协议

MODULE_VERSION("V1.0");

 

3. Filename: Makefile   ,生成两个ko文件

obj-m += led_drv.o  

obj-m += add.o   

KERNELDIR := /home/gec/linux-2.6.35.7-gec-v3.0-gt110

PWD:=$(shell pwd)

 

default:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -rf *.o *.mod.c *.mod.o *.ko

 

 

0 0
原创粉丝点击