文档库 最新最全的文档下载
当前位置:文档库 › linux驱动程序进入内核

linux驱动程序进入内核

linux驱动程序进入内核
linux驱动程序进入内核

ARM-uClinux下编写加载驱动程序详细过程

本文主要介绍在uClinux下,通过加载模块的方式调试IO控制蜂鸣器的驱动程序。实验过程与上篇文章所讲的过程基本相似,更多注重细节及注意事项。

本文适合学习ARM—Linux的初学者。

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

硬件平台:MagicARM2200教学试验开发平台(LPC2290)

Linux version 2.4.24,gcc version 2.95.3

电路连接:P0.7——蜂鸣器,低电平发声。

实验条件:uClinux内核已经下载到开发板上,能够正常运行;与宿主机相连的网络、串口连接正常。

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

编写蜂鸣器的驱动程序相对来说容易实现,不需要处理中断等繁琐的过程,本文以蜂鸣器的驱动程序为例,详细说明模块化驱动程序设计的主要过程和注意事项。

一、编写驱动程序

驱动程序的编写与上文所说的编写过程基本相同,这里再详细说明一下。

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

//蜂鸣器驱动程序:beep.c文件

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

#include /*模块相关*/

#include /*内核相关*/

#include /*linux定义类型*/

#include /*文件系统 file_opertions 结构体定义*/

#include /*出错信息*/

/*PINSEL0 注意:低2位是UART0复用口,不要改动*/

#define PINSEL0 (*((volatile unsigned*) 0xE002C000))

/*P0口控制寄存器*/

#define IO0PIN (*((volatile unsigned*) 0xE0028000))

#define IO0SET (*((volatile unsigned*) 0xE0028004))

#define IO0DIR (*((volatile unsigned*) 0xE0028008))

#define IO0CLR (*((volatile unsigned*) 0xE002800C))

#define MAJOR_NUMBER 254 /*自定义的主设备号*/

#define BEEP_CMD 0 /*自定义的控制命令*/

/*函数声明*/

static int beep_open(struct inode *inode, struct file *file);

static int beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);

static int beep_release(struct inode *inode, struct file *file);

static int beep_init(void);

static void beep_cleanup(void);

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

volatile static int beep_major = MAJOR_NUMBER; /*全局变量:主设备号自定义为254*/

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

/*注册函数:

用到file_operations结构体。将蜂鸣器结构体自命名为 beep_test ,在注册模块时要用到

*/

static struct file_operations beep_test =

{

owner : THIS_MODULE,

ioctl : beep_ioctl,

open : beep_open,

release : beep_release,

}; /*注意:此处的分号(;)不要丢掉*/

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

#define BEEPCON 0x00000080

static void beep_port_init(void) //蜂鸣器端口初始化:设置P0.7口为输出,初始值为高(蜂鸣器不发声)

{

IO0DIR = BEEPCON;

IO0SET = BEEPCON;

}

static void beep(int beep_status) //蜂鸣器操作:根据参数(beep_status)状态判断是否发声

{

if(beep_status == 0)

IO0CLR = BEEPCON;

else

IO0SET = BEEPCON;

}

static int beep_open(struct inode *inode, struct file *file) //beep_test结构体中的open()函数实体,以下同

{

MOD_INC_USE_COUNT; //注册模块数加1

beep_port_init();

return 0;

}

static int beep_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

if(cmd == 0)

{

printk("beep on!\n");

beep(0);

}

else

{

printk("beep off!\n");

beep(1);

}

return 0;

}

static int beep_release(struct inode *inode, struct file *file)

{

MOD_DEC_USE_COUNT; //模块数减1

return 0;

}

static int beep_init(void) //模块加载、初始化函数:将模块加载到内核运行

{

int result;

result = register_chrdev(beep_major, "named_beep", &beep_test);

if(result < 0)

{

printk(KERN_INFO"beep: can't get major number\n");

return result;

}

if(beep_major == 0) beep_major = result;

printk(KERN_INFO"beep: init OK!\n");

/*注意:驱动程序运行在内核空间,从内核打印信息要用printk()函数而不是printf()函数,而且要配有优先级*/

return 0;

}

static void beep_cleanup(void) //模块卸载函数:将模块从内核卸载出去

{

unregister_chrdev(beep_major, "named_beep");

}

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

/*以下部分是驱动程序的关键,后面做详细说明*/

//module_init(beep_init);

//module_exit(beep_cleanup);

int init_module(void) //加载模块

{

return beep_init();

}

void cleanup_module(void) //卸载模块

{

beep_cleanup();

}

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

//驱动程序文件结束

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

以上是整个驱动程序文件的全部内容,将文件保存,这里将其命名为beep.c。整个驱动程序很简

单,只填写了几个操作函数 beep_open()、beep_release()和beep_ioctl()。其实控制蜂鸣器用

beep_ioctl()一个函数即可,其它函数基本都是空操作。

在驱动文件最后的两个函数对驱动程序来数是及其重要的。应用程序与内核的区别就是应用程序从头到尾完成一个任务,而内核则为以后处理某些请求而注册自己,完成这个任务后,他的“主”函数就立即终止。换句话说,init_module()函数(名称不能更改)是模块入口点,如同应用程序的main()函数一样,换句话说,模块入口点init_module()函数的任务就是为以后调用模块的函数做准备;

cleanup_module()函数(名称不能更改)是模块的第二个入口点,此函数仅当模块被卸载前才被调用。它的功能是去掉init_module()函数所作的事情。这两个函数由头文件声明,有关模块实现的源代码可以参见../kernel/module.c。

init_module()函数在模块被加载时执行,模块的初始化就是通过调用init_module()函数完成的。它注册驱动设备,需调用register_chrdev()函数实现。register_chrdev有3个参数:(1):希望获得的设备主号,即beep_major全局变量,如果是0,系统将选择一个没有被占用的设备号返回;(2):设备文件名,自定义设备文件名,这里用named_beep,它返回这个驱动程序所使用的主设备号;(3):用来登记驱动程序实际执行操作的函数指针,即beep_test结构体。如果登记成功,register_chrdev返回设备的主设备号;否则返回一个负值。

模块是内核的一部分,但并未被编辑到内核中,他们被分别编译和连接成目标文件。用命令insmod 插入一个模块到内核中,用命令rmmod卸载一个模块。这两个命令分别调用init_module()函数和cleanup_module()函数。关于insmod和rmmod命令,后面还会用到。

在2.3版本以后的Linux内核中,提供了一种新的方法来命名这两个函数。例如可以定义

beep_init()和beep_cleanup()两个函数,然后在源代码文件末尾使用下面的语句,其效果是一样的。

module_init(beep_init);

module_exit(beep_cleanup);

注意:这两个宏是在中被定义的,所以源码文件中必须包括这个头文件。而且,这两行语句必须在函数声明后使用,否则会编译出错。

驱动程序部分先暂且介绍到这,继续往下介绍,如何将驱动程序加载到内核中去,又如何利用驱动程序来控制蜂鸣器发声。

二、编译驱动程序

编译驱动程序的过程比较无聊,按照步骤一步一步进行即可。但首先需要了解linux的基本操作命令,最好会Makefile文件的编写,至少能看懂也行。

下面一步一步的介绍:

1、将驱动程序beep.c文件传到宿主机中。

这里所说的“宿主机”是运行Linux的PC机,可以是安装了Linux操作系统的本地机,亦可以是

Linux服务器。由于嵌入式Linux的开发板资源有限,不可能在开发板上运行开发和调试工具。统称需要交叉编译调试的方式进行,即“宿主机+目标板”的形式。程序在宿主机上编译—连接—定位,得到的可执行文件则在目标板上运行。而“目标板”就是实验的硬件平台MagicARM2200教学试验开发平台。

本实验是在PC机上通过虚拟机搭建的宿主机。目标板和宿主机通过串口和网口连接,其中串口当作终端,作为人机交互界面。若目标板可以看成一台计算机的话,那么串口终端就相当于这台计算机的显示器,通过linux命令对目标板进行相关操作;而网口是与宿主机相连接,作为数据传输、共享的通道。这里利用linux的NFS服务器将宿主机系统下/home/armwork目录作为共享目录,在目标板上通过mount

命令将此目录挂在到目标板上的/mnt目录下,于是打开目标板的/mnt目录所见的内容就是宿主机上

/home/armwork目录的内容。

当然以上所说的内容包括宿主机的建立、交叉开发环境(arm-elf-gcc)的安装、uClinux系统移植、网卡串口驱动、嵌入TCP/IP协议栈等工作都已经做好,这里只是利用这一平台介绍驱动程序的编写。而且这些工作步骤也比较单调,可以很容易找到现成的步骤说明,这里就不做过多说明了。

说了一堆前提条件,现在开始继续。下面的工作都是在宿主机上进行的。

