c - 如何解决这个Linux定时器问题

标签 c linux sockets timer qnx

#include <features.h>
#include <time.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define million 1000000L

timer_t firstTimerID, secondTimerID, thirdTimerID;
double Task2ms_Raster, Task10ms_Raster, Task100ms_Raster;

struct sockaddr_in addr, client;
int acceptSocket;
char buf[256];
long rc, sentbytes;
int port = 18037;


void TASK1(Task2ms_Raster)
{

     struct timespec start, stop;
     double startTime, stopTime;

        if( (startTime = clock_gettime( CLOCK_REALTIME, &start)) == -1 ) {
          perror("clock gettime");

        }

        startTime =start.tv_sec + 0.0000001 * start.tv_nsec;
              printf("start time is %lf", startTime);


       // return EXIT_SUCCESS;

    /* Trigger DAQ for the 2ms XCP raster. */
    if( XCPEVENT_DAQ_OVERLOAD & Xcp_DoDaqForEvent_2msRstr( ))
    {
        ++numDaqOverload2ms;
    }

    /* Update those variables which are modified every 2ms. */
 counter32 += slope32;

    /* Trigger STIM for the 2ms XCP raster. */
  if( enableBypass2ms )
   {
        if( XCPEVENT_MISSING_DTO & Xcp_DoStimForEvent_2msRstr( ) )
        {
     ++numMissingDto2ms;
        }
        }
  if( (stopTime = clock_gettime( CLOCK_REALTIME, &stop)) == -1 ) {
          perror( "clock gettime" );

        }
  stopTime =  stop.tv_sec + 0.0000001 * stop.tv_nsec;
   printf("stop time is %lf", stopTime);

            duration2ms = (stopTime- startTime);
            printf( "time difference for task1 is= %ld\n", duration2ms );

}

void TASK2(Task10ms_Raster)
{
     struct timespec start, stop;

     double startTime, stopTime;
            if( (startTime = clock_gettime( CLOCK_REALTIME, &start)) == -1 ) {
              perror( "clock gettime" );

            }

            startTime =start.tv_sec + 0.0000001 * start.tv_nsec;
             printf("start time is %lf", startTime);


    /* Trigger DAQ for the 10ms XCP raster. */
    if( XCPEVENT_DAQ_OVERLOAD & Xcp_DoDaqForEvent_10msRstr( ))
    {
        ++numDaqOverload10ms;
    }

    /* Update those variables which are modified every 10ms. */
    counter16 += slope16;

    /* Trigger STIM for the 10ms XCP raster. */
    if( enableBypass10ms )
    {
        if( XCPEVENT_MISSING_DTO & Xcp_DoStimForEvent_10msRstr( ) )
        {
            ++numMissingDto10ms;
        }
    }

    if( (stopTime = clock_gettime( CLOCK_REALTIME, &stop)) == -1 ) {
              perror( "clock gettime" );

            }

    stopTime =  stop.tv_sec + 0.0000001 * stop.tv_nsec;
     printf("stop time is %lf", stopTime);


    duration10ms = ( stop.tv_sec - start.tv_sec )
                             + (double)( stop.tv_nsec - start.tv_nsec )
                               / (double)million;
           printf( "time difference for task2 is= %ld\n", duration10ms );
}


void TASK3(Task100ms_Raster)
{
     struct timespec start, stop;
     double startTime, stopTime;

            if( (startTime = clock_gettime( CLOCK_REALTIME, &start)) == -1 )
            {
              perror("clock gettime");

            }
           startTime =start.tv_sec + 0.0000001 * start.tv_nsec;
          printf("start time is %lf", startTime);

    /* Trigger DAQ for the 100ms XCP raster. */
    if( XCPEVENT_DAQ_OVERLOAD & Xcp_DoDaqForEvent_100msRstr( ))
    {
        ++numDaqOverload100ms;
    }

    /* Update those variables which are modified every 100ms. */
    counter8 += slope8;


    /* Trigger STIM for the 100ms XCP raster. */
    if( enableBypass100ms )
    {
        if( XCPEVENT_MISSING_DTO & Xcp_DoStimForEvent_100msRstr( ) )
        {
            ++numMissingDto100ms;
        }
    }

    if((stopTime = clock_gettime( CLOCK_REALTIME, &stop)) == -1 ) {
              perror( "clock gettime" );

            }

    stopTime =  stop.tv_sec + 0.0000001 * stop.tv_nsec;
     printf("stop time is %lf", stopTime);

    Xcp_CmdProcessor();

    duration100ms = ( stop.tv_sec - start.tv_sec )
                     + (double)( stop.tv_nsec - start.tv_nsec )
                       / (double)million;
          printf( "time difference for task3 is= %ld\n", duration100ms );
}

