Linux Kernel 2.4 和 2.6 的区别

Linux Kernel 2.4 和 2.6 的区别,第1张

1、 使用新的入口

必须包含 <linux/init.h>

module_init(your_init_func)

module_exit(your_exit_func)

老版本:int init_module(void)

void cleanup_module(voi)

2.4中两种都可以用,对如后面的入口函数不必要显示包含任何头文件。

2、 GPL

MODULE_LICENSE("Dual BSD/GPL")

老版本:MODULE_LICENSE("GPL")

3、 模块参数

必须显式包含<linux/moduleparam.h>

module_param(name, type, perm)

module_param_named(name, value, type, perm)

参数定义

module_param_string(name, string, len, perm)

module_param_array(name, type, num, perm)

老版本:MODULE_PARM(variable,type)

MODULE_PARM_DESC(variable,type)

4、 模块别名

MODULE_ALIAS("alias-name")

这是新增的,在老版本中需在/etc/modules.conf配置,现在在代码中就可以实现。

5、 模块计数

int try_module_get(&module)

module_put()

老版本:MOD_INC_USE_COUNT 和 MOD_DEC_USE_COUNT

6、 符号导出

只有显示的导出符号才能被其他 模块使用,默认不导出所有的符号,不必使用EXPORT_NO

_SYMBOLS

老板本:默认导出所有的符号,除非使用EXPORT_NO_SYMBOLS

7、 内核版本检查

需要在多个文件中包含<linux/module.h>时,不必定义__NO_VERSION__

老版本:在多个文件中包含<linux/module.h>时,除在主文件外的其他文件中必须定义_

_NO_VERSION__,防止版本重复定义。

8、 设备号

kdev_t被废除不可用,新的dev_t拓展到了32位,12位主设备号,20位次设备号。

unsigned int iminor(struct inode *inode)

unsigned int imajor(struct inode *inode)

老版本:8位主设备号,8位次设备号

int MAJOR(kdev_t dev)

int MINOR(kdev_t dev)

9、 内存分配头文件变更

所有的内存分配函数包含在头文件<linux/slab.h>,而原来的<linux/malloc.h>不存在

老版本:内存分配函数包含在头文件<linux/malloc.h>

10、 结构体的初试化

gcc开始采用ANSI C的struct结构体的初始化形式:

static struct some_structure = {

.field1 = value,

.field2 = value,

..

}

老版本:非标准的初试化形式

static struct some_structure = {

field1: value,

field2: value,

..

}

11、 用户模式帮助器

int call_usermodehelper(char *path, char **argv, char **envp,

int wait)

新增wait参数

12、 request_module()

request_module("foo-device-%d", number)

老版本:

char module_name[32]

printf(module_name, "foo-device-%d", number)

request_module(module_name)

13、 dev_t引发的字符设备的变化

1、取主次设备号为

unsigned iminor(struct inode *inode)

unsigned imajor(struct inode *inode)

2、老的register_chrdev()用法没变,保持向后兼容,但不能访问设备号大于256的设备

3、新的接口为

a)注册字符设备范围

int register_chrdev_region(dev_t from, unsigned count, char *name)

b)动态申请主设备号

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char

*name)

看了这两个函数郁闷吧^_^!怎么和file_operations结构联系起来啊?别急!

c)包含 <linux/cdev.h>,利用struct cdev和file_operations连接

struct cdev *cdev_alloc(void)

void cdev_init(struct cdev *cdev, struct file_operations *fops)

int cdev_add(struct cdev *cdev, dev_t dev, unsigned count)

(分别为,申请cdev结构,和fops连接,将设备加入到系统中!好复杂啊!)

d)void cdev_del(struct cdev *cdev)

只有在cdev_add执行成功才可运行。

e)辅助函数

kobject_put(&cdev->kobj)

struct kobject *cdev_get(struct cdev *cdev)

void cdev_put(struct cdev *cdev)

这一部分变化和新增的/sys/dev有一定的关联。

14、 新增对/proc的访问 *** 作

<linux/seq_file.h>

以前的/proc中只能得到string, seq_file *** 作能得到如long等多种数据。

相关函数:

static struct seq_operations 必须实现这个类似file_operations得数据中得各个成

