目录
3 创建VxWorks Image Project(VIP)项目
3 创建VxWorks Image Project(VIP)项目
就是用已编译好的组件创建一个VxWorks版本,组件包括标准组件和VSB生成的组件。(本教程使用VSB生成的组件)
需要提前确认的几个问题:
- 你的镜像是运行到VxWorks模拟器上还是实际的目标板上?
- 你想继承已经存在的项目吗?
- 你想从一开始就包含调试和网络支持吗?是否有团队成员构建了VSB项目?
3.1 创建VIP项目
File > New >VxWorks Image Project
1)镜像名称
2)“Based on”选择之前创建的VSB项目,配置BSP和Tool chain
3)选择配置概要文件“Profile”设置为“PROFILE_DEVELOPMENT”
PROFILE_DEVELOPMENT包含了一些标准开发和调试工具。
4)点击“Finish”完成创建
3.2 配置VIP组件
3.2.1 组件分类
1)Shell命令组件:用于在运行时启动、停止、修改应用程序;
2)系统日志组件:用于捕获运行时调试信息,设置调试级别;
3)系统变量组件;
4)接口配置组件:ifconfig获取网络接口信息;
5)环回接口组件:环回接口为FTP/Telnet提供一个稳定的地址,可用于本机通信;
6)网络接口组件:运行到真实目标板的VIP项目需要配置正确的网络接口;
3.2.2 默认添加的组件
INCLUDE_DEBUG:断点、堆栈跟踪
INCLUDE_DISK_UTIL:文件系统工具,如cd、copy、ls、mkdir等
INCLUDE_DISK_UTIL_SHELL_CMD:与文件系统相关的shell命令解释器的命令列表
INCLUDE_IPCOM_SHELL_CMD:IPCOM shell命令接口
INCLUDE_IPIFCONFIG_CMD:ifconfig shell命令接口
INCLUDE_IPNET_IFCONFIG_1:接口配置
INCLUDE_IPNET_USE_LOOPBACK:环回接口支持
INCLUDE_IPNET_LOOPBACK_CONFIG:环回接口缺省参数配置
INCLUDE_IPTCP:TCP协议
INCLUDE_SHELL:交互开发、原型设计、编译和测试的解释器
INCLUDE_SHELL_INTERP_CMD:内核shell命令解释器
INCLUDE_SOCKLIB:Socket API
INCLUDE_SYM_SHELL_CMD:符号访问相关的shell命令解释器命令列表
INCLUDE_WDB:支持Workbench 工具的软件代理
3.2.3 其他组件
如果需要获取网络组件详细调试信息,可添加下列组件:
INCLUDE_IPCOM_SYSLOGD_CMD:系统日志,syslog命令
INCLUDE_IPCOM_SYSLOGD_USE_LOG_FILE:IPCOM syslogd日志文件
INCLUDE_IPCOM_SYSVAR_CMD:系统变量,sysvar命令
INCLUDE_IPFTPS:FTP服务
INCLUDE_IPCOM_USE_AUTH:用户身份验证
INCLUDE_IPCOM_FS_NATIVE: IPCOM使用本地VxWorks文件系统
INCLUDE_PING:ICPMP客户端,ping命令
INCLUDE_ROUTECMD:route命令
INCLUDE_USER_CMD:IPCOM auth命令
其他有用的组件:
INCLUDE_IPNETSTAT_CMD:netstat命令(用于socket和静态路由)
INCLUDE_IPROUTE_CMD:route命令(用于路由表配置)
INCLUDE_IPD_CMD:用于IPD守护进程的IPCOM相关命令
3.2.4 为VIP项目添加组件
双击VIP项目下的“Kernel Configuration”打开组件配置界面。
1)查找要添加的组件
Ctrl+F / 右键Find都可以打开查找界面,输入“INCLUDE_IPCOM_SYSLOGD_CMD”,自动查找。
双击找到的节点“IPCOM syslog commands”,会在组件配置界面高亮显示。
2)添加组件
在“IPCOM syslog commands”右键“Include”,打开“Include”界面,点击“Finish”完成添加组件,workbench会自动添加关联的其他组件。
添加组件完成后,该组件以黑色加粗字体显示。
3)添加剩余组件
INCLUDE_IPCOM_SYSLOGD_USE_LOG_FILE
INCLUDE_IPCOM_SYSVAR_CMD
INCLUDE_IPFTPS
INCLUDE_IPCOM_USE_AUTH
INCLUDE_IPCOM_FS_NATIVE
INCLUDE_PING
INCLUDE_ROUTECMD
INCLUDE_USER_CMD
INCLUDE_IPIFCONFIG_CMD
4)修改组件参数
选择“IPCOM_SYSLOGD_DEFAULT_PRIORITY”组件,右键“Change Value” or 直接双击“Value”值,键入新的参数“IPCOM_LOG_DEBUG”,Ctrl+S保存。
3.2.5 网络接口配置
如果该VIP项目生成的镜像用于真实的目标板上,那么需要进行网络接口配置,此教程的镜像用于模拟器,此处忽略。
4 创建DKM项目
Downloadable Kernel Module(DKM)项目用于构建存储于内核空间的模块。你可以在VxWorks目标机上单独构建、运行、调试这些模块,快速加载、卸载和重加载。一旦开发工作完成,可将这些模块静态链接到内核。
4.1 创建DKM项目
File > New > VxWorks Downloadable Kernel Module Project 打开创建界面。
1)项目名称
2)“Next”一直到“Build Specs”界面,配置为“SIMNTgnu”。(与VIP项目中的一致)
3)Finish完成
4.2 编写DKM代码
TCP通信案例,包含三个文件:tcpExample.h、tcpServer.c、tcpClient.c。这些文件可以从 https://resources.windriver.com/ 右上角搜索“Example Files for Wind River VxWorks Platforms, 6.9”找到Demo代码,但是需要注册用户。
1)File > New > File,创建三个源代码文件:tcpExample.h、tcpServer.c、tcpClient.c。
2)编写代码
tcpExample.h
/* tcpExample.h - header used by both TCP server and client examples */
/* defines */
#define SERVER_PORT_NUM 5432 /* server's port number for bind() */
#define SERVER_WORK_PRIORITY 100 /* priority of server's work task */
#define SERVER_STACK_SIZE 10000 /* stack size of server's work task */
#define SERVER_MAX_CONNECTIONS 4 /* max clients connected at a time */
#define REQUEST_MSG_SIZE 1024 /* max size of request message */
#define REPLY_MSG_SIZE 500 /* max size of reply message */
/* structure for requests from clients to server */
struct request {
int reply; /* TRUE = request reply from server */
int msgLen; /* length of message text */
char message[REQUEST_MSG_SIZE]; /* message buffer */
};
tcpServer.c
/* tcpServer.c - TCP server example */
/*
DESCRIPTION
This file contains the server-side of the VxWorks TCP example code. The example code demonstrates the
usage of several BSD 4.4-style socket routine calls.
*/
/* includes */
#include "vxWorks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "taskLib.h"
#include "stdioLib.h"
#include "strLib.h"
#include "ioLib.h"
#include "fioLib.h"
#include "tcpExample.h"
/* function declarations */
VOID tcpServerWorkTask(int sFd, char * address, u_short port);
/****************************************************************************
*
* tcpServer - accept and process requests over a TCP socket
*
* This routine creates a TCP socket, and accepts connections over the socket
* from clients. Each client connection is handled by spawning a separate
* task to handle client requests.
*
* This routine may be invoked as follows:
* -> sp tcpServer
* task spawned: id = 0x3a6f1c, name = t1
* value = 3829532 = 0x3a6f1c
* -> MESSAGE FROM CLIENT (Internet Address 150.12.0.10, port 1027):
* Hello out there
*
* RETURNS: Never, or ERROR if a resources could not be allocated.
*/
STATUS tcpServer(void) {
struct sockaddr_in serverAddr; /* server's socket address */
struct sockaddr_in clientAddr; /* client's socket address */
int sockAddrSize; /* size of socket address structure */
int sFd; /* socket file descriptor */
int newFd; /* socket descriptor from accept */
int ix = 0; /* counter for work task names */
char workName[16]; /* name of work task */
/* set up the local address */
sockAddrSize = sizeof(struct sockaddr_in);
bzero((char *) &serverAddr, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_port = htons(SERVER_PORT_NUM);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/* create a TCP-based socket */
if ((sFd = socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror("socket");
return (ERROR);
}
/* bind socket to local address */
if (bind(sFd, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR) {
perror("bind");
close(sFd);
return (ERROR);
}
/* create queue for client connection requests */
if (listen(sFd, SERVER_MAX_CONNECTIONS) == ERROR) {
perror("listen");
close(sFd);
return (ERROR);
}
/* accept new connect requests and spawn tasks to process them */
FOREVER {
if ((newFd = accept(sFd, (struct sockaddr *) &clientAddr, &sockAddrSize)) == ERROR) {
perror("accept");
close(sFd);
return (ERROR);
}
sprintf(workName, "tTcpWork%d", ix++);
if (taskSpawn(workName, SERVER_WORK_PRIORITY, 0, SERVER_STACK_SIZE,
(FUNCPTR) tcpServerWorkTask, newFd,
(int) inet_ntoa(clientAddr.sin_addr),
ntohs(clientAddr.sin_port), 0, 0, 0, 0, 0, 0, 0) == ERROR) {
/* if taskSpawn fails, close fd and return to top of loop */
perror("taskSpawn");
close(newFd);
}
}
}
/****************************************************************************
*
* tcpServerWorkTask - process client requests
*
* This routine reads from the server's socket, and processes client
* requests. If the client requests a reply message, this routine
* will send a reply to the client.
*
* RETURNS: N/A.
*/
VOID tcpServerWorkTask(int sFd, /* server's socket fd */
char * address, /* client's socket address */
u_short port /* client's socket port */
) {
struct request clientRequest; /* request/message from client */
int nRead; /* number of bytes read */
static char replyMsg[] = "Server received your message";
/* read client request, display message */
while ((nRead = fioRead(sFd, (char *) &clientRequest, sizeof(clientRequest))) > 0) {
printf("MESSAGE FROM CLIENT (Internet Address %s, port %d):\n%s\n", address, port, clientRequest.message);
if (clientRequest.reply)
if (write(sFd, replyMsg, sizeof(replyMsg)) == ERROR)
perror("write");
}
if (nRead == ERROR) /* error from read() */
perror("read");
close(sFd); /* close server socket connection */
}
tcpClient.c
/* tcpClient.c - TCP client example */
/*
DESCRIPTION
This file contains the client-side of the VxWorks TCP example code.
The example code demonstrates the usage of several BSD 4.4-style
socket routine calls.
*/
/* includes */
#include "vxWorks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "stdioLib.h"
#include "strLib.h"
#include "hostLib.h"
#include "ioLib.h"
#include "tcpExample.h"
/****************************************************************************
*
* tcpClient - send requests to server over a TCP socket
*
* This routine connects over a TCP socket to a server, and sends a
* user-provided message to the server. Optionally, this routine
* waits for the server's reply message.
*
* This routine may be invoked as follows:
* -> tcpClient "remoteSystem"
* Message to send:
* Hello out there
* Would you like a reply (Y or N):
* y
* value = 0 = 0x0
* -> MESSAGE FROM SERVER:
* Server received your message
*
* RETURNS: OK, or ERROR if the message could not be sent to the server.
*/
STATUS tcpClient(char * serverName /* name or IP address of server */) {
struct request myRequest; /* request to send to server */
struct sockaddr_in serverAddr; /* server's socket address */
char replyBuf[REPLY_MSG_SIZE]; /* buffer for reply */
char reply; /* if TRUE, expect reply back */
int sockAddrSize; /* size of socket address structure */
int sFd; /* socket file descriptor */
int mlen; /* length of message */
/* create client's socket */
if ((sFd = socket(AF_INET, SOCK_STREAM, 0)) == ERROR) {
perror("socket");
return (ERROR);
}
/* bind not required - port number is dynamic */
/* build server socket address */
sockAddrSize = sizeof(struct sockaddr_in);
bzero((char *) &serverAddr, sockAddrSize);
serverAddr.sin_family = AF_INET;
serverAddr.sin_len = (u_char) sockAddrSize;
serverAddr.sin_port = htons(SERVER_PORT_NUM);
if (((serverAddr.sin_addr.s_addr = inet_addr(serverName)) == ERROR)
&& ((serverAddr.sin_addr.s_addr = hostGetByName(serverName)) == ERROR)) {
perror("unknown server name");
close(sFd);
return (ERROR);
}
/* connect to server */
if (connect(sFd, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR) {
perror("connect");
close(sFd);
return (ERROR);
}
/* build request, prompting user for message */
printf("Message to send: \n");
mlen = read(STD_IN, myRequest.message, REQUEST_MSG_SIZE);
myRequest.msgLen = mlen;
myRequest.message[mlen - 1] = '\0';
printf("Would you like a reply (Y or N): \n");
read(STD_IN, &reply, 1);
switch (reply) {
case 'y':
case 'Y':
myRequest.reply = TRUE;
break;
default:
myRequest.reply = FALSE;
break;
}
/* send request to server */
if (write(sFd, (char *) &myRequest, sizeof(myRequest)) == ERROR) {
perror("write");
close(sFd);
return (ERROR);
}
if (myRequest.reply) /* if expecting reply, read and display it */
{
if (read(sFd, replyBuf, REPLY_MSG_SIZE) < 0) {
perror("read");
close(sFd);
return (ERROR);
}
printf("MESSAGE FROM SERVER:\n%s\n", replyBuf);
}
close(sFd);
return (OK);
}
4.3 编译DKM项目
有两种编译方式,第一种:与VIP项目分开编译,分别在VIP项目和本DKM项目上右键,选择“Build”分别进行编译。
第一次编译会弹出下面的对话框,“Generate Includes”主要用来组织头文件,直接选择“Continue”即可。
第二种:与VIP项目一起编译,将本DKM项目添加到VIP项目当中,然后VIP项目右键选择“Build”进行编译。
1)本DKM项目右键,选择“Project References > Add as Project Reference”,选择VIP项目,点击“OK”。
“test_dkm_sim”项目将会出现在“test_vip_sim”项目下。
2)如果不想将DKM项目添加到VIP项目,可在DKM项目右键选择“Project References > Remove Project Refrence”。
下一篇:【VxWorks】入门教程3:模拟器连接及运行DKM程序