前面所说的beep.c驱动文件是在Windows环境下编写的(当然也可以在Linux下编写,如用vi 编写),使用SSH Secure或FlashFXP等FTP工具,将beep.c文件上传到宿主机中,先在宿主机的

/home/armwork目录下建立一个新目录命名为beep。在宿主机的终端命令行上输入下面两条命令:(这里假定宿主机中已经存在有/home/armwork目录,当然也可以直接在图形编辑环境下新建目录)

# cd /home/armwork

# mkdir beep

# cd beep

这三条命令意思分别为:将/home/armwork目录指定为当前目录;在当前目录下建立beep目录;将beep 目录指定为当前目录。

然后,利用FTP工具将beep.c文件上传到刚刚建立的beep目录下,输入 ls 命令显示当前目录下的内容:

# ls -l

(命令均为为字母l,不是数字1)显示内容为文件的详细信息:

-rw-r--r-- 1 root root 2891 5月 5 18:12 beep.c

依次为操作权限、用户、文件大小、日期、文件名等信息。

2、编写Makefile文件。

以下是Makefile文件的详细内容,将其保存命名为Makefile(文件名不能更改)

#---------------------------------------------------------------------------------#

#各项对应驱动程序的文件名。

EXEC = beep

OBJS = beep.o

SRC = beep.c

#交叉环境所在的目录,根据各自机器存放位置修改。

INCLUDE = /usr/src/uClinux-dist/linux-2.4.x/include

#所使用的交叉环境

CC = arm-elf-gcc

LD = arm-elf-ld

MODCFLAGS = -D__KERNEL__ -I$(INCLUDE) -Wall -O2 -fno-strict-aliasing -fno-common -pipe

-fno-builtin -D__linux__ -g -DNO_MM -mapcs-32 -march=armv4 -mtune=arm7tdmi -mshort-load-bytes -msoft-float -nostdinc -iwithprefix include

LDFLAGS = -m armelf -r

all: $(EXEC)

$(EXEC): $(OBJS)

$(LD) $(LDFLAGS) -o $@ $(OBJS)

%.o:%.c

$(CC) $(MODCFLAGS) -mapcs -c $< -o $@

clean:

-rm -f $(EXEC) *.elf *.gdb *.o

#---------------------------------------------------------------------------------#

其中代码的含义这里不做详细讲解,其作用就是将beep.c文件编译生成beep.o文件和beep可执行文件。关于Makefile文件的编写,可以参考相关资料,这里不对写法做详细说明。

3、编译驱动程序。

用同样的方法,将Makefile文件上传到宿主机的beep目录下。可以利用 ls 命令查看目录内容。确定文件正确并传输成功,在beep目录下输入make命令编译。

# make

显示如下结果:

arm-elf-gcc -D__KERNEL__ -I/usr/src/uClinux-dist/linux-2.4.x/include -Wall -O2

-fno-strict-aliasing -fno-common -pipe -fno-builtin -D__linux__ -g -DNO_MM -mapcs-32

-march=armv4 -mtune=arm7tdmi -mshort-load-bytes -msoft-float -nostdinc -iwithprefix include -mapcs -c beep.c -o beep.o

arm-elf-ld -m armelf -r -o beep beep.o

make命令是在当前目录下找到Makefile文件,并对Makefile文件的代码进行解析、执行。而Makefile文件就类似于DOS下的批处理文件。如果遇到问题请查看Makefile文件、操作权限等是否正确。

如果一切顺利,那么驱动程序就编译成功了,beep目录下会多出几个文件,用 ls 命令查看:

# ls -l

显示如下:

-rw-r--r-- 1 root root 86762 5月 6 09:35 beep

-rw-r--r-- 1 root root 2891 5月 5 18:12 beep.c

-rw-r--r-- 1 root root 86624 5月 6 09:35 beep.o

-rw-r--r-- 1 root root 547 5月 5 14:35 Makefile

其中beep文件即为可执行文件。后面介绍要加载到模块的文件就是此文件。

三、加载模块到内核

前面已经把驱动程序beep.c编译成可执行文件beep,那么这个beep可执行文件即为要加载的所谓的“模块”。既然模块已经做好,下面的工作就轻松了,加载工作非常简单。加载模块的工作是在目标板上进行的,因为我们所要做的就是为目标板做驱动程序,所要加载的模块是要加载到目标板上的uClinux 内核中。宿主机与目标板上都运行着linux系统,而其用途是不同的,这一点一定要注意,不要混淆。这里再强调一遍:宿主机的Linux系统安装有编译调试工具,为的是编译C语言程序,生成目标文件(.o文件)和可执行文件。而目标板上的uClinux系统是为实际应用所做的系统,它仅仅是为了直接运行宿主机所生成的可执行代码。这样做的目的就是为了节省目标板的硬件开销,或者说是为了完成在目标板上不可能完成的工作,即编译调试程序。

首先运行目标板,成功运行uClinux系统,并成功把宿主机上的/home/armwork目录挂在到目标板的/mnt目录下。这一步的作用前面已经说过,是为了让目标板共享宿主机上的/home/armwork目录,即要想打开宿主机上的/home/armwork目录,只要打开目标板上的/mnt目录就可以了。于是前面所编译生成的beep可执行文件就可以直接通过这个目录获取了。

以下操作都是对目标板进行的,这就需要通过串口的人机终端进行操作。首先连接好串口数据线。若在Windows下,则打开超级终端(开始->所有程序->附件->通讯->超级终端),新建一个超级终端并设置参数使之与目标板相匹配。若在宿主机Linux下,则启动minicom(调整好终端命令行的大小后,输入minicom命令)根据minicom的提示,按CTRL+A,松开后再按Z,进入minicom配置界面,同样要配置成

与目标板相匹配的参数。以下操作都是在超级终端或minicom下进行输入的。

接下来,在目标板上建立设备节点,输入如下命令:

> cd /mnt/beep

> rm -f /dev/beep

> mknod /dev/beep c 254 0

这两行命令分别为:设置/mnt/beep目录为当前目录;强行删除原有相同名称的设备节点;创建名为beep 的设备节点,类型为字符型设备,主设备号为254,从设备号为0。

因为/mnt目录已经被挂在到宿主机的/home/armwork目录了,那么查看/home/armwork目录下的文件就可以通过查看/mnt目下的文件方式实现了。

从命令中能够看出,设备节点是存储在/dev目录下的,可以通过下面命令查看系统已经建立了哪些设备节点。

> ls /dev

接下来,加载模块到内核,使用insmod命令

> insmod beep

这一命令将当前目录(/mnt/beep目录)下的beep刻执行文件加载到内核中,执行insmod命令,即调用init_modele()函数,显示结果如下:

Using beep

beep: init OK!

第一句是系统提示的输出,后一句是在驱动程序的init_modele()函数中执行beep_init()函数实现的输出,可以根据需要修改beep_init()函数。

以上工作需要多次输入命令,操作繁琐,容易出错。要解决这一问题可以将以上输入的命令编写到一起,保存为一个文本文件,如下:

#!/bin/sh

rm -f /dev/beep

mknod /dev/beep c 254 0

insmod beep

将以上代码保存自命名为loadbeep文件,要加载模块的时候只需执行loadbeep文件即可。

> ./loadbeep

注意:是“.”和“/”后面跟文件名,表示执行此文件。执行此文件等同于执行以上命令。同时还用注意权限问题,如果出现“./loadbeep: Permission denied ”提示信息,表示目标板没有对宿主机文件执行的权限。这时需要在宿主机上修改loadbeep文件的使用权限,在宿主机的root用户(linux下拥有最好权限的用户)下输入以下命令:

# chmod 755 loadbeep

这样,其它用户就拥有执行该文件的权限了。其中命令前的“#”表示root用户,“$”表示其它用户。

若模块使用后,不再需要,则可以使用rmmod命令卸载模块:

> rmmod beep

这一命令将调用cleanup_module()函数。

若要查看当前已经加载过的设备模块,可以使用lsmod命令查看:

> lsmod

这一命令只是输出的是/proc目录下的modules文件,当然可以用cat命令直接查看该文件。

至此,模块加载工作也完成了。

四、编写应用程序,测试驱动模块

编写测试应用程序和编写驱动程序的过程基本相同,这里不再重复,程序代码如下:

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

//测试程序:main.c文件

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

#include

main()

