基于嵌入式操作系统VxWorks的多任务并发程序设计(全) 联系客服

发布时间 : 星期一 文章基于嵌入式操作系统VxWorks的多任务并发程序设计(全)更新完毕开始阅读64db28244b35eefdc8d3330e

int send (

int s, /* socket to send to */

const char * buf, /* pointer to buffer to transmit */ int bufLen, /* length of buffer */

int flags /* flags to underlying protocols */ );

int sendmsg (

int sd, /* socket to send to */

struct msghdr * mp, /* scatter-gather message header */ int flags /* flags to underlying protocols */ );

(8)recvfrom ()、recv ()、recvmsg ():接收数据

int recvfrom (

int s, /* socket to receive from */ char * buf, /* pointer to data buffer */ int bufLen, /* length of buffer */

int flags, /* flags to underlying protocols */ struct sockaddr * from, /* where to copy sender's addr */ int * pFromLen /* value/result length of from */ ); int recv (

int s, /* socket to receive data from */ char * buf, /* buffer to write data to */ int bufLen, /* length of buffer */

int flags /* flags to underlying protocols */ ); int recvmsg (

int sd, /* socket to receive from */

struct msghdr * mp, /* scatter-gather message header */ int flags /* flags to underlying protocols */ );

限于篇幅的关系,我们在此不在列举socket通信的例子。但在最后一次连载的综合实例中,将包括完整的socket通信过程源代码。 10.信号与异常处理

信号是VxWorks中用于异常处理的方式,信号的驱动和执行机制有点类似于硬件中断(可以认为是一种软件上的通告,即software notification)。信号的生存期为从“产生”到“传递”,一个“产生”而未“传递”的信号处于pending状态。信号适宜进行异常处理,任务间的通信不要使用信号。 下面是从Embry-Riddle Real-Time Laboratory试验课程中获得的一个signal的例子: 例4:信号与异常处理

/* includes */ #include \#include \#include \#include \

/* function prototypes */ void catchSIGINT(int); void sigCatcher(void);

/* globals */

#define NO_OPTIONS 0 #define ITER1 100

#define LONG_TIME 1000000 #define HIGHPRIORITY 100 #define LOWPRIORITY 101 int ownId;

void sigGenerator(void) /* task to generate the SIGINT signal */ {

int i, j, taskId; STATUS taskAlive;

if ((taskId = taskSpawn(\ 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)

printf(\

ownId = taskIdSelf(); /* get sigGenerator's task id */

taskDelay(30); /* allow time to get sigCatcher to run */

for (i = 0; i < ITER1; i++) {

if ((taskAlive = taskIdVerify(taskId)) == OK) {

printf(\ kill(taskId, SIGINT); /* generate signal */

/* lower sigGenerator priority to allow sigCatcher to run */ taskPrioritySet(ownId, LOWPRIORITY);

} else

/* sigCatcher is dead */ break; }

printf(\}

void sigCatcher(void) /* task to handle the SIGINT signal */ {

struct sigaction newAction; int i, j;

newAction.sa_handler = catchSIGINT; /* set the new handler */ sigemptyset(&newAction.sa_mask); /* no other signals blocked */ newAction.sa_flags = NO_OPTIONS; /* no special options */

if (sigaction(SIGINT, &newAction, NULL) == - 1) printf(\

for (i = 0; i < ITER1; i++) {

for (j = 0; j < LONG_TIME; j++) ;

printf(\ }

printf(\}

void catchSIGINT(int signal) /* signal handler code */ {

printf(\ /* increase sigGenerator priority to allow sigGenerator to run */ taskPrioritySet(ownId, HIGHPRIORITY); }

分析以上程序,kill()函数产生信号,其原型为:

int kill (

int tid, /* task to send signal to */ int signo /* signal to send to task */ );

sigaction()函数将信号与信号处理函数进行绑定,一个信号处理函数类似于程序中的catchSIGINT函数,一般结构为:

void sigHandlerFunction(int signalNumber) {

... /* signal handler code */ }

sigaction()函数的原型为:

int sigaction (

int signo, /* signal of handler of interest */ const struct sigaction * pAct, /* location of new handler */ struct sigaction * pOact /* location to store old handler */ );

signo为信号序号,而输入参数pAct中存放的是信号处理函数的信息,pOact是一个输出参数,可以获得老的信号处理函数信息。 运行上述程序,输出结果为:

Normal processing in sigCatcher

… //大量的Normal processing in sigCatcher Normal processing in sigCatcher

+++++++++++++++sigCatcher Exited+++++++++++++++

我们将从下一次连载――《VxWorks中断处理》中发现中断与信号的相似性。

中断处理是整个运行系统中优先级最高的代码,可以抢占任何任务级代码运行。中断机制是多任务环境运行的基础,是系统实时性的保证。几乎所有的实时多任务操作系统都需要一个周期性系统时钟中断的支持,用以完成时间片调度和延时处理。VxWorks 提供tickAnnounce(),由系统时钟中断调用,周期性地触发内核。

为了快速响应中断,VxWorks的中断服务程序(ISR)运行在特定的空间。不同于一般的任务,中断服务程序没有任务上下文,不包含任务控制块,所有的中断服务程序使用同一中断堆栈,它在系统启动时就已根据具体的配置参数进行了分配和初始化。在ISR中能使用的函数类型与在一般任务中能使用的有些不同,主要体现在:

(1)ISR中不能调用可能导致blocking的函数,例如:

(a)不能以semTake获取信号量,因如果该信号量不可利用,内核会试图让调用者切换到blocking态; (b)malloc和free可能导致blocking,因此也不能使用; (c)应避免进行VxWorks I/O系统操作(除管道外); (d)应避免在ISR中进行浮点操作。

(2)在ISR中应以logMsg打印消息,避免使用printf;

(3)理想的ISR仅仅调用semGive等函数,其它的事情交给semTake这个信号量的任务去做。一个ISR通常作为通信或同步的发起者,它采用发送信号量或向消息队列发送一个消息的方式触发相关任务至就绪态。ISR几乎不能作为信息的接收者,它不可以等待接收消息或信号量。 11.中断服务程序

VxWorks中与中断相关的重要API函数或宏有:

(1)intConnect():中断连接,将中断向量与ISR入口函数绑定

SYNOPSIS STATUS intConnect (

VOIDFUNCPTR * vector,/* interrupt vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */