- 论坛徽章:
- 0
|
序言:
对于unix的动态驱动程序,我们称之为逻辑上的驱动程序,因为它不和任何的硬件设备相连接。这种驱动程序能够生成数据文件、监测打印机、或者产生大量不挤占磁盘空间的随机数据。
目标:
1.设计一个简单的设备驱动程序
2.研究用户程序如何与设备进行交互数据
3.知道动态装入
正文:
我们用一个长字符串"How are you?"作为输出结果。当用户程序调用设备程序时,设备程序将会把字符串放到一个缓冲区中,而这个缓冲区也能为用户程序所访问。如:
bytes_read = read(fileDescr, buffer, sizeof(buffer));
其中,fileDescr是系统调用的文件描述符;
buffer 是字符串的缓冲区;
当我们调用此函数,核心进程就会执行设备驱动程序,设备驱动程序就会通过这一接口把字符串数据写入buffer缓冲区中,接着用户程序就能得到此字符串的内容、属性。
下面,我将介绍一下unix驱动程序的安装过程、入口。首先,系统监测驱动设备是否存在;接着,设备初始化;分配内存并且和一定数据结构对应;初始化着一数据结构并赋值;最后,赋以指针指向此结构。这样我们就能够着手设计了。
首先,定义数据结构,其包含字符串长度、内存区间:
/*drv1info.h*/
#define STRLEN 45
struct drv1info {
char foxmessage[STRLEN];
};
我们对字符串进行初始化:
/* drv1info.c*/
#include "drv1info.h"
struct drv1info drv1info0 = {
"How are you?.\n"
};
我们再定义一个数据静态类型,通过它调用字符串信息,调用之后要求释放其内存:
struct drv1statics {
char *foxmessage;
};
数据结构定义之后,我们就要设计驱动程序的入口了。我们知道,系统打开设备驱动程序时,系统首先确定此文件类型,同时系统使用主设备号与设备驱动程序接口绑定,如果不成功,则使用此设备号。如果都不成功,那末就无法打开此设备驱动程序了。
设备驱动程序入口的建立,主要通过数据结构进行,系统能够提供服务即使用此数据区,用户程序能够读取此数据区接收服务,相当于客户。这种方式是应用unix的系统设备服务调用(sysbrk driver service call):
struct drv1statics *sp; /* allocate a (s)tatics (p)ointer */
/* allocate memory for the statics structure */
if (!(sp = (struct drv1statics *) sysbrk((long) sizeof *sp) ))
return (char *) SYSERR;
指向此数据结构的指针sp->;foxmessage,其内容是:How are you?。对此字符串的引用为:
if (!(sp->;foxmessage = sysbrk((long) STRLEN)))
sysfree(sp, (long)sizeof *sp);
return (char *) SYSERR;
}
由上可见,如果条件成立,那末静态数据的内存区将被释放。但是,其返回的数据为字符指针,给出结果情况。如果分配到缓冲区了,则有:
strcpy(sp->;foxmessage, info->;foxmessage);
它把info->;foxmessage("How are you?" 通过字符串函数拷贝给sp->;foxmessage。
如果设备驱动程序不能成功初始化,许多已分空间要释放:
void drv1uninstall(sp)
struct drv1statics *sp;
{
sysfree(sp->;foxmessage,(long)STRLEN);
sysfree(sp, (long)sizeof *sp);
}
读接口数据,即驱动程序把数据写到数据缓冲区的过程:
int drv1read(sp, fp, buf, count)
struct drv1statics *sp;
struct file *fp;
char *buf;
int count;
{
int index=0;
static long offset=0;
if (wbounds(buf) < count) {
pseterr(EFAULT);
return(SYSERR);
}
while (count) {
*(buf+index) = sp->;foxmessage[offset%(STRLEN-1)];
index++;
offset++;
count--;
}
return index;
}
设备驱动程序被初始化之后,如何动态装载,只需在入口点结构前加上dldd
编译动态属性即可:
#include <dldd.h>;
/* Add this statement to the end of drv1drvr.c */
static struct dldd entry_points = {
ionull, /* open */
ionull, /* close */
drv1read, /* read */
ionull, /* write */
ionull, /* select */
ionull, /* ioctl */
drv1install, /* install */
drv1uninstall, /* uninstall */
(char *) 0
};
此设备驱动程序编译步骤:
1,#cc -c drv1drvr.c
编译成为目标文件drv1drvr.o
2, #drinstall -c drv1drvr.o
drv1drvr.o xid
安装测试设备程序,若成功返回设备号(xid)
3. # devinstall -c -d xid drv1drvr.o
若生成设备文件名:Un_driver
4. # mknod /dev/Un_driver c xid 0 0444
给此设备分配节点,用户程序能够通过节点访问设备驱动程序。
至此,设备驱动程序设计过程结束。下面我们如何调用它略举一例:
/* drv1test.c */
#include <io.h>;
#include <fcntl.h>;
#include <stdio.h>;
main() {
int fildes;
char buffer[100];
fildes = open ("/dev/Un_driver",O_RDONLY);
if (sizeof(buffer) == read (fildes, buffer, sizeof(buffer)))
write(1,buffer,sizeof (buffer));
else
printf("操作失败!" ;
}
附整个程序:
/* drv1info.h */
#define STRLEN 45
struct drv1info {
char foxmessage[STRLEN];
};
--------------------------------------------------------------------------------
/* drv1info.c */
#include "drv1info.h"
struct drv1info drv1info0 = {
"How are you?.\n";
};
main() {
write (1,&drv1info0,sizeof (struct drv1info));
}
--------------------------------------------------------------------------------
/* drv1drvr.c */
#include <io.h>;
#include <conf.h>;
#include <kernel.h>;
#include <mem.h>;
#include <file.h>;
#include <errno.h>;
#include <dldd.h>;
#include "drv1info.h"
struct drv1statics {
char *foxmessage;
};
extern int ionull();
char *drv1install(info)
struct drv1info *info;
{
struct drv1statics *sp;
int i;
if (!(sp = (struct drv1statics *) sysbrk((long) sizeof *sp) ))
return (char *) SYSERR;
if (!(sp->;foxmessage = sysbrk((long) STRLEN))) {
sysfree(sp, (long)sizeof *sp);
return (char *) SYSERR;
}
strcpy(sp->;foxmessage, info->;foxmessage);
return (char *) sp;
}
void drv1uninstall(sp)
struct drv1statics *sp;
{
sysfree(sp->;foxmessage,(long)STRLEN);
sysfree(sp, (long)sizeof *sp);
}
int drv1read(sp, f, buf, count)
struct drv1statics *sp;
struct file *f;
char *buf;
int count;
{
int index=0;
static long offset=0;
if (wbounds(buf) < count) {
pseterr(EFAULT);
return(SYSERR);
}
while (count) {
*(buf+index) = sp->;foxmessage[offset%(STRLEN-1)];
index++;
offset++;
count--;
}
return index;
}
static struct dldd entry_points = {
ionull, /* open */
ionull, /* close */
drv1read, /* read */
ionull, /* write */
ionull, /* select */
ionull, /* ioctl */
drv1install, /* install */
drv1uninstall, /* uninstall */
(char *) 0
}; |
|