{

int fd;

int i;

fd = open("/dev/beep", O_RDONLY);

/*打开设备文件beep,O_RDONLY表示以只读方式打开,并会调用驱动程序中的beep_open()函数*/

if(fd == -1) //若打开失败,则报告出错,退出

{

printf("Can not open file\n");

exit(-1);

}

for(i=0; i<3; i++) //让蜂鸣器每隔1秒响一次,共响三次

{

ioctl(fd, 0, 0); //IO操作函数,指令码为0,调用驱动程序中的beep_ioctl()函数,控制蜂鸣器发声

sleep(1); //Linux系统函数,让进程暂停一段时间,可用于延时,时间单位是秒

ioctl(fd, 1, 0); //IO操作函数,指令码为1,调用驱动程序中的beep_ioctl()函数,控制蜂鸣器停止发声

sleep(1);

}

close(fd); //关闭设备文件,并会调用驱动程序中的beep_release()函数

printf("Success!\n"); //用户程序运行在用户空间,打印信息用printf()函数

return(0);

}

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

//测试程序文件结束

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

测试程序完成,下面将测试程序按照上传驱动程序的方法上传到宿主机中。

在宿主机的/home/armwork目录下新建一个目录,这里命名为exc目录。将测试程序main.c上传到这个目录下。下面编写编译测试程序的Makefile文件。

#---------------------------------------------------------------------------------#

EXEC = main

OBJS = main.o

SRC = main.c

CC =arm-elf-gcc

BASEPATH =/usr/src/uClinux-dist

LIBPATH =$(BASEPATH)/lib

LLIBPATH =$(LIBPATH)/uClibc/lib

INCLUDEPATH =$(BASEPATH)/linux-2.4.x/include

LDFLAGS =-Os -g -Dlinux -D__linux__ -Dunix -D__uClinux__ -DEMBED

LDLIBS =-I$(LIBPATH)/uClibc/include -I$(LIBPATH)/libm -I$(LIBPATH)/libcrypt_old -I$(BASEPATH) -fno-builtin -nostartfiles -D__PIC__ -fpic -msingle-pic-base -I$(INCLUDEPATH)

LDLIBS_EXEC =-Wl,-elf2flt $(LLIBPATH)/crt0.o $(LLIBPATH)/crti.o $(LLIBPATH)/crtn.o

-L$(LIBPATH)/uClibc/. -L$(LLIBPATH) -L$(LIBPATH)/libm -L$(LIBPATH)/libnet -L$(LIBPATH)/libdes -L$(LIBPATH)/libaes -L$(LIBPATH)/libpcap -L$(LIBPATH)/libcrypt_old -L$(LIBPATH)/libssl

-L$(LIBPATH)/zlib -lc

LDLIBS_OBJS =-c

all: $(EXEC)

$(EXEC): $(OBJS)

$(CC) $(LDFLAGS) $(LDLIBS) $(LDLIBS_EXEC) -o $@ $(OBJS)

%.o:%.c

$(CC) $(LDFLAGS) $(LDLIBS) $(LDLIBS_OBJS) -c $< -o $@

clean:

-rm -f $(EXEC) *.elf *.gdb *.o

#---------------------------------------------------------------------------------#

保存并命名为Makefile(文件名不能更改),将当前目录设置为/home/armwork/exc目录,上传Makefile文件到当前目录中,输入make命令,编译测试程序main.c文件,生成main.o目标文件和main 可执行文件。显示输出以下结果:

arm-elf-gcc -Os -g -Dlinux -D__linux__ -Dunix -D__uClinux__ -DEMBED

-I/usr/src/uClinux-dist/lib/uClibc/include -I/usr/src/uClinux-dist/lib/libm

-I/usr/src/uClinux-dist/lib/libcrypt_old -I/usr/src/uClinux-dist -fno-builtin -nostartfiles -D__PIC__ -fpic -msingle-pic-base -I/usr/src/uClinux-dist/linux-2.4.x/include -c -c main.c -o main.o

arm-elf-gcc -Os -g -Dlinux -D__linux__ -Dunix -D__uClinux__ -DEMBED

-I/usr/src/uClinux-dist/lib/uClibc/include -I/usr/src/uClinux-dist/lib/libm

-I/usr/src/uClinux-dist/lib/libcrypt_old -I/usr/src/uClinux-dist -fno-builtin -nostartfiles -D__PIC__ -fpic -msingle-pic-base -I/usr/src/uClinux-dist/linux-2.4.x/include -Wl,-elf2flt

/usr/src/uClinux-dist/lib/uClibc/lib/crt0.o /usr/src/uClinux-dist/lib/uClibc/lib/crti.o

/usr/src/uClinux-dist/lib/uClibc/lib/crtn.o -L/usr/src/uClinux-dist/lib/uClibc/.

-L/usr/src/uClinux-dist/lib/uClibc/lib -L/usr/src/uClinux-dist/lib/libm

-L/usr/src/uClinux-dist/lib/libnet -L/usr/src/uClinux-dist/lib/libdes

-L/usr/src/uClinux-dist/lib/libaes -L/usr/src/uClinux-dist/lib/libpcap

-L/usr/src/uClinux-dist/lib/libcrypt_old -L/usr/src/uClinux-dist/lib/libssl

-L/usr/src/uClinux-dist/lib/zlib -lc -o main main.o

编译后,该目录多出几个文件。用 ls 命令查看详细文件信息,显示结果如下:

-rwxr--r-- 1 root root 29464 5月 6 11:34 main

-rw-r--r-- 1 root root 515 5月 5 17:31 main.c

-rwxr-xr-x 1 root root 742336 5月 6 11:34 main.gdb

-rw-r--r-- 1 root root 6828 5月 6 11:34 main.o

-rw-r--r-- 1 root root 951 5月 5 14:42 Makefile

从显示结果可以看出,现在的main可执行文件只有宿主机的root用户拥有可执行权限,其它用户只拥有只读权限,使用chmod命令更改权限:

# chmod 755 main

用 ls 命令查看修改后的文件详细信息为:

-rwxr-xr-x 1 root root 29464 5月 6 11:34 main

这样,目标板也拥有对该文件的可执行权限了。

现在回过头来再看目标板,通过超级终端,设置当前目录为/mnt/exc目录,执行main文件(输入./main命令),一切正常则可以听到测试程序所设计的:蜂鸣器每秒响一声,共响三声,同时超级终端有如下显示输入:

beep on!

beep off!

beep on!

beep off!

beep on!

beep off!

Success!

其中最后一条“Success! ”是在测试程序主函数里倒数第二条代码实现的(见前面的测试程序),其它显示是在驱动程序中beep_ioctl()函数里实现的。

至此,测试工作完成。

五、总结

本文从编写驱动程序开始到编译驱动程序、加载模块一直到测试驱动程序,详细的介绍了如何在ARM的uClinux系统环境下加载模块化驱动程序及具体实现过程,完整阐述了模块化驱动程序的编写方法及注意事项,对ARM-Linux的初学者来说能起到一定的引导作用。而本文对Makefile文件的编写及分析没有进行介绍,在以后的文章中会详细介绍Makefile文件的编写。以上所完成的实验过程是在MagicARM2200

教学试验开发平台实验测试通过的,所将内容大多是我的个人理解,而我也只是初学者,因此纰漏在所难免,也望各位读者指教。

全文完

Linux下编写驱动程序

2008年05月01日星期四 18:44

摘要:设备驱动程序是操作系统内核与机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节。那么驱动程序如何书写实现这一接口功能是本文讨论的重点,并以一简单的驱动程序介绍书写细节。

在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。(应用程序一般是在用户态下进行)也就是说系统必须在驱动程序的子函数返回后才能进行其它的工作,即驱动程序不能进入死循环。

字符型设备驱动程序的编写包含一下信息:

#define _NO_VERSION_

#include

#include

char kernel_version[]=UTS_RELEASE

这段定义了一些版本信息,虽然用处不大,但也必不可少。

最好要包含。由于用户进程是通过设备文件同硬件打交道,对设备文件的操作不外乎就是一些系统调用,如open,read,write,close……,(注意,不是fopen,fread,)但是如何把系统调用和驱动程序联系起来呢?这需要了解一个非常关键的数据结构:

struct file_opertions{

int(*seek)(struct inode*, struct file*, off_t, int);/*文件定位*/

int(*read)(struct inode*, struct file*, char, int);/*读取数据*/

int(*write)(struct inode*, struct file*, off_t, int);/*写数据*/

int(*readdir)(struct inode*, struct file*, struct dirent*, int);/*读取相关目录*/

int(*select)(struct inlde*, struct file*, int, select_table*);/*非阻塞设备访问*/

int(*ioctl)(struct inlde*, struct file*, unsigned int, unsigned long);

int(*mmap)(struct inlde*, struct file*, struct vm_area_struct*);

int(*open)(struct inlde*, struct file*);

int(*release)(struct inlde*, struct file*);

int(*fsync)(struct inlde*, struct file*);/*强制同步*/

int(*fasync)(struct inlde*, struct file*);

int(*check_media_change)(struct inlde*, struct file*);

int(*revalidata)(dev_t dev);/*使设备重新有效*/

}

其中read,write,open,close(release),ioctl是最核心的,必须实现的。

