要求:基于VxWorks的内存模拟型的字符IO设备驱动程序的设计,并编写应用程序实现任务间的通信,编写makefile文件。
基于VxWorks的内存模拟型的字符IO设备驱动程序的设计
1 内存模拟型的字符IO设备驱动程序memDrv.c
/* memDrv.c - pseudo memory device driver */
#include "memDrv.h"
/*memDrv - install a memory driver*/
STATUS memDrv (void)
{
/* If driver already installed, just return */
if (memDrvNum > 0)
return (OK); /* driver already installed */
/* driver initialization, if any, here */
/* add driver to driver table */
memDrvNum = iosDrvInstall ((FUNCPTR) NULL, (FUNCPTR) NULL,
(FUNCPTR) memOpen, memClose,
memRead, memWrite, memIoctl);
return (memDrvNum == ERROR ? ERROR : OK);
}
/*memDevCreate - create a memory device*/
STATUS memDevCreate
(
char * name, /* device name */
char * base, /* where to start in memory */
int length /* number of bytes */
)
{
STATUS status;
FAST MEM_DEV *pMemDv;
if (memDrvNum < 1)
{
errnoSet (S_ioLib_NO_DRIVER);
return (ERROR);
}
if ((pMemDv = (MEM_DEV *) calloc (1, sizeof (MEM_DEV))) == NULL)
return (ERROR);
pMemDv->MemBase=base;
status = iosDevAdd ((DEV_HDR *) pMemDv, name, memDrvNum);
if (status == ERROR)
free ((MEM_DEV *) pMemDv);
return (status);
}
LOCAL MEM_DEV_PER_FD *memOpen
(
MEM_DEV *pMemDv, /* pointer to memory device descriptor */
char *name, /* name of file to open (a number) */
int mode /* access mode (O_RDONLY,O_WRONLY,O_RDWR) */
)
{
MEM_DEV_PER_FD *pMemDevPerFd = NULL;
pMemDevPerFd = (MEM_DEV_PER_FD *) calloc(1,sizeof(MEM_DEV_PER_FD));
if (pMemDevPerFd != NULL)
{
pMemDevPerFd->pMemDev = (MEM_DEV *) pMemDv;
pMemDevPerFd->allowOffset2 = 0;
return pMemDevPerFd;
}
else
return (MEM_DEV_PER_FD *) ERROR;
}
/*memRead - read from a memory IO device*/
LOCAL int memRead
(
MEM_DEV_PER_FD *pfd, /* file descriptor of file to read */
char *buffer, /* buffer to receive data */
int maxbytes /* max bytes to read in to buffer */
)
{
bcopy (pfd->pMemDev->MemBase,buffer, maxbytes);
return (maxbytes);
}
/*memWrite - write to a memory IO device */
LOCAL int memWrite
(
MEM_DEV_PER_FD *pfd, /* file descriptor of file to write */
char *buffer, /* buffer to be written */
int nbytes /* number of bytes to write from buffer */
)
{
temp=pfd->pMemDev->MemBase;
/* for(count=0;count<nbytes;count++)
{
bcopy (buffer,temp, 1);
buffer=buffer+1;
temp=temp+1;
taskDelay(1);
}
*/
bcopy (buffer,pfd->pMemDev->MemBase, nbytes);
return (nbytes);
}
/* memIoctl - do device specific control function */
LOCAL STATUS memIoctl (pfd, function, arg)
MEM_DEV_PER_FD *pfd; /* descriptor to control */
FAST int function; /* function code */
int arg; /* some argument */
{
return (OK);
}
/*memClose - close a memory IO device */
LOCAL STATUS memClose (pfd)
MEM_DEV_PER_FD *pfd; /* file descriptor of file to close */
{
free (pfd);
return OK;
}
STATUS memDevDelete(char * devName)
{
DEV_HDR *pDevHdr;
char *pNameTail;
pDevHdr = iosDevFind (devName, &pNameTail);
if (pDevHdr == NULL || *pNameTail != '\0')
return (ERROR);
iosDevDelete (pDevHdr);
free ((MEM_DEV *) pDevHdr);
return (OK);
}
STATUS memDrvRemove()
{
/*check device driver exist */
if(memDrvNum!=-1)
{ if(iosDrvRemove(memDrvNum,TRUE)==ERROR)
{
printErr("Fail to unload driver.\n");
return ERROR;
}
}
memDrvNum=-1;
}
2 设备驱动程序的头文件memDrv.h
#include "copyright_wrs.h"
#include "vxWorks.h"
#include "stat.h"
#include "dirent.h"
#include "memLib.h"
#include "errnoLib.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "ioLib.h"
#include "iosLib.h"
typedef struct /* MEM_DEV - memory device descriptor */
{
DEV_HDR devHdr;
char *MemBase;
int allowOffset1;
} MEM_DEV;
typedef struct /* MEM_DEV_PER_FD - memory deviceId */
{
MEM_DEV *pMemDev;
int allowOffset2;
} MEM_DEV_PER_FD;
/* forward declarations */
LOCAL int memDrvNum;
LOCAL char *temp; /* driver number of memory driver */
LOCAL int count;
/*MEM_DEV_PER_FD pMemDevPerFd;*/
STATUS memDrv ();
STATUS memDevCreate();
LOCAL MEM_DEV_PER_FD *memOpen ();
LOCAL int memRead ();
LOCAL int memWrite ();
LOCAL int memClose ();
LOCAL STATUS memIoctl ();
STATUS memDevDelete();
STATUS memDrvRemove();
3 IO设备驱动实现任务间的通信的程序代码memIoDemo.c
/* includes */
#include "vxWorks.h"
#include "taskLib.h"
#include "msgQLib.h"
#include "sysLib.h"
#include "stdio.h"
#include "ioLib.h"
#include "memDrv.h"
#define MemIoDev_NAME "/memIoDevice" /* 虚拟内存IO设备的文件名*/
#define PRODUCER_TASK_PRI 98 /* Priority of the producer task */
#define CONSUMER_TASK_PRI 99 /* Priority of the consumer task */
#define TASK_STACK_SIZE 5000 /* stack size for spawned tasks */
#define PRODUCER_TASK_MSG 3
#define CONSUMER_TASK_MSG 3
struct msg { /* data structure for msg passing */
int tid; /* task id */
int value; /* msg value */
};
LOCAL int memIoFd;
LOCAL BOOL notDone; /* Flag to indicate the completion
of this demo */
/* function prototypes */
LOCAL STATUS producerTaskFunc (); /* producer task */
LOCAL STATUS consumerTaskFunc (); /* consumer task */
/*memIoDevDemo */
int main (void)
{
notDone = TRUE; /* initialize the global flag */
printf ("memIoDevDemo\r\n");
if(memDrv()== ERROR)
{
perror("Error in installing memory IO Device");
}
if (memDevCreate (MemIoDev_NAME, calloc(1,20), sizeof (struct msg)) == ERROR)
{
perror ("Error in creating memory IO Device");
}
if ((memIoFd = open (MemIoDev_NAME, O_RDWR, 0)) == ERROR)
{
perror ("Error in opening memory IO device");
return (ERROR);
}
/* Spwan the producerTask task */
if (taskSpawn ("tProducerTask", PRODUCER_TASK_PRI, 0, TASK_STACK_SIZE,
(FUNCPTR) producerTaskFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
== ERROR)
{
perror ("producerTask: Error in spawning demoTask");
return (ERROR);
}
/* Spwan the consumerTask task */
if (taskSpawn ("tConsumerTask", CONSUMER_TASK_PRI, 0, TASK_STACK_SIZE,
(FUNCPTR) consumerTaskFunc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
== ERROR)
{
perror ("consumerTask: Error in spawning demoTask");
return (ERROR);
}
return (OK);
}
/*****************************************************************************
* producerTask - produces messages, and sends messages to the consumerTask
* using the message queue.
*
* RETURNS: OK or ERROR
*
*/
STATUS producerTaskFunc (void)
{
int count;
int value;
struct msg producedItem; /* producer item - produced data */
printf ("producerTask started: task id = %#x \n", taskIdSelf ());
/* Produce 2 number of messages and send these messages */
for (count = 1; count <= PRODUCER_TASK_MSG; count++)
{
value = count * 20; /* produce a value */
/* Fill in the data structure for message passing */
producedItem.tid = taskIdSelf ();
producedItem.value = value;
/* Send Messages */
if ((write (memIoFd, (char *)&producedItem, sizeof (producedItem))) == ERROR)
{
perror ("Error in sending the message");
return (ERROR);
}
else
printf ("ProducerTask: tid = %#x, produced value = %d \n",
taskIdSelf (), value);
}
if(PRODUCER_TASK_PRI > CONSUMER_TASK_PRI)
{
memDevDelete("/memIoDevice");
memDrvRemove();
}
return (OK);
}
/*****************************************************************************
* consumerTask - consumes all the messages from the message queue.
*
* RETURNS: OK or ERROR
*
*/
STATUS consumerTaskFunc (void)
{
int count;
struct msg consumedItem; /* consumer item - consumed data */
printf ("\n\nConsumerTask: Started - task id = %#x\n", taskIdSelf());
/* consume 3 number of messages */
for (count = 1; count <= CONSUMER_TASK_MSG; count++)
{
if (read (memIoFd, (char *)&consumedItem, sizeof (consumedItem)) == ERROR)
{
perror ("Error in receiving the message");
return (ERROR);
}
else
printf ("ConsumerTask: Consuming msg of value %d from tid = %#x\n",
consumedItem.value, consumedItem.tid);
}
if(PRODUCER_TASK_PRI < CONSUMER_TASK_PRI)
{
memDevDelete("/memIoDevice");
memDrvRemove();
}
return (OK);
}
4 makefile文件
CC=ccsimpc
CFLAGS=-g -O0
all:memIoDevDemo.o memDrv.o
$(CC) $(CFLAGS) memIoDevDemo.o memDrv.o -o all
memIoDevDemo.o:memIoDevDemo.c
$(CC) $(CFLAGS) -c memIoDevDemo.c -o memIoDevDemo.o
memDrv.o:memDrv.c
$(CC) $(CFLAGS) -c memDrv.c -o memDrv.o
.phony:clean
clean:
-vxrm memIoDevDemo.o memDrv.o
5 运行步骤
5.1 在命令提示符下执行make命令
利用命令提示符执行make命令和make clean命令。
5.2 在windSh下加载模块all
在windSh下加载模块all,并执行main函数。
5.3 打印任务间通信结果
下图是打印在模拟器上的两任务间通信结果,生产者任务优先级高于消费者,生产者任务先运行,三次向同一段内存分别写入20、40、60。紧接着消费者任务运行,读取生产者写入那段内容,但三次读取到的数据均为60,因为生产者每次写入都会覆盖上一次写入的数据,所以最终只能读到数据60。