员函数。

seq_printf();

int seq_putc(struct seq_file *m, char c)

int seq_puts(struct seq_file *m, const char *s)

int seq_escape(struct seq_file *m, const char *s, const char *esc)

int seq_path(struct seq_file *m, struct vfsmount *mnt,

struct dentry *dentry, char *esc)

seq_open(file, &ct_seq_ops)

等等

15、 底层内存分配

1、<linux/malloc.h>头文件改为<linux/slab.h>

2、分配标志GFP_BUFFER被取消,取而代之的是GFP_NOIO 和 GFP_NOFS

3、新增__GFP_REPEAT,__GFP_NOFAIL,__GFP_NORETRY分配标志

4、页面分配函数alloc_pages(),get_free_page()被包含在<linux/gfp.h>中

5、对NUMA系统新增了几个函数:

a) struct page *alloc_pages_node(int node_id,

unsigned int gfp_mask,

unsigned int order)

b) void free_hot_page(struct page *page)

c) void free_cold_page(struct page *page)

6、 新增Memory pools

<linux/mempool.h>

mempool_t *mempool_create(int min_nr,

mempool_alloc_t *alloc_fn,

mempool_free_t *free_fn,

void *pool_data)

void *mempool_alloc(mempool_t *pool, int gfp_mask)

void mempool_free(void *element, mempool_t *pool)

int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)

16、 per-CPU变量

get_cpu_var()

put_cpu_var()

void *alloc_percpu(type)

void free_percpu(const void *)

per_cpu_ptr(void *ptr, int cpu)

get_cpu_ptr(ptr)

put_cpu_ptr(ptr)

老版本使用

DEFINE_PER_CPU(type, name)

EXPORT_PER_CPU_SYMBOL(name)

EXPORT_PER_CPU_SYMBOL_GPL(name)

DECLARE_PER_CPU(type, name)

DEFINE_PER_CPU(int, mypcint)

2.6内核采用了可剥夺得调度方式这些宏都不安全。

17、 内核时间变化

1、现在的各个平台的HZ为

Alpha: 1024/1200ARM : 100/128/200/1000CRIS: 100i386: 1000IA-64:

1024M68K: 100M68K-nommu: 50-1000MIPS: 100/128/1000MIPS64: 100

PA-RISC: 100/1000PowerPC32: 100PowerPC64: 1000S/390: 100SPARC32:

100SPARC64: 100SuperH: 100/1000UML: 100v850: 24-100x86-64: 1000.

2、由于HZ的变化,原来的jiffies计数器很快就溢出了,引入了新的计数器jiffies_64

3、#include <linux/jiffies.h>

u64 my_time = get_jiffies_64()

4、新的时间结构增加了纳秒成员变量

struct timespec current_kernel_time(void)

5、他的timer函数没变,新增

void add_timer_on(struct timer_list *timer, int cpu)

6、新增纳秒级延时函数

ndelay();

7、POSIX clocks 参考kernel/posix-timers.c

18、 工作队列(workqueue)

1、任务队列(task queue )接口函数都被取消,新增了workqueue接口函数

struct workqueue_struct *create_workqueue(const char *name)

DECLARE_WORK(name, void (*function)(void *), void *data)

INIT_WORK(struct work_struct *work,

void (*function)(void *), void *data)

PREPARE_WORK(struct work_struct *work,

void (*function)(void *), void *data)

2、申明struct work_struct结构

int queue_work(struct workqueue_struct *queue,

struct work_struct *work)

int queue_delayed_work(struct workqueue_struct *queue,

struct work_struct *work,

unsigned long delay)

int cancel_delayed_work(struct work_struct *work)

void flush_workqueue(struct workqueue_struct *queue)

void destroy_workqueue(struct workqueue_struct *queue)

int schedule_work(struct work_struct *work)

int schedule_delayed_work(struct work_struct *work, unsigned long

delay)

19、 新增创建VFS的"libfs"

libfs给创建一个新的文件系统提供了大量的API.

主要是对struct file_system_type的实现。

参考源代码:

drivers/hotplug/pci_hotplug_core.c

drivers/usb/core/inode.c

drivers/oprofile/oprofilefs.c

