当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > 字符设备驱动在Linux系统中和在VxWorks系统中的异同

字符设备驱动在Linux系统中和在VxWorks系统中的异同 时间:2018-09-26      来源:未知

Linux和VxWorks是嵌入式系统中很常见的两种操作系统。Linux由于其高度的可裁剪性和可移植性,目前已被广泛地应用在了嵌入式领域。VxWorks以高可靠性和实时性著称,在航空、军工、医疗等领略有着广泛的应用。二者的关键特性对比如下:

尽管两者在具体实现上有巨大的差异,但是某些基本的思想是相通的。本文从二者的字符设备驱动实现形式进行对比分析,可以发现二者在实现思想上存在极大的相似之处。

一个的典型Linux字符设备驱动有一个包含struct cdev类型成员的结构体,另外还有一个struct file_operations的操作方法集合的结构体。通常的形式如下:

struct xxx_dev {

struct cdev cdev;

……

};

static struct xxx_dev xxx_dev;

static struct file_operations xxx_ops = {

.open = xxx_open,

.release = xxx_close,

.read = xxx_read,

.write = xxx_write,

……

};

在VxWorks中也有类似的一个结构体,通常的形式如下:

typedef struct _xxx_dev {

DEV_HDR pDevHdr;

……

}XXX_DEV;

XXX_DEV xxxDev;

其中pDevHdr是用于把VxWorks中的所有这些字符设备链接在一起的指针。

在Linux中需要初始化包含cdev的那个结构体的各个成员,并完成与设备号和操作方法集合的绑定,后注册该结构体。典型的代码如下:

static int __init fschr_init(void)

{

……

ret = register_chrdev_region(devno, XXX_NR, XXX_NAME);

……

cdev_init(&xxx_dev.cdev, &xxx_ops);

……

ret = cdev_add(&xxx_dev.cdev, devno, XXX_NR);

}

在VxWorks中,也有类似的一个过程,通过调用iosDrvInstall来注册一个字符设备驱动,同时绑定好操作方法集合,并返回一个驱动号。典型的代码如下:

STATUS xxxDrv(void) or

STATUS xxxInit(int arg, ...)

{

xxxDrvNum = iosDrvInstall(

NULL, /* Create */

NULL, /* delete */

xxxOpen,

xxxClose,

xxxRead,

xxxWrite,

xxxIoctl);

}

在此基础之上,通过调用iosDevAdd将刚才的设备结构体和新注册的设备驱动关联(主要是和驱动号和操作方法集合进行绑定)。典型的代码如下:

STATUS xxxDevCreate(int arg, ...)

{

iosDevAdd(&xxxDev.pDevHdr, devName, xxxDrvNum);

}

在字符设备的访问上,Linux通过文件系统的那套机制将对设备文件的访问终转化为对相应的字符设备驱动中的操作方法的调用,过程相对来说比较复杂,在此不展开叙述。在VxWorks中这个流程相对要精简得多,通过下图可以很清晰地了解这个过程。

上面通过设备路径直接找到设备结构体(通过名字来对应),因为设备结构体和驱动号关联,所以可以找到对应的驱动,后调用驱动提供的操作方法。一个简单的VxWorks字符设备驱动的完整代码如下:

#include "sioLib.h"

#include "stdio.h"

#include "iosLib.h"

#include "string.h"

typedef struct {

DEV_HDR pDevHdr;

char buf[256];

}CHR_DEV;

LOCAL CHR_DEV chrDev;

LOCAL int chrDrvNum = -1;

LOCAL int chrOpen(DEV_HDR *pDevHdr, char *name, int flags, int mode)

{

return (int)pDevHdr;

}

LOCAL STATUS chrClose(DEV_HDR *pChrDev)

{

return OK;

}

LOCAL int chrRead(CHR_DEV *pChrDev, char *buffer, int nbytes)

{

int len;

len = nbytes > 256 ? 256 : nbytes;

memcpy(buffer, pChrDev->buf, len);

return len;

}

LOCAL int chrWrite(CHR_DEV *pChrDev, char *buffer, int nbytes)

{

int len;

len = nbytes > 256 ? 256 : nbytes;

memcpy(pChrDev->buf, buffer, len);

return len;

}

LOCAL STATUS chrDrv(void)

{

if (chrDrvNum != -1) {

printf("fschr: driver has already been installed\n");

return (OK);

}

chrDrvNum = iosDrvInstall(NULL,

NULL,

chrOpen,

chrClose,

chrRead,

chrWrite,

NULL);

if (chrDrvNum == ERROR) {

printf("fschr: install driver failed\n");

return (ERROR);

} else {

printf("fschr: install driver success\n");

return (OK);

}

}

LOCAL STATUS chrDeviceCreate(void)

{

if (iosDevAdd(&chrDev.pDevHdr, "/dev/fsdev", chrDrvNum) == ERROR) {

printf("fschr: add device failed\n");

return (ERROR);

} else {

printf("fschr: add device success\n");

return (OK);

}

}

STATUS fsChrProbe(void)

{

if (chrDrv() == ERROR) {

return (ERROR);

} else {

return chrDeviceCreate();

}

}

fsChrProbe是入口函数,在这个函数中分别调用chrDrv和chrDeviceCreate去注册了驱动和设备,并完成了上述的绑定工作。之后对设备进行访问时,对应驱动的操作方法将会被调用。Linux也可以实现上面类似的一个字符设备驱动,详细的代码不再列出。

VxWorks的测试应用程序代码如下,Linux的与之类似。

#include

#include

#include

#include

int main(int argc, char *argv[])

{

int fd;

int ret;

char *wbuf = "I Love embedded system!\n";

char rbuf[256];

fd = open("/dev/fsdev", O_RDWR, 0);

if (fd < 0) {

perror("fsdev");

return -1;

}

ret = write(fd, wbuf, strlen(wbuf) + 1);

if (ret < 0) {

perror("fsdev");

close(fd);

return ret;

}

ret = read(fd, rbuf, sizeof(rbuf));

if (ret < 0) {

perror("fsdev");

close(fd);

return ret;

}

printf("read data: %s", rbuf);

close(fd);

}

Linux系统上测试的效果如下:

VxWorks系统上的测试效果如下:

上一篇:Service中onRebind何时被调用

下一篇:C语言的内存分配和段错误的处理

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部