how to solve this Linux Timer

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-12 02:26:52

问题


#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);
    }

I created a server side program for receiving data from the client and sending the response back to the client.There are some api whose definition is not shown above.

I'm writing an application that uses timer to do some data acquisition and processing at a fix sample rate (200Hz). The application acts like a server and run in background. It should be controllable from other processes or other machines from UDP.

To do so, I use the timer_create() API to generate signals periodically and call an handler that do the acquisition and the processing.

The code above is called when a 'start' command is received from UDP. To check for command I have an infinite loop in my main program that call recvfrom() syscall.

PROBLEM : In debug mode - I am recieving the data from the client, timer as been called and it is getting stuck at - static void timerHandler( int sig, siginfo_t *si, void *uc ) { .

REASON for the problem: i am creating multiple timers, say 3 timers from a single process. and all are supposed to land in single Timer handler.

But its giving bus error and "si->si_value.sival_ptr" ==> is of junk value and some how it is getting corrupted. - See more at: http://www.graphics-muse.org/wp/?p=868#sthash.cuvJDp39.dpuf .

could anyone help me in this ??


回答1:


The problem appears to be centered in your CreateSockeet function.

In your read loop you call timerCalculation which in turn creates and sets three timers in makeTimer. It does this every time through the loop. So depending on the arrival of your data you can potentially create many timers before one of them goes off. This doesn't actually account for your problem - at worst you should have timers going off at inappropriate times - but I suspect this is shortened code and problems manifest themselves down the line.

At a minimum you should get the timer creation out of the loop and either reuse them or at least delete them when you are done.

Also, you exit your read loop when a read returns 0. This is a tcp/stream semantic for the other side disconnecting. There is no corresponding meaning in UDP. A UDP packet of 0 length is legal and just means an empty datagram was received. Unless you have some protocol arrangement with your peer that a zero-length packet means end-of-transmission this is not going to get you out of your loop.



来源:https://stackoverflow.com/questions/22063208/how-to-solve-this-linux-timer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!