这个结构体的每个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备注册程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。既然是这样,则编写设备驱动程序的主要工作就是编写子函数,并填充file_operatons的各个域。

以下是简单的字符型设备的驱动程序编写方式,例子程序并不牵扯到具体设备,只是个编写框架。

#include //Linux基本类型定义

#include //文件系统相关头文件

#include //memmory management内存管理

#include //错误代码

#include //汇编文件

unsigned int test_major = 0; /*定义一个主设备号(主设备号、从设备号在Linux设备管理中有相关介绍)*/

static int read_test(struct inode *inode, struct file *file, char *buf, int count)

{

/*本函数对应于file_opertions中read的实现,函数名自己定义。inode为设备节点,file为设备文件描述符(open()打开后自动或得),buf为数据缓冲区,count为数据传送个数。“static ”这里修饰函数名表示函数只在本文件中有

效。这里函数只实现简单数据拷贝功能。*/

int left;

if(verify_area(VERIFY_WRITE, buf, count) == -EFAULT) //验证缓存中的数据是否有效

return -EFAULT; //错误码,在 包含

for(left=count; left>0; left--)

{

__put_user(1, buf, 1);

/* “ __”表示内核调用函数,此函数表示把数据从内核空间放到用户空间,参数依次表示:填充数、用户空间、数据量。*/

buf++;

}

return count;

}

这个函数是为read调用准备的。当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf是read调用的一个参数。它是用户进程空间的一个地址。但是在read_test被调用时,系统进入核心态(内核空间),必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数,参考内核调用接口函数。在向用户空间拷贝数据之前,必须验证buf空间是否可用。这就用到verify_area()。

static int write_test(struct inode *inode *inode, struct file *file, const char *buf, int count)

{

return count;

}

写数据函数,具体没有实现,直接返回计数值。

static int open_test(struct inode *inode, struct file *file)

{

MOD_INC_USE_COUNT; //宏:注册模块数加1

return 0; //返回0表示成功,根据函数自己定义。

}

这个函数比较简单,它不牵扯到设备文件,仅将模块数加1。

static void release_test(struct inode *inode, struct file *file)

{

MOD_DEC_USE_COUNT; //模块数减1

}

以上实现四个函数,后三个函数都是空操作,实际调用发生时什么也不做,它们仅仅为file_operations结构体提供函数指针。

下面开始注册刚刚写好的函数

struct file_operations test_fops =

/*file_operations结构体名,test_fops结构体对象*/

{

NILL, /*seek*/

read_test,

write_test,

NULL, /*test_readdir*/

NULL, /*test_mmap*/

open_test,

release_test,

NULL, /*test_fsvnc*/

NULL, /*test_fasync*/

/* 其它位置均填为空NILL*/

};

设备驱动程序的主体可以说是写好了,现在把驱动程序嵌入内核。驱动程序可用按照两种方式编译。一种是编译进内核(kernel),另一种是编译成模块(modules)如*.o文件,如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。

1、登记注册设备:

方式一:编译进内核,利用函数init_module()

int init_module(void)

{

int result;

result = register_chrdev(0, "test", &test_fops);

/*内核函数:注册一个字符型设备到内核中去。参数:指定设备号(0:表示内核根据主设备号获得并返回给result)、设备名、设备结构体名*/

if(result < 0)

{

printk(KERN_INFO"test:: can't get major number\n");

/*在内核空间驱动程序打印数据,参数:打印优先级、打印信息*/

return result;

}

if(test_major == 0) test_major = result;

return 0;

}

方式二:编译加载模块方式,利用insmod命令,在用insmod命令将编译好的模块调用内存时,init_module()函数被调用。在这里,init_module()函数只做了

一件事,就是向系统的字符设备表登记了一个字符设备。

register_chrdev()需要三个参数,参数一是希望获得的设备号,如果是0,系统将选择一个没有被占用的设备号返回。参数二是设备文件名,参数三用来登记驱动程序实际执行操作的函数指针。如果登记成功,返回设备的主设备号,不成功,返回一个负数。

2、卸载设备:

void cleanup_module(void)

{

unregister_chrdev(test_major, "test");

}

在用rmmod卸载模块时,cleanup_module()函数被调用,它释放字符设备test在系统字符设备表中占有的表项。

至此,一个及其简单的字符设备可以说写好了,为以下叙述方便,命名文件为test.c。

上文讲到驱动程序已经基本写好,并命名为test.c文件,下面进行编译:

$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c

注释:-O2表示优化等级,-DMODULE表示编译成模块,-D__KERNEL__表示加载到内核的某个模块, -c表示编译生成test.o文件(2.4版本)

得到的文件test.o就是一个设备驱动程序。如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后进行链接

$ ld -r file1.o file2.o -o <模块名>

驱动程序已经编译好了,现在把它安装到系统中去。

$ insmod -f test.o

注释:-f表示强制加载,test.o为模块名

如果安装成功,在/proc/devices文件中就可以看到设备test,并可以看到它的设备号。要卸载的话,运行

$ rmmod test

下一步要创建设备节点

$ mknod /dev/test c 主设备号从设备号

注释:c表示字符型设备,主设备号就是在/proc/devices里看到的。用shell 命令打印全部设备,就可以获得主设备号。

$ cat /proc/device

我们现在可以通过设备文件来访问我们的驱动程序。写一个测试程序。

#include

#include

#include

#include

main()