fs/ramfs/inode.c

fs/nfsd/nfsctl.c (simple_fill_super() example)

linux的uboot启动映像、zImage和uImage的区别

uboot启动zImage(go)和uImage(bootm)分析

1.bootm加载linux镜像是加载uIamge,uIamge是由mkimage制作而来,和zIamge的差异是uIamge是zIamge压缩过的,bootm需要先对uIamge解压,解压地址为内核入口地址。当解压完成时uIamge和zIamge几乎是相同的,具体差异可以论述。uboot目前只能支持uImage启动,不支持zImage启动

2.bootm解压过程

---------------------------------------------------------------------------

## Booting image at 08808000 ...

Image Name:   Linux-2.6.14.7

Image Type:   ARM Linux Kernel Image (uncompressed)

Data Size:    989172 Bytes = 966 kB

Load Address: 08008000

Entry Point:  08008000

Verifying Checksum ... OK

OK                                         uboot bootm命令对uIamge的解压 *** 作

---------------------------------------------------------------------------

Starting kernel ...         

传递内核参数将控制权交给arch\arm\boot\compressed]head.S

----------------------------------------------------------------------------

如mx1ADS班子内存的起始地址为0x0800_0000,通过tftp 下载到0x0800_8000 +offset ,offset大于0x80_0000,即tftp 0x0880_8000 然后bootm 0x0880_8000 即将0x0880_8000处的uIamge解压,解压地址即为mkimage 设置的kernel入口地址0x0800_8000。

zImage和uImage的区别一、vmlinuzvmlinuz 是可引导的、压缩的内核。“vm”代表“Virtual Memory”。Linux 支持虚拟内存,不像老的 *** 作系统比如DOS有640KB内存的限制。Linux能够使用硬盘空间作为虚拟内存,因此得名“vm”。 

vmlinuz 的建立有两种方式。一是编译内核时通过“make zImage”创建,然后通过:“cp /usr/src/linux-2.4/arch/i386/linux/boot/zImage/boot/vmlinuz”产生。zImage适用于 小内核的情况,它的存在是为了向后的兼容性。 

二 是内核编译时通过命令make bzImage创建,然后通过:“cp/usr/src/linux-2.4/arch/i386/linux/boot/bzImage /boot/vmlinuz”产生。bzImage是压缩的内核映像,需要注意,bzImage不是用bzip2压缩的,bzImage中的bz容易引起 误解,bz表示“big zImage”。 bzImage中的b是“big”意思。 zImage(vmlinuz)和bzImage(vmlinuz)都是用gzip压缩的。它们不仅是一个压缩文件,而且在这两个文件的开头部分内嵌有 gzip解压缩代码。所以你不能用gunzip 或 gzip –dc解包vmlinuz。 

二、 initrd-x.x.x.img 

initrd是“initial ramdisk”的简写。initrd一般被用来临时的引导硬件到实际内核vmlinuz能够接管并继续引导的状态。 

initrd 映象文件是使用mkinitrd创建的。mkinitrd实用程序能够创建initrd映象文件。这个命令是RedHat专有的。其它Linux发行版或 许有相应的命令。这是个很方便的实用程序。具体情况请看帮助:man mkinitrd下面的命令创建initrd映象文件。 

最后生成的内核镜象有两种zImage以及uImage。其中zImage下载到 目标板中后,可以直接用uboot的 命令go来 进行直接跳转。这时候内核直接解压启动。但是无法挂载文件系统,因为go命令没有将内核需要的相关的启动参数传递给内核。传递启动参数我们必须使用命令bootm来进行跳 转。Bootm命 令跳转只处理uImage的 镜象。 

uboot源代码的tools/目录下 有mkimage工 具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。 

mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头, 记录参数所指定的信息,这样uboot才 能识别这个映象是针对哪个CPU体 系结构的,哪个OS的, 哪种类型,加载内存中的哪个位置,入口点在内存的那个位置以及映象名是什么 

用法如下: 

./mkimage -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image 

-A ==>set architecture to 'arch' 

-O ==>set operating system to 'os' 

-T ==>set image type to 'type' 

-C ==>set compression type 'comp' 

-a ==>set load address to 'addr' (hex) 

