Linux驱动之hello world


启动终端,首先用VI编写一个C程序:vi hello.c

#include  "stdio.h"
int main()
{
printf("hello world!!!\n");
return 0;
}

接着用GCC进行编译:gcc -o hello hello.c,最后运行该程序:./hello,在终端上你会看到:hello world!!!

上面的是在操作系统基础上进行的用户应用程序的开发。然而对于Linux驱动程序的开发是绝然不同的,因为驱动程序的开发是运行在内核空间的,而应用程序是运行在用户空间的。也就是说,程序不能直接通过指针,把用户空间的数据地址传递给内核(因为MMU映射的地址根本不一样)。要想在应用程序和驱动程序之间传递数据(指针),就需要经过转换。把用户态“看到”的空间地址转换成内核态可访问的地址。

Linux内核把驱动程序划分为3种类型:字符设备、块设备和网络设备。应用程序对于字符设备的每一个I/O操作,都会直接传递给系统内核对应的驱动程序;而应用程序对于块设备的操作,要经过系统的缓冲区管理,间接传递给驱动程序处理。块设备的这种管理方式是为存储提供优化的;而字符设备的管理方式是为操作提供优化的。

至于网络设备,它在Linux系统中是一类比较特殊的设备它不像字符设备或块设备那样通过对应的设备文件节点去访问,内核也不再通过read和write等调用去访问网络设备。Linux的网络系统主要是基于BSD UNIX的套接字机制,在系统和驱动程序之间有专门的数据结构进行数据传输。

在Linux系统中,驱动程序都做成模块的形式,也就是module。简单的说,一个模块提供一个功能,这些模块是可以按照需要随时装入内核空间和从内核空间卸载的。因此,内核模块是为了给内核动态增减功能而设计的,并不仅仅是限于驱动程序。当用户输入命令“insmod 模块文件名”加载内核模块时,系统会检测此模块能否被加载,如果能被加载,内核调用模块的初始化函数module_init()(2.4内核为init_module())。当用户输入命令“rmmod 模块文件名”卸载内核模块时,此时,系统会检测此模块是否能被卸载,内核将调用模块清除函数module_exit()(2.4内核为cleanup_module())。

相关内容