管道可以看作受驱动器 pipeDrv 管理的虚拟 I/O 设备,使用基本的 I/O 系统接口可以读、写和操作管道,这些函数包括 read 、 write 、 open 、 close 、 ioctl 和 select 等。与 pipe 密切相关的其它 API 还有: ( 1 ) ( ) :初始化 pipeDrv ,函数原型: ( 2 ) pipeDevCreate( ) :创建 pipe ,函数原型: char * name, /* 创建的 pipe 名 */ int nMessages, /* pipe 中的最大消息数 */ ( 3 ) pipeDevDelete :删除 pipe ,函数原型: char * name, /* 要删除的 pipe 名 */ BOOL force /* 如果为真,则强制删除 pipe */ VOIDFUNCPTR routine; /* 函数指针 */ } MSG_REQUEST; /* message structure */ #define TASK_PRI 254 /* tServers task's priority */ #define TASK_STACK_SIZE 5000 /* tServer task's stack size */ #define PIPE_NAME "/pipe/server" /* name of the pipe device */ #define NUM_MSGS 10 /* max number of messages in the pipe */ LOCAL int pipeFd; /* File descriptor for the pipe device */ LOCAL void pipeServer(); /* server task */ /* serverStart :初始化 pipeServer 任务以执行管道中夹带的函数 */ if (pipeDevCreate(PIPE_NAME, NUM_MSGS, sizeof(MSG_REQUEST)) == ERROR) perror("Error in creating pipe"); /* print error if pipe is already * created, but do not return */ if ((pipeFd = open(PIPE_NAME, UPDATE, 0)) == ERROR) perror("Error in opening pipe device"); /* Spawn the server task */ if (taskSpawn("tServer", TASK_PRI, 0, TASK_STACK_SIZE, (FUNCPTR)pipeServer, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) perror("Error in spawning tServer task"); /* serverSend :发送管道消息,将函数指针作为消息的一部分 */ STATUS serverSend(VOIDFUNCPTR routine, /* name of the routine to execute */ int arg /* argument of the routine */ /* Initialize the message structure */ msgRequest.routine = routine; /* Send the message and return the results */ status = write(pipeFd, (char*) &msgRequest, sizeof(MSG_REQUEST)); return ((status == sizeof(MSG_REQUEST)) ? OK : ERROR); /* pipeServer :读取管道消息并执行管道消息中夹带的函数 */ while (read(pipeFd, (char*) &msgRequest, sizeof(MSG_REQUEST)) > 0) (*msgRequest.routine)(msgRequest.arg); 上述程序中, pipeServer 执行于非常低的优先级 (254 级 ) ,当我们在 shell 中输入“ serverSend(VOIDFUNCPTR routine, int arg) ” 时, pipeServer 将读到管道中的消息,并执行“ *routine (arg) ”。 当我们在 tShell 中输入“ serverSend(PRINT,2); ”,在 VxSim 中将输出 2 。 9.套接字
不论网络中的节点使用什么操作系统,套接字的通信都是完全对等的。套接字有两种: ( 1 )流套接字( SOCK_STREAM ,采用 TCP 协议):流套接字提供了双向的、有序的、无重复并且无记录边界的数据流服务; ( 2 )数据报套接字( SOCK_DGRAM ,采用 UDP 协议):数据报套接字也支持双向数据传输,但并不保证是可靠、有序和无重复的。 VxWorks 中与 Socket 相关的函数有: ( 1 ) socket() :创建套接字 ,原型为: int domain, /* address family (for example, AF_INET) */ int type, /* SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW */ int protocol /* socket protocol (usually 0) */ ( 2 ) bind() :给套接字绑定名称 ,原型为: int s, /* socket descriptor */ struct sockaddr * name, /* name to be bound */ int namelen /* length of name */ ( 3 ) listen() :服务端监听 TCP 连接请求,原型为: int s, /* socket descriptor */ int backlog /* number of connections to queue */ ( 4 ) accept() :服务端接受 TCP 连接请求,原型为: int s, /* socket descriptor */ struct sockaddr * addr, /* peer address */ int * addrlen /* peer address length */ ( 5 ) connect() :客户端请求连接套接字,原型为: int s, /* socket descriptor */ struct sockaddr * name, /* addr of socket to connect */ int namelen /* length of name, in bytes */ ( 6 ) shutdown() :关闭套接字间连接,原型为: int s, /* socket to shut down */ int how /* 0:receives disallowed;1:sends disallowed; 2:sends and receives disallowed */ ( 7 ) sendto() 、 send() 、 sendmsg() :发送数据 int s, /* socket to send data to */ caddr_t buf, /* pointer to data buffer */ int bufLen, /* length of buffer */ int flags, /* flags to underlying protocols */ struct sockaddr * to, /* recipient's address */ int tolen /* length of to sockaddr */ 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 sd, /* socket to send to */ struct msghdr * mp, /* scatter-gather message header */ int flags /* flags to underlying protocols */ ( 8 ) recvfrom () 、 recv () 、 recvmsg () :接收数据 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 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 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 的例子: /* function prototypes */ #define LONG_TIME 1000000 void sigGenerator(void) /* task to generate the SIGINT signal */ if ((taskId = taskSpawn("signal", 100, 0x100, 20000, (FUNCPTR)sigCatcher, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) printf("taskSpawn sigCatcher failed\n"); 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("+++++++++++++++++++++++++++++++SIGINT sinal generated\n"); kill(taskId, SIGINT); /* generate signal */ /* lower sigGenerator priority to allow sigCatcher to run */ taskPrioritySet(ownId, LOWPRIORITY); printf("\n***************sigGenerator Exited***************\n"); void sigCatcher(void) /* task to handle the SIGINT signal */ struct sigaction newAction; 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("Could not install signal handler\n"); for (i = 0; i < ITER1; i++) for (j = 0; j < LONG_TIME; j++) printf("Normal processing in sigCatcher\n"); printf("\n+++++++++++++++sigCatcher Exited+++++++++++++++\n"); void catchSIGINT(int signal) /* signal handler code */ printf("-------------------------------SIGINT signal caught\n"); /* increase sigGenerator priority to allow sigGenerator to run */ taskPrioritySet(ownId, HIGHPRIORITY); 分析以上程序, kill() 函数产生信号,其原型为: int tid, /* task to send signal to */ int signo /* signal to send to task */ sigaction() 函数将信号与信号处理函数进行绑定,一个信号处理函数类似于程序中的 catchSIGINT 函数,一般结构为: void sigHandlerFunction(int signalNumber) ... /* signal handler code */ 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中断处理》中发现中断与信号的相似性。
本文转自 21cnbao 51CTO博客,原文链接:http://blog.51cto.com/21cnbao/120323,如需转载请自行联系原作者