Recently I am studying VxWorks, but I always feel that if I don't do something, look at the online document of the E version, I will not give me the skills. I remembered the previous time, when I added OAM functionality to our company, I need to measure the Utilization of the CPU. Our company's VxWorks prawn took advantage of anti-discovery, it should be successful, but not stable, occasionally Exception. So I am determined to challenge the difficulties.
After viewing information, browse the major embedded development forums, summarize some of the following methods, and each is equivalent. First, let me first introduce the implementation principle of the Spy tool provided by the SpyLib library of VxWorks.
SPY uses an auxiliary timer to generate an interrupt and maintains a counter for each task. Then write down the task being interrupted and add the counter's counter. After a period of time, the counter of each task reflects the case where the task occupies the CPU utilization. Obviously, this is the use of sampling technology. And the accuracy of the obtained CPU utilization depends on the persistence and periodicity of the task.
By looking up the SPYLIB.H file, we found that there is a spycommon function except for the spy () function, with a function pointer parameter. Specifies the function pointer type (int) (* p) (CHAR * FMTSTR, ...) (this is true of verification). So you can write your own function to accept the data that you need to print, SPY calls the function by row the results. We can constantly analyze a string of strings to get the results we need.
INT SpyPTNFunc (const char * fmtptn, ...)
{
Char buf [128];
CPUUSAGEDATAMSG DATA;
VA_LIST VL;
VA_START (VL, FMTPTN);
Vsprintf (buf, fmtptn, vl); // Get a line of strings.
VA_END (VL);
// Analyze the BUF to get the use of the CPU of the task.
Return 0;
}
Another method is to utilize a special task, the priority of the task is lower than the priority of all tasks in the system, the task is dead cycle, the purpose of this task is to consume CPU resources, occupying the CPU idle time, because when the system Other tasks are hanging up, the task can get the right to use the CPU. Assume that within a period of Total, the task runs the runtime, the CPU utilization calculation formula is (Total-IDle)% Total. This method is very simple, but it can only calculate the CPU usage of the entire system, and cannot get a single task CPU usage! At the same time it will make the CPU full load. The source code is as follows
#include "vxworks.h"
#include "semlib.h"
#include "tasklib.h"
#define seconds_to_burn 60
Typedef struct cpuusage {
SEM_ID StartSem;
Int DidNotcomplete;
Unsigned long ticksnocontent;
Int nburnnocontent;
Unsigned long ticksnow;
Int nburnnow;
Double Usage;
} cpuusage;
Static CPUusage * PCPUUSAGE = 0;
Static Double CPuburn ()
{
INT I;
Double Result = 0.0;
For (i = 0; i <5; i ) Result = SQRT ((Double) i);
Return (Result);
Static void cpuusagetask ()
{
While (true) {
INT I;
Unsigned long Tickstart, Tickend;
Semtake (PCPUUSAGE-> StartSem, Wait_Forever);
PCPUUSAGE-> Ticksnow = 0;
PCPUUSAGE-> nburnnow = 0;
Tickstart = tickget ();
For (i = 0; i
Cpuburn ();
PCPUUSAGE-> Ticksnow = tickget () - tickstart;
PCPUUSAGE-> NburnNow;
}
Tickend = tickget ();
PCPUUSAGE-> DIDNOTCOMPLETE = FALSE;
PCPUUSAGE-> Ticksnow = Tickend - Tickstart;
}
}
Double getcpu ()
{
IF (PCPUUSAGE-> DidNotcomplete && PCPUusage-> nburnnow == 0) {
PCPUUSAGE-> USAGE = 0.0;
} else {
Double Temp;
Double ticksnow, nburnnow;
Ticksnow = (double) PCPUUSAGE-> Ticksnow;
Nburnnow = (double) PCPUUSAGE-> NburnNow;
Ticksnow * = (double) PCPUUSAGE-> NburnnoContention / NburnNow;
Temp = ticksnow - (double) PCPUUSAGE-> Ticksnocontent;
Temp = 100.0 * TEMP / TICKSNOW;
IF (Temp <0.0 || Temp> 100.0) TEMP = 0.0; / * handle tick overflow * /
PCPUUSAGE-> USAGE = TEMP;
}
PCPUUSAGE-> DIDNOTCOMPLETE = TRUE;
Semgive (PCPUusage-> StartSem);
Printf ("CPU USAGE:% F / R / N", PCPUUSAGE-> USAGE);
Return (PCPUUSAGE-> USAGE);
}
Void CPUUSAGEINIT (VOID)
{
Unsigned long tickstart, ticknow;
INT nburnnocontent = 0;
Int tickstowait;
Tickstowait = seconds_to_burn * sysclkrateget ();
PCPUUSAGE = Calloc (1, Sizeof (CPUusage));
Tickstart = tickget ();
/ * Wait for a tick * /
While (tickstart == (ticknow = tickget ())) {;}
Tickstart = Ticknow;
While (true) {
IF ((Tickget () - TickStart> = Tickstowait) Break;
Cpuburn ();
NburnnoContention ;
}
PCPUUSAGE-> nburnnocontent = nburnnoContent; PCPUUSAGE-> StartSem = sembcreate (SEM_Q_FIFO, SEM_EMPTY);
PCPUUSAGE-> Ticksnocontent = Tickstowait;
PCPUUSAGE-> DIDNOTCOMPLETE = TRUE;
Taskspawn ("CPUusageTask", 255, VX_FP_TASK, 1000, (Funcptr) CPUUSAGETSK,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
I have achieved the above two ways, and work is normal!
Thank you!