Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1264701
  • 博文数量: 404
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 5382
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-03 16:29
文章存档

2010年(40)

2009年(140)

2008年(224)

我的朋友

分类: LINUX

2009-03-04 12:44:18

管道可以看作受驱动器pipeDrv管理的虚拟I/O设备,使用基本的I/O系统接口可以读、写和操作管道,这些函数包括readwriteopencloseioctlselect等。与pipe密切相关的其它API还有:

1( ):初始化pipeDrv,函数原型:

STATUS pipeDrv (void);

2pipeDevCreate( ):创建pipe,函数原型:

STATUS pipeDevCreate

    (

    char * name,              /* 创建的pipe */

    int    nMessages,         /* pipe中的最大消息数 */

    int    nBytes             /* 每个消息的大小 */

    );

3pipeDevDelete:删除pipe,函数原型:

STATUS pipeDevDelete

    (

    char * name,              /* 要删除的pipe */

    BOOL   force              /* 如果为真,则强制删除pipe */

    );

下面我们看看pipe使用的demo

3:管道

/* includes */

#include "vxWorks.h"

#include "taskLib.h"

#include "stdio.h"

#include "ioLib.h"

#include "pipeDrv.h"

 

/*globals */

typedef struct

{

  VOIDFUNCPTR routine;   /* 函数指针 */

  int arg;

} 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任务以执行管道中夹带的函数 */

STATUS serverStart()

{

  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 */

  }

 

  /* Open the pipe */

  if ((pipeFd = open(PIPE_NAME, UPDATE, 0)) == ERROR)

  {

    perror("Error in opening pipe device");

    return (ERROR);

  }

 

  /* 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");

    close(pipeFd);

    return (ERROR);

  }

 

  return (OK);

}

 

/* serverSend :发送管道消息,将函数指针作为消息的一部分 */

STATUS serverSend(VOIDFUNCPTR routine, /* name of the routine to execute */ int arg /* argument of the routine */

)

{

  MSG_REQUEST msgRequest;

  int status;

 

  /* Initialize the message structure */

  msgRequest.routine = routine;

  msgRequest.arg = arg;

 

  /* Send the message and return the results */

  status = write(pipeFd, (char*) &msgRequest, sizeof(MSG_REQUEST));

 

  return ((status == sizeof(MSG_REQUEST)) ? OK : ERROR);

}

 

/* pipeServer:读取管道消息并执行管道消息中夹带的函数 */

LOCAL void pipeServer()

{

  MSG_REQUEST msgRequest;

 

  while (read(pipeFd, (char*) &msgRequest, sizeof(MSG_REQUEST)) > 0)

    (*msgRequest.routine)(msgRequest.arg);

}

   上述程序中,pipeServer执行于非常低的优先级(254),当我们在shell中输入“serverSend(VOIDFUNCPTR routine, int arg) 时,pipeServer将读到管道中的消息,并执行“*routine (arg)”。

       为对此进行验证,我们在程序中再添加一个函数:

void PRINT(int arg)

{

       printf("%d",arg);

}

当我们在tShell中输入“serverSend(PRINT,2);”,在VxSim中将输出2

9.套接字

不论网络中的节点使用什么操作系统,套接字的通信都是完全对等的。套接字有两种:

1)流套接字(SOCK_STREAM,采用TCP协议):流套接字提供了双向的、有序的、无重复并且无记录边界的数据流服务;

2)数据报套接字(SOCK_DGRAM,采用UDP协议):数据报套接字也支持双向数据传输,但并不保证是可靠、有序和无重复的。

另外还有一种RAW套接字,但不常见。

VxWorks中与Socket相关的函数有:

1socket():创建套接字   ,原型为:

int socket

    (

    int domain,    /* address family (for example, AF_INET) */

    int type,      /* SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW */

    int protocol   /* socket protocol (usually 0) */

    );

2bind():给套接字绑定名称 ,原型为:

STATUS bind

    (

    int               s,      /* socket descriptor */

    struct sockaddr * name,   /* name to be bound */

    int            namelen /* length of name */

    );

3listen():服务端监听TCP连接请求,原型为:

STATUS listen

    (

    int s,                    /* socket descriptor */

    int backlog               /* number of connections to queue */

    );

4accept():服务端接受TCP连接请求,原型为:

int accept

    (

    int            s,      /* socket descriptor */

    struct sockaddr * addr,   /* peer address */

    int *           addrlen /* peer address length */

    );

5connect():客户端请求连接套接字,原型为:

STATUS connect

    (

    int               s,      /* socket descriptor */

    struct sockaddr * name,   /* addr of socket to connect */

    int            namelen /* length of name, in bytes */

    );

6shutdown():关闭套接字间连接,原型为:

STATUS shutdown

    (

    int s,                /* socket to shut down */

    int how              /* 0:receives disallowed;1:sends disallowed;

2:sends and receives disallowed */

    );

7sendto()send()sendmsg():发送数据

int sendto

    (

    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 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 */

    );

8recvfrom ()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 "vxWorks.h"

#include "sigLib.h"

#include "taskLib.h"

#include "stdio.h"

 

/* 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("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);

    }

    else

     /* sigCatcher is dead */

      break;

  }

  printf("\n***************sigGenerator Exited***************\n");

}

 

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("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 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中断处理》中发现中断与信号的相似性。

Trackback:

阅读(699) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~