日期:2014-05-16  浏览次数:20763 次

linux简单的字符设备驱动程序

要求:掌握添加设备驱动程序的方法

内容:
采用模块方法,添加一个新的设备驱动程序。
要求添加字符设备的驱动。

编写一个应用程序,测试添加的驱动程序。

<style type="text/css"> <!-- p {margin-bottom:0.21cm} --> </style>

linxu系统中,在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:

  1. 对设备初始化和释放.

  2. 把数据从内核传送到硬件和从硬件读取数据.

  3. 读取应用程序传送给设备文件的数据和回送应用程序请求的数据.

  4. 检测和处理设备出现的错误.

设备分为两种:字符设备和块设备,这里就以简单的字符设备为例。

<style type="text/css"> <!-- p {margin-bottom:0.21cm} --> </style>

在设备驱动程序中有一个非常重要的结构file_operations,该结构的每个域都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。

struct file_operations {

int(*seek) (struct inode * ,structfile *, off_t ,int);
int (*read) (struct inode * ,structfile *, char ,int);
int (*write) (struct inode * ,structfile *, off_t ,int);

……

}
<style type="text/css"> <!-- p {margin-bottom:0.21cm} --> </style>

编写设备驱动程序的主要工作是编写子函数,并填充file_operations的各个域

例如:

Structfile_operations my_fops={

.read=my_read,

.write=my_write,

.open=my_open,

.release=my_release

}

<style type="text/css"> <!-- p {margin-bottom:0.21cm} --> </style>

然后再定义函数my_read,my_write,my_open,my_release相应的函数体。

例如:

staticssize_t my_open(struct inode *inode,struct file *file){

staticint counter=0;

if(Device_Open)

return-EBUSY;

Device_Open++;

/*写入设备的信息*/

sprintf(msg,"the device hasbeen called %d times\n",counter++);

msg_ptr=msg;

return0;

}

<style type="text/css"> <!-- p {margin-bottom:0.21cm} --> </style>

同时对于可卸载的内核模块(LKM),至少还有两个基本的模块:

<style type="text/css"> <!-- p {margin-bottom:0.21cm} --> </style>

my_init用于注册设备,获得设备的主设备号

调用register_chrdev(0,“sky_driver(设备名)”,&my_fops);

my_exit用于注销设备