{

int testdev;

int i;

char buf[10];

testdev = open("/dev/test", O_RDWR);

/*open()函数首先为打开文件分配文件句柄fd,然后再为打开的文件在文件表中分配一个空闲文件结构项,然后让刚分配的文件句柄fd的文件结构指针指向搜索到的文件结构,然后调用namei()取得对应文件i节点,然后让文件结构与这个i节点结构相关联。i节点中包含有该文件所代表的主设备号和子设备号,还有它属于什么类型文件(如普通文件、目录文件、字符设备文件、块设备文件、管道文件等)。*/

if(testdev == -1)

{

printf("Cann't open file \n"); //用户空间使用printf(),内核空

linux内核升级图文攻略

linux内核升级图文攻略 一、Linux内核概览Linux是一个一体化内核(monolithic kernel)系统。设备驱动程序可以完全访问硬件。Linux内的设备驱动程序可以方便地以模块化(modularize)的形式设置,并在系统运行期间可直接装载或卸载。1. linux内核linux 操作系统是一个用来和硬件打交道并为用户程序提供一个 有限服务集的低级支撑软件。一个计算机系统是一个硬件和软件的共生体,它们互相依赖,不可分割。计算机的硬件,含有外围设备、处理器、内存、硬盘和其他的电子设备组成计算机的发动机。但是没有软件来操作和控制它,自身是不能工作的。完成这个控制工作的软件就称为操作系统,在Linux的术语中被称为“内核”,也可以称为“核心”。Linux内核的主要模块(或组件)分以下几个部分:. 进程管理(process management) . 定时器(timer). 中断管理(interrupt management). 内存管理(memory management). 模块管理(module management). 虚拟文件系统接口(VFS layer). 文件系统(file system). 设备驱动程序(device driver). 进程间通信(inter-process communication). 网络管理(network management. 系统启动(system init)等操作系统功能的实现。2. linux内核版本号Linux内核使用三种不同的版本编号方式。. 第一种方

式用于1.0版本之前(包括1.0)。第一个版本是0.01,紧接着是0.02、0.03、0.10、0.11、0.12、0.95、0.96、0.97、0.98、0.99和之后的1.0。. 第二种方式用于1.0之后到2.6,数字由三部分“A.B.C”,A代表主版本号,B代表次主版本号,C代表较小的末版本号。只有在内核发生很大变化时(历史上只发生过两次,1994年的1.0,1996年的2.0),A才变化。可以通过数字B来判断Linux是否稳定,偶数的B代表稳定版,奇数的B代表开发版。C代表一些bug修复,安全更新,新特性和驱动的次数。以版本2.4.0为例,2代表主版本号,4代表次版本号,0代表改动较小的末版本号。在版本号中,序号的第二位为偶数的版本表明这是一个可以使用的稳定版本,如2.2.5; 而序号的第二位为奇数的版本一般有一些新的东西加入,是个不一定很稳定的测试版本,如2.3.1。这样稳定版本来源于上一个测试版升级版本号,而一个稳定版本发展到完全成熟后就不再发展。. 第三种方式从2004年2.6.0版本开始,使用一种“time-based”的方式。 3.0版本之前,是一种“A.B.C.D”的格式。七年里,前两个数字A.B即“2.6”保持不变,C随着新版本的发布而增加,D代表一些bug修复,安全更新,添加新特性和驱动的次数。3.0版本之后是“A.B.C”格式,B随着新版本的发布而增加,C代表一些bug修复,安全更新,新特性和驱动的次数。第三种方式中不使用偶数代表稳定版,奇数代表开发版这样的命名

Linux kernel内核升级全过程,教你一次成功

序言 由于开发环境需要在linux-2.6内核上进行,于是准备对我的虚拟机上的Linux系统升级。没想到这一弄就花了两天时间( 反复装系统,辛苦啊~~),总算把Linux系统从2.4.20-8内核成功升级到了2.6.18内核。 网上虽然有很多介绍Linux内核升级的文章,不过要么过时,下载链接失效;要么表达不清,不知所云;更可气的是很多 文章在转载过程中命令行都有错误。刚开始我就是在这些“攻略”的指点下来升级的,以致于浪费了很多时间。 现在,费尽周折,升级成功,心情很爽,趁性也来写个“升级攻略”吧!于是特意又在虚拟机上重新安装一个Linux系统 ,再来一次完美的升级,边升级边记录这些步骤,写成一篇Linux内核升级记实录(可不是回忆录啊!),和大家一起分享 ~~! 一、准备工作 首先说明,下面带#号的行都是要输入的命令行,且本文提到的所有命令行都在终端里输入。 启动Linux系统,并用根用户登录,进入终端模式下。 1、查看Linux内核版本 # uname -a 如果屏幕显示的是2.6.x,说明你的已经是2.6的内核,也用不着看下文了,该干什么干什么去吧!~~~如果显示的是 2.4.x,那恭喜你,闯关通过,赶快进行下一步。 2、下载2.6内核源码 下载地址:https://www.wendangku.net/doc/5817981334.html,/pub/linux/kernel/v2.6/linux-2.6.18.tar.bz2 3、下载内核升级工具 (1)下载module-init-tools-3.2.tar.bz2 https://www.wendangku.net/doc/5817981334.html,/pub/linux/utils/kernel/module-init-tools/module-init-tools-3.2.tar.bz2 (2)下载mkinitrd-4.1.18-2.i386.rpm https://www.wendangku.net/doc/5817981334.html,/fedora/linux/3/i386/RPMS.core/mkinitrd-4.1.18-2.i386.rpm (3)下载lvm2-2.00.25-1.01.i386.rpm https://www.wendangku.net/doc/5817981334.html,/fedora/linux/3/i386/RPMS.core/lvm2-2.00.25-1.01.i386.rpm (4)下载device-mapper-1.00.19-2.i386.rpm https://www.wendangku.net/doc/5817981334.html,/fedora/linux/3/i386/RPMS.core/device-mapper-1.00.19-2.i386.rpm (2.6.18内核和这4个升级工具我都有备份,如果以上下载地址失效,请到https://www.wendangku.net/doc/5817981334.html,/guestbook留下你的邮箱,我给你发过去)

ubuntu12.04 升级内核实战

ubuntu12.04 升级内核实战 ubuntu 12.04内核是linux 3.2.0-24,其实升级到最新版本3.3.4也没什么很大意义,主要是集成了一些新的驱动和一些普通用户用不到的功能,所以基本上本文纯属折腾,但不要随便升级当班设备啊!好了,不废话了,我们开始........... 首先是准备条件: ①、有一台装有ubuntu 12.04的机器 ②、先移步到https://www.wendangku.net/doc/5817981334.html,/下载linux稳定版内核 ③、拥有root权限 ④、并将下载好的内核解压到/usr/src下,使用命令如下: #tar jxvf linux-3.3.4.tar.bz2 这样你就可以得到一个名叫linux-3.3.4 好,现在一切都准备好了,接下来就开始配置,编译,安装新内核吧!1,进入刚才的文件夹/usr/src/linux-3.3.4,输入命令:$ make mrproper 该命令的功能在于清除当前目录下残留的.config和.o文件,这些文件一般是以前编译时未清理而残留的。而对于第一次编译的代码来说,不存在这些残留文件,所以可以略过此步,但是如果该源代码以前被编译过,那么强烈建议执行此命令,否则后面可能会出现未知的问题。2,配置编译选项 作为操作系统的内核,其内容和功能必然非常繁杂,包括处理器调

度,内存管理,文件系统管理,进程通讯以及设备管理等等,而对于不同的硬件,其配置选项也不相同,所以在编译源代码之前必须设置编译选项。其实我觉得这一步是升级内核整个过程中最有技术含量的,因为要根据自己的需要正确选择yes or no需要对计算机方方面面的知识都有所了解。但是这里的选项实在是太多了,大概有几百项之多,我以前曾尝试着一项一项的选,但是最后还是放弃了,因为有很多选项不是很明白。 既然这样,难道没有什么简便的方法么?当然有!那就是make menuconfig 或者make xconfig。我使用的是make menuconfig,但是前提条件是要装ncurses。 ncurses 到https://www.wendangku.net/doc/5817981334.html,/pub/gnu/ncurses/下载,可以放到任何目录进行安装: tar zxvf ncurses.tar.gz #解压缩并且释放文件包 cd ncurses #进入解压缩的目录(注意版本) ./configure #按照你的系统环境制作安装配置文件 make #编译源代码并且编译NCURSES库 su root #切换到root用户环境 make install #安装编译好的NCURSES库 另外,在make menuconfig过程中也会有一些选项需要你来设置

redhat5.8升级内核版本培训资料

r e d h a t5.8升级内核 版本

一、升级背景 前段时间公司有个项目用到了短信收发的业务,采购了两台16口的Wavecom USB短信猫设备,服务器操作系统是ReadHat5.4,内核2.6.18,插上设备后,操作系统无法自动识别该设备,原因是没有预装该设备USB转串口的驱动程序,可能是只有这个产品不能识别,因为曾经我用过单口的GSM MODEM短信猫测试,可以自动识别出来。后来从供应商处得到信息,说是他们这个产品比较新,版本低的内核没有预装新的USB转串口驱动程序,但现在2.6.32以上内核都自带了USB转串口的驱动,所以最后通过升级系统内核的方式解决了这个问题。 二、升级测试环境 宿主机:Window xp 虚拟机:VM8.0.2 OS:CentOS 5.8 Final 内核(升级前):2.6.18 所有操作步聚使用root权限 三、升级步聚 1、下载内核 到https://www.wendangku.net/doc/5817981334.html,下载一个新版本内核源码,当前最新稳定版为3.3.4。这里下载的是: https://www.wendangku.net/doc/5817981334.html,/pub/linux/kernel/v2.6/longterm/v2.6.35/linux-2.6.35.13.tar.bz2

2、解压内核文件 将linux-2.6.35.13.tar.bz2上传到/usr/local/src目录下,使用tar -jxvf linux-2.6.35.13.tar.bz2命令解压,得到linux-2.6.35.13目录 3、清除文件 cd linux-2.6.35.13(下面所有操作都是在此目录,除非切换了新的目录) make distclean 清除以前编译内核生成的所有文件(除了清除可执行文件和目标文件外,configure所产生的Makefile也会清除掉) 如果是第一次编译,这步聚可以省略 4、复制配置文件 将系统默认的内核配置文件复制到linux-2.6.35.13目录下,并命名.config cp /boot/config-2.6.18-308.el5 .config 5、内核配置(make menuconfig) 内核配置,有三种方式: a)、make config:基于文本的最为传统的配置界面,不推荐使用 b)、make menuconfig:基于文本选单的配置界面,字符终端下推荐使用。 注意:使用make menuconfig 需要安装ncurses(yum -y install ncurses-devel),如果未安装会报如下错误:

RedHat5 内核升级指南

RedHat5.3 升级内核到2.6.33 版本

错误:insmod: error inserting '/lib/dm-region-hash.ko' : -1 File exists 编译2.6.31内核后重启出现 insmod: error inserting '/lib/dm-region-hash.ko' : -1 File exists 解决方法: 1,解压initrd文件 [root@bogon ~]# cp /boot/initrd-2.6.30.4.img /tmp [root@bogon ~]# cd /tmp/ [root@bogon tmp]# ls initrd-2.6.30.4.img [root@bogon tmp]# mkdir newinitrd [root@bogon tmp]# cd newinitrd/ [root@bogon newinitrd]# zcat ../initrd-2.6.30.4.img |cpio -i 11537 blocks 释放之后看到如下内容 [root@bogon newinitrd]# ls bin dev etc init lib proc sbin sys sysroot 2,ok,下边就是编辑init,删掉其中重复的四行中的两行 echo "Loading dm-region-hash.ko module" insmod /lib/dm-region-hash.ko echo "Loading dm-region-hash.ko module" insmod /lib/dm-region-hash.ko 3,重新打包initrd [root@bogon newinitrd]# find .|cpio -c -o > ../initrd 11538 blocks [root@bogon newinitrd]# cd .. [root@bogon tmp]# gzip -9 < initrd > initrd.img [root@bogon tmp]# ls initrd-2.6.30.4.img initrd initrd.img newinitrd 好了,initrd.img就是重新打包的initrd了,然后把initrd.img拷贝到/boot,更改grub.conf里边的initrd-2.6.30.4.img为initrd.img就可以了, 这样“insmod: error inserting '/lib/dm-region-hash.ko' : -1 File exists”就不会有了 其实将init文件的第二行“setquiet”去掉,你就知道initrd文件到底在做什么了

Linux如何禁止系统内核Kernel自动升级

Linux如何禁止系统内核Kernel自动升级 Kernel是系统内核,Linux系统在进行升级的时候内核也会跟着更新,有时为了避免不必要的麻烦,不少用户会选择不升级Linux内核,那么要如何禁止Kernel升级呢? 不过在更新其他软件包时,如果依赖最新的内核,那么该软件包是没法更新成功的。 方法如下: 方法1: # vim /etc/yum.conf exclude=kernel* 在 [main]配置段下,追加或修改以上内容。 可通过下面的命令查看是否生效: # yum update | grep -i kernel 方法2: 在yum命令行中加上-x参数,来跳过指定的更新。如: # yum -x ‘kernel*’ update Linux禁止系统内核Kernel升级的方法就介绍到这里了,方法2是通过在yum命令行中加入参数来实现的,相较于方法1简单了很多。 【拓展阅读】Linux 新手容易犯的 7 个错误 7. 选择错误的 Linux 发行版 Linux 有几百个不同的版本,或者按他们的称呼叫做发行版(distribution)。其中许多是专门针对不同的版本或用户的。选择了错误的版本,你与 Linux 的第一次亲密体验将很快变成一个噩梦。 如果你是在朋友的帮助下切换的话,确认他们的建议是适合你,而不是他们。有大量的文章可以帮助到你,你只需要关注前 20 名左右的或者列在 Distrowatch 的即可,就不太可能会搞错。

更好的做法是,在你安装某个发行版之前先试试它的 Live DVD。Live DVD 是在外设 上运行发行版的,这样可以允许你在不对硬盘做任何改动的情况下对其进行测试。事实上,除非你知道怎么让硬盘在 Linux 下可访问,否则你是不会看到你的硬盘的。 6. 期待什么都是一样的 由于经验有限,许多 Windows 用户不知道新的意味着新的程序和新的处理方式。事 实上你的 Windows 程序是无法在 Linux 上运行的,除非你用 WINE 或者 Windows 虚拟机。而且你还不能用 MS Office 或者 PhotoShop ——你必须要学会使用 LibreOffice 和 Krita。 经过这些年,这些应用可能会有和 Windows 上的应用类似的功能,但它们的功能可能具 有不同的名称,并且会从不同的菜单或工具栏获得。 就连很多想当然的都不一样了。Windows 用户会特别容易因为他们有多个桌面环境 可以选择而大吃一惊——至少有一个主要的和很多次要的桌面环境。 5. 安装软件的时候不知所措 在 Windows 上,新软件是作为一个完全独立的程序来安装的。通常它囊括了其它所 需的依赖库。 有两种叫做 Flatpak 和 Snap 的软件包服务目前正在 Linux 上引进类似的安装系统, 但是它们对于移动设备和嵌入式设备来说太大了。更多情况下,Linux 依赖于包管理系统,它会根据已安装的包来判断软件的依赖包是否是必需的,从而提供其它所需的依赖包。 笔记本和工作站上的包管理本质上相当于手机或平板电脑上的 Google Play:它速度 很快,并且不需要用于安装的物理介质。不仅如此,它还可以节省 20%-35% 的硬盘空间,因为依赖包不会重复安装。 4. 假想软件会自动更新好 Linux 用户认为控制权很重要。Linux 提供更新服务,不过默认需要用户手动运行。 例如,大多数发行版会让你知道有可用的软件更新,但是你需要选择安装这些更新。 如果你选择更新的话,你甚至可以单独决定每一个更新。例如,你可能不想更新到新的内核,因为你安装了一些东西需要使用当前的内核。又或者你想要安装所有的安全性更新,但不想把发行版更新到一个新的版本。一切都由你来选择。 3. 忘记密码 许多 Windows 用户因为登录不方便而忘记密码。又或者为了方便起见,经常运行一 个管理账户。

ubuntu内核升级及卸载

ubuntu内核升级及卸载 ubuntu下内核的升级与卸载 很多用户一般都会选择Windows + Ubuntu的双系统。用得时间久了,随着Ubuntu内核的不断升级,开机启动菜单会变得越来越臃肿。下面简单介绍一下如何删除开机启动菜单多余的内核(旧版本),以及如何调整不同操作系统的启动顺序。 Ubuntu是由grub引导启动的。每当Ubuntu升级到新的版本后,grub会自动调整开机启动菜单的顺序,把新的内核放在启动菜单的开始,同时也不会删除久的内核版本。这样,当Ubuntu的升级次数一多,启动菜单中将变得非常臃肿。而且那些旧版本的内核基本不会用,不如删除之。解决方案如下: 1.找出系统已经安装的内核版本,在终端里输入命令:dpkg --get-selections | grep linux-image 然后会显示系统中已安装的内核,例如: linux-image-2.6.35-22-generic install linux-image-2.6.38-10-generic install

linux-image-2.6.38-11-generic install linux-image-2.6.38-8-generic install linux-image-3.0.0-12-generic install linux-image-generic install 2.卸载旧的内核版本,在终端里输入命令:sudo apt-get remove linux-image-2.6.35-22-generic linux-image-2.6.38-8-generic linux-image-2.6.38-10-generic linux-image-2.6.38-11-generic 上面命令和含义是: dpkg --get-selections [ ...] 把已选中的软件包列表打印到标准输出; grep linux-image 匹配查找; uname -a 查看已安装的linux内核版。 这样,旧的内核版本就删除了。然而,grub修改开机启动菜单,会自动把最新的Ubuntu放在第一位,把Windows放在最后一个。我们经常希望把Windows调整到靠前的位置,可能还会修改默认的启动项和等待时间等。解决方案如下:1.找到grub配置,打开配置文档,在终端里输入命令:sudo gedit /boot/grub/grub.cfg 2.修改grub配置

[教程] (已更新6个AMD适用的内核)

这篇贴子是我依照samsonwtsui大大的一步神贴,补充了大大忽略的问题,删繁就简总结出来的产物,以供新手们作为安装雪豹系统的参考,我的是AMD的CPU,其它的U也适用(主要是替换内核部分不同),新手结合我的贴子和一步神贴阅读效果更佳! 第一步:缩小现有分区卷 雪豹使用自己的文件系统,HFS+,不兼容Windows的NTFS文件系统,这个指南需要2个HFS+分区完成安装任务,其中一个大小是6.3GB,用来放雪豹安装光盘,另一个用来放雪豹操作系统,大小是20GB(按照自己需要增减,操作系统本身就占了约4.5GB)。 操作: 1. 右键点击我的电脑(计算机)——>管理——>弹出来的窗口左边的磁盘管理,这里你可以看见你的硬盘分区状况。 2. 在D盘上点击右键——>压缩卷然后在弹出来的框输入26906(1024MB/GB×26.3GB),然后按确定即可。(XP用户和使用FAT32格式的用户如无法压缩卷可以使用Acronis Disk Director Suite或Paragon PM实现类似功能)

3. 右键点击未分配空间——>新建简单卷,点击下一步后输入6426(1024MB/GB×6.3GB),下一步将此空间分配到E,不要格式化。完成之后Windows会弹出框告诉你需要格式化E才能访问,先谢谢她的好意,不过选择取消,不格式化。 4. 用同样的办法把剩下的20G也新建一个卷。这个卷随便你格不格式化。 技巧:6.3GB的盘一定要靠近原来的D盘,等安装完成后把这个光盘拆了,用扩展卷功能又能够让它的空间合到D盘里面。 第二步:加载DVD到硬盘并修改。 1.下载HFS-Explorer并安装 2.若你的Windows之前没有安装Java VM(Java JRE虚拟机),也另需下载安装。 3.打开HFS-Explorer点击"File"—>"Load file system from file",在弹出框里找到雪豹的安装光盘DMG文件,然后在弹出框里选含有HFS+那一项,如图,然后点即可。已购买苹果DVD 的朋友插入光盘后点击"File"—>"Load file system from device",然后点击“Load”

关于WIN终端版本(软件)升级方法

关于WIN终端版本(软件)升级方法 ——所有售前技术人员及客服需了解 软件版本V3.00及其以后为基于CE4.2内核程序的终端软件版本。此版本对改变了以前所有版本的程序结构,修改很大。此版本适应本公司硬件版本AT V1.3以后所有及其DT V1.1以后所有(包含)。现将此版本的制作与升级方法列入下: 附1:DOC制作、结构与文件存储 一:由V3.00(软件)以前终端升级到此版本(V1.3以前不适用) A:使用putimage文件升级: 使用电子小硬盘(或者带有DOS启动的IDE接口硬盘)启动终端,运行putimage 程序,将image文件PUT到终端即可 实例:image文件名称为A T5K300,则运行为:C:\> putimage at5k300。 注意:确保putimage的版本为5.1.4 二:V3.00同版本或之后版本升级 A:使用终端FTP升级 1、配置FTP服务器: ㈠如果服务器已经有了*:\Inetpub\ftproot这个目录(注:* 代表系统所在盘) 把升级文件直接拷贝到*:\Inetpub\ftproot目录下,这样就完成了服务器的设置。 ㈡如果服务器没有*:\Inetpub\ftproot目录,则要安装“internet信息服务”,步骤如下:在“控制面板”中,选择“添加/删除程序”中的“添加/删除windows组件”,在“windows组件向导”中在第一项“internet信息服务(IIS)”前面的复选框打上勾。如图所示: 选择“详细信息“,如下图:

在“文件传输协议(FTP)服务器“前打勾,确定后单击“下一步”跳出如下图所示的窗口 这时放入win2000的安装盘继续点“下一步”系统就开始安装internet信息服务直到完成服务的安装。完成后再进行如㈠中的步骤即可。 1.服务器配置完成后。在终端的“终端管理器”中选择“本机→程序升级”选择升级方式为“远程ftp” 2.终端正常启动,配置好终端IP地址等,运行PING,确认终端能PING通FTP服务器。

内核升级方法

内核升级方法: 一、将Linux内核从2.6.9.55直接升级到2.6.18.8 步骤: 1、将linux-2.6.18.8.tar.bz2放置在/usr/src/下然后解压: cd /usr/src tar -jxvf linux-2.6.18.8.tar.bz2 2、进入/usr/src目录,依次执行下列命令: make mrproper(第一次编译内核不需要) make menuconfig(直接保存退出) make make modules_install install 3、修改grub.conf文件 在/boot/grub/grub.conf 里新加enforcing =0 变成: title Red Hat Enterprise Linux ES (2.6.18.8) root (hd0,0) kernel /vmlinuz-2.6.18.8 ro root=LABEL=/ enforcing=0 rhgb quiet initrd /initrd-2.6.18.8.img 如果不加enfocing=0可能在重起后不能登录新编内核,并出现错误: Mkrootdev:label /enforcing=0 not found mount :error 6 mounting ext3 mount:error 2 mounting none switchroot:mount failed:22 umount /initrd/dev failed:2 kernel panic –not synicncing:Attemped to kill init 分析:root找不到挂载点,所以不能启动。另外需要注意的是enforcing=0和/与rhgb之间需要一个空格,否则错误信息同上。 4、重起,登录新编译的内核。 二、不在/usr/src目录下操作,在另外的目录下用shell脚本升级 我们在/dhcc目录下,建立个自己的目录,比如zhangbing,然后把linux-2.6.18.8.tar.bz2解压到这个目录下linux-2.6.18.8,同时建立一个目录build。 在linux-2.6.18.8目录中建立一个脚本shmake.sh 脚本内容如下: # !/bin/sh echo "make O=../build menuconfig" make O=../build menuconfig echo "make O=../build" make O=../build echo "make O=../build modules_install install" make O=../build modules_install install 此脚本的目的在于每次编译不对原内核产生任何影响,每次编译的东东都放于build目录中了。 脚本执行完后,同第一种方法一样修改grub.conf文件。 三、自己定制一个系统

linux内核升级

RedHat Linux 9.0系统内核升级 目录 1 引言 (1) 1.1 课程设计的目的 (1) 1.2 课程设计的意义 (1) 1.3 课程设计的内容 (2) 2 相关内容介绍 (3) 2.1内核版本2.6.18的新特性 (3) 2.2 几个重要的内核文件简介 (4) 2.2.1 vmlinuz-2.4.20-8 (5) 2.2.2 initrd-2.4.20-8.img (5) 2.2.3 System.map-2.4.20-8 (5) 2.3 内核升级大体过程 (7) 2.4 几个重要命令简介 (7) 3 内核升级的详细设计 (8) 3.1 准备阶段 (9) 3.2配置阶段 (10) 3.3 编译阶段 (17) 3.4 启动新内核 (18) 4 测试结果 (20) 4.1 升级前的内核 (20) 4.2 升级后的内核 (21) 5 升级过程中遇到的问题及解决方法 (22) 5.1 安装工具包时的问题及解决方法 (22) 5.2 配置文件系统时的问题及解决方法 (22) 5.3 安装新内核时出现的问题及解决方法 (23) 结束语 (24) 参考文献 (25)

第1页共25页 1 引言 1.1 课程设计的目的 RedHat Linux是目前世界上使用最多的Linux操作系统。因为它具备最好的图形界面,无论是安装、配置还是使用都十分方便,而且运行稳定。RedHat Linux推出9.0版本后,在原有的基础上又有了很大的进步。它完善了图形界面,增强了硬件的兼容性等等。众所周知,由于Linux 操作系统具有免费,开源等特点,加上用Linux作为服务器性能稳定,并且具有较高的安全性,所以近几年Linux操作系统有了蓬勃的发展,内核的版本的升级很快。RedHat Linux 9.0默认安装内核版本为2.4.20-8,随着在Linux上面应用的服务越来越多,这个内核版本已不能满足需要了,比如某些软件的安装需要的内核版本至少为2.6.××,所以在RedHat Linux9.0上对原有内核的升级变得刻不容缓。 本课程设计设主要目的是在虚拟机VMware Workstation 6.5-7.x下安装RedHat Linux9.0操作系统后,对原有内核版本2.4.20-8升级到2.6.18,通过对内核的升级,能够使Linux操作系统满足更多的需要,更大程度地发挥Linux操作系统的优势。 1.2 课程设计的意义 通过此次课程设计,可以加深自身对Linux系统的了解,更加深刻的认识Linux内核的结构,同时还可以更了解Linux操作系统的运行机制,更加熟悉Linux这一现在流行的操作系统,为以后更深入的学习Linux打下了良好的基础。 同时通过本次课程设计,可以加强我们的实际动手能力,明白理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才是真正的知识,才能提高自己的实际动手能力和独立思考的能力。同时还具有重大意义的是,在课程设计的过程中,会遇到很多问题,从发现问题、分析

Linux内核升级全过程 手把手教你一次成功

Linux内核升级全过程手把手教你一次成功 由于开发环境需要在linux-2.6内核上进行,于是准备对我的虚拟机上的Linux系统升级。没想到这一弄就花了两天时间(反复装系统,辛苦啊~~),总算把Linux系统从2.4.20-8内核成功升级到了2.6.18内核。 网上虽然有很多介绍Linux内核升级的文章,不过要么过时,下载链接失效;要么表达不清,不知所云;更可气的是很多文章在转载过程中命令行都有错误。刚开始我就是在这些“攻略”的指点下来升级的,以致于浪费了很多时间。 现在,费尽周折,升级成功,心情很爽,趁性也来写个“升级攻略”吧!于是特意又在虚拟机上重新安装一个Linux系统,再来一次完美的升级,边升级边记录这些步骤,写成一篇Linux内核升级记实录(可不是回忆录啊!),和大家一起分享~~! 首先说明,下面带#号的行都是要输入的命令行,且本文提到的所有命令行都在终端里输入。接下来,让我们一起开始精彩的Linux内核升级之旅吧! 一、准备工作 启动Linux系统,并用根用户登录,进入终端模式下。 1、查看Linux内核版本 #uname-a 如果屏幕显示的是2.6.x,说明你的已经是2.6的内核,也用不着看下文了,该干什么干什么去吧!~~~如果显示的是2.4.x,那恭喜你,闯关通过,赶快进行下一步。 2、下载2.6内核源码 下载地址:https://www.wendangku.net/doc/5817981334.html,/pub/linux/kernel/v2.6/linux-2.6.18.tar.bz2 3、下载内核升级工具 (1)下载module-init-tools-3.2.tar.bz2 https://www.wendangku.net/doc/5817981334.html,/pub/linux/utils/kernel/module-init-tools/module-init-tool s-3.2.tar.bz2 (2)下载mkinitrd-4.1.18-2.i386.rpm https://www.wendangku.net/doc/5817981334.html,/fedora/linux/3/i386/RPMS.core/mkinitrd-4.1.18-2.i386.r pm (3)下载lvm2-2.00.25-1.01.i386.rpm https://www.wendangku.net/doc/5817981334.html,/fedora/linux/3/i386/RPMS.core/lvm2-2.00.25-1.01.i386.r pm (4)下载device-mapper-1.00.19-2.i386.rpm https://www.wendangku.net/doc/5817981334.html,/fedora/linux/3/i386/RPMS.core/device-mapper-1.00.19-2. i386.rpm (2.6.18内核和这4个升级工具我都有备份,如果以上下载地址失效,请到https://www.wendangku.net/doc/5817981334.html,/guestbook留下你的邮箱,我给你发过去) 二、配置工作 好啦,2.6内核和4个升级工具都下载完了(少一个也不行,如果没有下载齐全,请不要尝试下面的步骤,升级是不会成功的),下面回到Linux系统中开始配置工作吧。 4、将下载好的内核和4个升级工具都拷贝到/usr/src文件夹下。怎么拷贝就不用我教了吧~~~~不会拷贝的去撞墙吧!~~呵呵! 5、拷贝完毕,开始解压新内核,具体操作请依次执行以下命令: #cd/usr/src(进入到/usr/src目录下,如果已经在/usr/src目录下,可不执行该命令)

内核升级方法

升级内核方法 一、使用安装介质中的内核包直接升级(*.rpm) 二、通过内核源码包升级(*.src.rpm) 三、通过内核官网源码压缩包升级(*.tar.bz *.tar.gz ) ●了解系统当前的状态 1、# uname –a(查看内核版本) 2、cat /etc/redhat-release(查看系统发行版) 3、cd /boot ls -l |grep -iE '*.img|vmlinuz*' (查看内核启动的文件) 4、cat /boot/grub/menu.lst (查看内核菜单启动列表) 方法一:内核包直接升级 例子: 1. 使用安装光盘介质中的内核包 [root@u70151 ~]# ls -l kernel* -rw-r--r-- 1 root root 22507963 Aug 22 09:43 kernel-2.6.18-308.el5.x86_64.rpm 2. 安装新的内核包 [root@u70151 ~]# rpm -ivh kernel-2.6.18-308.el5.x86_64.rpm warning: kernel-2.6.18-308.el5.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID e8562897 Preparing... ########################################### [100%] 1:kernel ########################################### [100%] 3. 安装完成后的状态(查看方法) ▼ rpm -qa|grep kernel (查看内核安装包) kernel-2.6.18-164.el5 kernel-2.6.18-308.el5 ▼ at /boot/grub/menu.lst # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You have a /boot partition. This means that # all kernel and initrd paths are relative to /boot/, eg. # root (hd0,0) # kernel /vmlinuz-version ro root=/dev/VolGroup01/LogVol00 # initrd /initrd-version.img #boot=/dev/sda default=0 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu title Red Hat Enterprise Linux Server (2.6.18-308.el5) root (hd0,0) kernel /vmlinuz-2.6.18-308.el5 ro root=/dev/VolGroup01/LogVol00 rhgb quiet initrd /initrd-2.6.18-308.el5.img title Red Hat Enterprise Linux Server (2.6.18-164.el5) root (hd0,0) kernel /vmlinuz-2.6.18-164.el5 ro root=/dev/VolGroup01/LogVol00 rhgb quiet initrd /initrd-2.6.18-164.el5.img ▼cd /boot # ls -l |grep -iE '*.img|vmlinuz*'(查看升级后使用的文件)

R4烧录卡内核升级

使用之前 microSD 卡的操作 本卡采用microSD 卡储存和运行程序(游戏)。虽然microSD 卡能够保存大量的数据并且具有防震的特性,但是有几点需要注意的事项。当使用此部件时,请注意以下几点。 *可以使用的microSD 卡空间通常按1GB=1,000,000,000个字节进行计算。本卡、PC 和软件的容量表示成1GB=1,024×1,024×1,024=1,073,741,824个字节。因此,指示的容量值看起来会小于标称的容量数值。 ? 请勿使microSD 卡受到震动和撞击。 由于环境和使用状况,microSD 卡的部分可能会容易受损坏,或者可能无法读取和记录数据。在使用过程中,请勿使本卡受到震动或撞击,并且不要在开机状态下取卡或在数据正在写入时关断电源。 ? 请定期备份数据。 microSD 卡是暂时储存器。为了避免由于静电、电磁波、破损和故障而导致的数据丢失,请将数据(尤其是个人存档)备份到PC 或DVD 光盘中。 ? 如果感到microSD 卡有任何异常,请立即备份数据。 microSD 卡的故障可能会在程序(游戏)运行中或存档时产生错误的数据写入操作。继续使用会导致进一步恶化,并且最终可能使microSD 卡无法使用。如果发现这些现象,请立即将microSD 卡中的数据复制到PC 、DVD 光盘等中,并重新格式化microSD 卡恢复其正确的储存特性,一旦microSD 卡出了故障,数据就无法被恢复。 ? 在过热或过冷的环境下,操作可能会停止。 如果周围温度过热或过冷,NDS 主机可能将无法使用。而本卡带所使用的microSD 卡也有使用温度范围限制,详细请阅读microSD 卡的规格说明。 关于储存内容的赔偿 对于由于任何类型的问题所导致的储存或编辑内容的丢失及其造成的直接或间接的损坏,R4iSDHC RTS 制造商不承担任何责任。同样,以上陈述也适用于任何类型品牌的microSD 卡售后服务有限责任的情况。 部件的识别和操作 请按照正确的方向插入microSD 卡

SAP kernel升级步骤

1、登陆下载最新的kernel,包含两个压缩包 包含两个压缩包。。 门户下载路径:My Company's Application Components - My Company's Software - SAP CRM - SAP CRM 7.0 - Entry by Component - CRM Application Server ABAP 选择路径:SAP KERNEL 7.01 64-BIT UNICODE -> Linux on x86_64 64bit -> #Database independent 与数据库有关:SAPEXEDB_111-10005987.SAR 与数据库无关:SAPEXE_111-10005984.SAR 添加到downbasket下载即可 如提示找不到该命令,,需从SAP门户下载对应系统的工具 2、必须使用sapcar命令解压 命令解压,,如提示找不到该命令 解压命令:sapcar -xvf -R 3、解压到同一个目录 sapcar -xvf /dir/ SAPEXEDB_111-10005987.SAR /temp sapcar -xvf /dir/ SAPEXE_111-10005984.SAR /temp 4、查看升级前的kernel信息 查看status状态:

使用sm51查看Release Notes信息: 5、停止sap应用 stopsap saposcol -k 如果发现还有adm的用户进程,用kill命令删掉 覆盖之前一定要备份,,以防止出错可以恢复6、将以下目录的文件用刚才解压到temp的文件覆盖 的文件覆盖,,覆盖之前一定要备份

REDHAT.内核升级.官方步骤

[root@localhost weblogic]# ls -l /boot -rw-r--r-- 1 root root 709527 Jan 24 09:50 initrd-2.6.9-78.0.13.ELsmp.img

-rw-r--r-- 1 root root 722707 Oct 27 14:58 initrd-2.6.9-78.EL.img -rw-r--r-- 1 root root 712703 Oct 27 14:58 initrd-2.6.9-78.ELsmp.img [root@localhost weblogic]# more /etc/grub.conf title Red Hat Enterprise Linux AS (2.6.9-78.0.13.ELsmp) root (hd0,0) kernel /vmlinuz-2.6.9-78.0.13.ELsmp ro root=LABEL=/ rhgb quiet initrd /initrd-2.6.9-78.0.13.ELsmp.img title Red Hat Enterprise Linux AS (2.6.9-78.ELsmp) root (hd0,0) kernel /vmlinuz-2.6.9-78.ELsmp ro root=LABEL=/ rhgb quiet initrd /initrd-2.6.9-78.ELsmp.img title Red Hat Enterprise Linux AS-up (2.6.9-78.EL) root (hd0,0) kernel /vmlinuz-2.6.9-78.EL ro root=LABEL=/ rhgb quiet initrd /initrd-2.6.9-78.EL.img 二、Kernel版本类型 单处理器:kernel- 多处理器:kernel-smp- 大内存:kernel-hugemem- 虚拟机:kernel-xen- 源码:kernel-devel- 区别:kernel-devel包只包含用于内核开发环境所需的内核头文件以及Makefile,而kernel-souce包含所有内核源代码。 如果仅仅是用于你自己编写的模块开发的话,因为只需引用相应的内核头文件,所以只有devel包即可,如果你要修改现有的内核源代码并重新编译,那必须是kernel-souce。 kernel-souce在RH某些版本之后不再附带在发行版中了,必须自己通过kernel-XXX.src.rpm 做出来。 三、内核获取方法 https://www.wendangku.net/doc/5817981334.html, 账户、密码:LEWISE.LIU有; 用户往往遇到这样的需求,只希望下载更新的软件包,例如内核,来更新系统的特定部分,用户需要首先点击"Channel",然后选择希望下载的版本的OS,例如客户安装的是RHEL3,希望下载最新的内核包(当前是U5)来更新原有的RHEL3,则点击“Red Hat Enterprise Linux ES (v. 3 for 32-bit x86)”:

相关文档
相关文档 最新文档