荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: 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软件 网络书店