荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标 题: Unix驱动程序开发过程及分析 wupei (转寄)[转载]
发信站: 荔园晨风BBS站 (Sun Apr 21 22:52:38 2002), 转信
【 以下文字转载自 jjk 的信箱 】
【 原文由 jjksam@smth.org 所发表 】
发信人: Pasific (饮水思源), 信区: KernelTech
标 题: Unix驱动程序开发过程及分析
发信站: BBS 水木清华站 (Tue Oct 9 19:08:24 2001)
序言:
对于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
};
--
※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.167.231]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店