-e ==>set entry point to 'ep' (hex) 

-n ==>set image name to 'name' 

-d ==>use image data from 'datafile' 

-x ==>set XIP (execute in place) 

参数说明: 

-A 指定CPU的体系结构: 

取值表示的体 系结构 

alpha Alpha 

arm A RM 

x86 Intel x86 

ia64 IA64 

mips MIPS 

mips64 MIPS 64 Bit 

ppc PowerPC 

s390 IBM S390 

sh SuperH 

sparc SPARC 

sparc64 SPARC 64 Bit 

m68k MC68000 

-O 指定 *** 作系统类 型,可以取以下值: 

openbsd、netbsd、freebsd、4_4bsd、linux、svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos 

-T 指定映象类型, 可以取以下值: 

standalone、kernel、ramdisk、multi、firmware、script、filesystem 

-C 指定映象压缩方 式,可以取以下值: 

none 不 压缩 

gzip 用gzip的压缩方式 

bzip2 用bzip2的压缩方 式 

-a 指 定映象在内存中的加载地址,映象下载到内存中时,要按照用mkimage制作映象时,这个参数所指定的地址值来下载 

-e 指定映象运行的 入口点地址,这个地址就是-a参 数指定的值加上0x40(因 为前面有个mkimage添 加的0x40个 字节的头) 

-n 指定映象名 

-d 指定制作映象的源文件 

我在编译时用到的命令如下: 

# make zImage      //生成zImage镜象 

#/usr/local/arm/k9uboot/tools/mkimage -n 'Linux 2.4.27' -A arm -O linux -T 

kernel -C none -a 0x20007fc0 -e 0x20008000 -d zImage uImage 

内核镜象已经准备好了,这个时候我们就要来准备文件系统了。由于时间缘故,本人暂时采用的是其他 人已经好的文件系统k9.img.gz。 这个时候我们要做的是,自己写一个简单hello.c的程序,编译通过后加入到该文件系统中,然后下载到目标板中运行。 

先编写hello.c; 

编译: 

#/usr/local/arm/2.95.3/bin/arm-linux-gcc –o start-hello hello.c 

编译后生成可执行文件start-hello 

下面我们就必须把该执行文件加入到文件系统中去,步骤如下: 

#gunzip k9.img.gz                     //解 压缩 

#mount –o loop k9.img /mnt/new_disk    //挂载 

#cp start-hello /mnt/new_disk           //将 文件拷贝到文件系统中 

#cd /mnt/new_disk 

#umount /mnt/new_disk                 //卸 载 

#gzip –c –v9 k9.img >k9.img.gz          //压缩生成最终的文件系统 

下面我们就要下载内核以及准备好文件系统了,这边先说明我 的内存分配情况如下: 

Flash: 

0x10000000 ――― 0x10020000     boot 

0x10020000 ――― 0x10040000     uboot 

0x10040000 ――― 0x10060000     uboot env 

0x10060000 ――― 0x10200000     kernel 

0x10200000 ――― 0x11000000     ramdisk 

Sdram: 

0x20007fc0 ――― 0x20a00000     kernel 

0x20a00000 ―――                ramdisk  

Loadb 通过串口下载数据到ram中 

cp.b    拷贝ram中的数据到flash中。 

将kernel以及文件系统ramdisk下载完 毕之后,我们还需要设置uboot的 环境变量,这样uboot才 能够在上电启动的时候启动内核等 *** 作。环境变量设置如下: 

Set cpfltoram cp.b 10200000 20a00000 18ffff            //拷贝文件系统到ram中 

Set boot bootm 20007fc0                            //启动kernel 

Set bootcmd run cpfltoker\run cpfltoram\run boot       //uboot复位的执行指令 

Set cpfltoker cp.b 10060000 20007fc0 f4fff             //拷贝内核到ram中 

Set bootargs root=/dev/ram rw initrd=0x20a00000,4M init=/linuxrc console=ttyS0,11520 

0,mem=32m                      //uboot传 递给内核的启动参数  

设置完毕后,saveenv把 环境变量存储起来。 

学习心得:zImage 和uImage 都是生成的可执行内核镜像文件   