/*The handler checks that the value stored in sival_ptr matches a given timerID
variable.  The sival_ptr is the same as the one we set in makeTimer(),
though here it lives in a different structure.
Obviously, it got copied from there to here on the way to this signal handler.
The point is that the timerID is what is used to determine which timer just went off
and determine what to do next */


static void timerHandler( int sig, siginfo_t *si, void *uc )
{
    timer_t *tidp;

    tidp = si->si_value.sival_ptr;

    if ( *tidp == firstTimerID )

        TASK1(Task2ms_Raster);
   else if ( *tidp == secondTimerID )
       TASK2(Task10ms_Raster);
    else if ( *tidp == thirdTimerID )
        TASK3(Task100ms_Raster);
}

/*
The function takes a pointer to a timer_t variable that will be filled with the
timer ID created by timer_create().  This pointer is also saved in the sival_ptr
variable right before calling timer_create().  In this function notice that we
always use the SIGRTMIN signal, so expiration of any timer causes this signal to
be raised.  The signal handler I've written for that signal is timerHandler.
*/

 static int makeTimer( char *name, timer_t *timerID, int expireMS, int intervalMS )
{
     //sigset_t mask;
    struct sigevent         te;
    struct itimerspec       its;
    struct sigaction        sa;
    int                     sigNo = SIGRTMIN;

    /* Set up signal handler. */
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = timerHandler;
    sigemptyset(&sa.sa_mask);
    if (sigaction(sigNo, &sa, NULL) == -1)
    {
        perror("sigaction");
    }

    /* Set and enable alarm */
    te.sigev_notify = SIGEV_SIGNAL;
    te.sigev_signo = sigNo;
    te.sigev_value.sival_ptr = timerID;
    timer_create(CLOCK_REALTIME, &te, timerID);

    its.it_interval.tv_sec = 0;
    its.it_interval.tv_nsec = intervalMS * 1000000;
    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = expireMS * 1000000;
    timer_settime(*timerID, 0, &its, NULL);


    return 1;
}

void timerCalculation()
 {

     makeTimer("First Timer", &firstTimerID, 2, 2);   //2ms

   makeTimer("Second Timer", &secondTimerID, 10, 10);    //10ms
   makeTimer("Third Timer", &thirdTimerID, 100, 100);  //100ms


 }


int CreateSocket()
{


    socklen_t len = sizeof(client);
       // Socket creation for UDP

       acceptSocket=socket(AF_INET,SOCK_DGRAM,0);

       if(acceptSocket==-1)

       {

         printf("Failure: socket creation is failed, failure code\n");

         return 1;

       }

       else

       {

         printf("Socket started!\n");

       }

       //non blocking mode
      /* rc = ioctl(acceptSocket, FIONBIO, (char *)&flag);
          if (rc < 0)
          {
                     printf("\n ioctl() failed \n");
             return 0;
          }*/

          //Bind the socket
     memset(&addr, 0, sizeof(addr));

     addr.sin_family=AF_INET;

     addr.sin_port=htons(port);

     addr.sin_addr.s_addr=htonl(INADDR_ANY);

     rc=bind(acceptSocket,(struct sockaddr*)&addr,sizeof(addr));

     if(rc== -1)

     {

       printf("Failure: listen, failure code:\n");

       return 1;

     }

     else

     {

       printf("Socket an port %d \n",port);

     }


     if(acceptSocket == -1)
     {
         printf("Fehler: accept, fehler code:\n");

          return 1;
     }
     else
     {

     while(rc!=-1)
         {


         rc=recvfrom(acceptSocket,buf, 256, 0, (struct sockaddr*) &client, &len);
         if(rc==0)
         {
           printf("Server has no connection..\n");
           break;
         }
         if(rc==-1)
         {
             printf("something went wrong with data %s", strerror(errno));
           break;
         }


         XcpIp_RxCallback( (uint16) rc, (uint8*) buf, (uint16) port );
         timerCalculation();

          }


     }

       close(acceptSocket);

       return 0;

     }