2者在u-boot中启动的方式分别是 go addr 与 bootm addr 来实现启动过程的 

即对于zImage是通过 go 来进行引导   而uImage是通过bootm来进行引导的 

zImage 和 uImage 2者的关系 是 uImage 是zImage通过mkimage (u--boot下面tools下的工具)来生成的 

结果是后者比前者在头部多了64个byte,这多余的64 个byte是用来通知给u-boot用的;将相关信息告知u-boot  

这样做的结果在u-boot引导内核时存在2个地址:loadaddress 和entry address 2者的差值刚好是0x40(64byte)的大小 

这样在使用bootm loadaddress 时u-boot会根据相应的loadaddress进行调整,有2中情况; 

1)、当loadaddress与mkimage时传送的一致时:

那么在加载 ldr pc,entry address时,会选择mkinage 时的entry地址;即pc=loadaddress + 4然后由pc来控制流程跳转倒ram中去执行; 

2)、当loadaddress与mkimage时传送的不一致时:

那么,u-bbot会进行地址比较 后,将当前的loadaddress减去64byte后,将真正的内核映像(去掉64byte头部的内核)拷贝倒预先制定的loadaddress,然后 直接从这个loadaddress来引导内核运行;  

总结,那么上面2中情况实际区别呢?其实就是最终代码执行时,如果地址与mkinage时指定的 不符,那么u-boot将进行去头后,拷贝内核代码,直接执行;而如果不处理,则会将 loadaddress+0x40来执行内核; 

通过tftp服务来下载 zImage或者uImage; 

loadb   在tftp不成功的情况下使用  串口来下载内核 希望不要用这个方法 

cp【.b\.w\.l】 完成 内存之间 内存向flash之间进行拷贝 

最后可以设置 bootcmd 环境变量可以实现 u-boot自动引导内核启动 

至于文件系统的2中方式:ramdisk 以及nfs 推荐开发者使用nfs  方便修改; 

当使用ramdisk时, 

#gunzip k9.img.gz                     //解压缩 

#mount –o loop k9.img /mnt/new_disk    //挂 载 

#umount /mnt/new_disk                 //卸载 

#gzip –c –v9 k9.img >k9.img.gz          //压 缩生成最终的文件系统  

这四条命令不要忘记,对于你来说多么强大 

不要你去再建立根文件系统。

Linux 是一个开放自由的 *** 作系统内核,具有一些鲜明特点如下:

(1) Linux 是一个一体化内核;

注:“一体化内核”是也称“宏内核”,是相对于“微内核”而言的。几乎所有

的嵌入式和实时系统都采用微内核,如 VxWorks、uC/OS-II、PSOS 等。

(2) 可移植性强。尽管 Linus 最初只为在 X86 PC 上实现一个“类 UNIX”,后来随

着加入者的努力,Linux 目前已经成为支持硬件平台最广泛的 *** 作系统;

注:目前已经在 X86、IA64、ARM、MIPS、AVR32、M68K、S390、Blackfin、M32R

等众多架构处理器上运行。

(3) 是一个可裁剪 *** 作系统内核。Linux 极具伸缩性,内核可以任意裁剪,可以大至

几十或者上百兆,可以小至几百 K,运行的设备从超级计算机、大型服务器到

小型嵌入式系统、掌上移动设备或者嵌入式模块,都可以运行;

(4) 模块化。Linux 内核采用模块化设计,很多功能模块都可以编译为模块,可以在

内核运行中动态加载/卸载而无需重启系统;

(5) 网络支持完善。Linux 内核集成了完整的 POSIX 网络协议栈,网络功能完善;

(6) 稳定性强。运行 Linux 的内核的服务器可以做到几年不用复位重启;

(7) 安全性好。Linux 源码开放,由众多黑客参与 Linux 的开发,一旦发现漏洞都能及时修复;

(8) 支持的设备广泛。Linux 源码中,设备驱动源码占了很大比例,几乎能支持任何

常见设备,无论是很老旧的设备还是最新推出的硬件设备,几乎都能找到 Linux下的驱动。致远电子那边有很多的,你可以去看一下


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7120965.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-01
下一篇2023-04-01

发表评论

登录后才能评论

评论列表(0条)

    保存