int main()
{

     Xcp_Initialize();
     CreateSocket();

     return 0;
}

void XcpApp_IpTransmit( uint16 XcpPort,  Xcp_StatePtr8 pBytes, uint16 numBytes )
{


        if ((long)XcpPort==port){
                sentbytes = sendto(acceptSocket,(char*)pBytes,(long)numBytes,0, (struct sockaddr*)&client, sizeof(client));
        }
        XcpIp_TxCallback(port,(uint16)sentbytes);
    }

我创建了一个服务器端程序,用于从客户端接收数据并将响应发送回客户端。有一些 api 的定义未在上面显示。

我正在编写一个应用程序,它使用计时器以固定采样率(200Hz)进行一些数据采集和处理。该应用程序就像服务器一样在后台运行。它应该可以通过 UDP 从其他进程或其他机器进行控制。

为此,我使用 timer_create() API 定期生成信号并调用执行采集和处理的处理程序。

当从 UDP 接收到“start”命令时,将调用上面的代码。为了检查命令,我的主程序中有一个无限循环,调用 recvfrom() 系统调用。

问题:在 Debug模式下 - 我正在从客户端接收数据,计时器已被调用,并且它卡在 - static voidtimerHandler( int sig, siginfo_t *si, void *uc ) { .

问题原因:我正在创建多个计时器,例如单个进程中的 3 个计时器。所有这些都应该落在单个计时器处理程序中。

但是它给出的总线错误和“si->si_value.sival_ptr”==>具有垃圾值(value)以及它是如何被损坏的。 - 查看更多信息:http://www.graphics-muse.org/wp/?p=868#sthash.cuvJDp39.dpuf .

有人可以帮我吗?

最佳答案

问题似乎集中在您的 CreateSocket 函数中。

在读取循环中,您调用timerCalculation,它又在makeTimer中创建并设置三个计时器。每次循环都会执行此操作。因此,根据数据的到达,您可能会在其中一个计时器关闭之前创建许多计时器。这实际上并不能解决你的问题 - 最坏的情况是你应该让计时器在不适当的时间关闭 - 但我怀疑这是缩短的代码,问题会在接下来的时间里显现出来。

至少您应该让计时器创建脱离循环,并重用它们或至少在完成后删除它们。

此外,当读取返回 0 时,您将退出读取循环。这是另一端断开连接的 TCP/流语义。 UDP中没有对应的含义。长度为 0 的 UDP 数据包是合法的,仅意味着收到了空数据报。除非您与对等方有某种协议(protocol)安排,即零长度数据包意味着传输结束,否则这不会让您脱离循环。

关于c - 如何解决这个Linux定时器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22063208/

相关文章:

java - 查看套接字输入流

c - 如何将结构体中的指针直接分配给新结构体?

信号量可以用于访问同一库的两个不同应用程序

c - 套接字连接返回错误号 ETIMEOUT

android - 从另一个共享库中检查丢失的共享库 (.so)

需要处理查询时 C 秒滴答作响?

Java ObjectInputStream(Socket套接字)重新启动整个应用程序?

c - 错误 `./px' : free(): invalid next size (normal)Aborted (core dumped)

C getchar() 不等待输入/条件循环不 int

c - Keil C 编译器中的 strcpy 和 strcat