Notes Accurate delay under Linux, #include <linux/delay.h> call error

Source: Internet
Author: User
Tags function prototype sleep function usleep

When writing application-level programs, sometimes you need to delay, what should I do?

In the kernel code, we often see such a header file using # include <linux/delay.h>, and thought of calling this directly is OK! But at the time of compiling, we found that

The prompt error is as follows:error:no such file or directory.

It is not very strange, obviously the file is there, how can not be called, and the kernel a lot of file calls very happy. What is this for?

Because the kernel program differs from the application, some special kernel header file compilers are not allowed to be called by the application. So compile the application using the kernel header file, error is unavoidable

But what should we do at this time?

Ha ha! #include <unistd.h> header file appears! functionality is consistent with # include <linux/delay.h>, but can be invoked at the application level. It's a good thing! The following is a detailed description:

Application layer:
#include <unistd.h>
 
1, unsigned int sleep (unsigned int seconds); second level
2, int usleep (useconds_t usec); Microsecond level: 1/10^-6

 
#define _posix_c_source 199309
#include <time.h>
3, int nanosleep (const struct TIMESPEC *req, struct timespec *rem);
struct Timespec {
time_t tv_sec; /* seconds * /
long tv_nsec; /* nanoseconds * /
              };
//The value of the nanoseconds field must is in the range 0 to 999999999.
 
Kernel layer:
include <linux/delay.h>
1, void Ndelay (unsigned long nsecs); Nanosecond level: 1/10^-10
2, void Udelay (unsigned long usecs); Microsecond level: 1/10^-6
3, void Mdelay (unsigned long msecs); Millisecond level: 1/10^-3

Udelay uses the software loop to specify the number of subtleties, Mdelay calls the former to reach the delay millisecond level. The Udelay function can only be used to obtain a short time delay because the Loops_per_second value has a precision of only 8 bits, so a considerable amount of error is accumulated when the longer delay is calculated. Although the maximum allowable delay is nearly 1 seconds (because the longer delay is going to overflow), the maximum value of the parameters of the recommended Udelay function is 1000 microseconds (1 milliseconds). function Mdelay can be used when the delay is greater than 11 milliseconds. Mdelay does not exist in Linux 2.0, and the header file Sysdep.h make up for this flaw.
It is important to note that Udelay is a busy wait function (so Mdelay is also) that it is not possible to run other tasks during the delay period, so be very careful, especially mdelay, unless there is no other way to avoid it.

first of all, I would say there is no guarantee that the stroke (process) you perform in user mode (User-mode) can accurately control timing because Linux is a multi-worker environment. Your journey in execution (process) is suspended for a variety of reasons for about 10 milliseconds at any time. To a few seconds (at a very high system load). However, for most applications that use I/O ports, this delay is actually nothing. To shorten the delay time, you have to use the function nice to set your trip (process) in execution to high priority (see the Nice (2) Usage documentation) or use the immediate schedule method (real-time scheduling) (see below).

If you want to get a more precise timing than the stroke (process) performed in the general user mode (User-mode), there are some ways you can get the ' instant ' scheduling support in user mode (User-mode). Linux 2.x version of the core of the software in the form of real-time scheduling support; Please refer to Sched_setscheduler (2) for detailed instructions.
use the documentation. There is a special core support for the real-time scheduling of hardware, please refer to the website for detailed information luz.cs.nmt.edu/~rtlinux/

Rest (sleeping):

sleep () and usleep ()

now, let's start with a simpler sequential function call. The best way to delay a few seconds is to use function sleep (). To delay at least dozens of milliseconds (ten Ms appears to be the shortest delay time), the function usleep () should be available.
These functions give the CPU the right to use the other desired itinerary (processes) ("Take a Break"), so there is no time wasted on the CPU. For details, please refer to: Sleep (3) and Usleep (3) documentation.

If you give up the CPU so that the time is delayed by about 50 milliseconds (depending on the speed of the processor and the machine, and the load of the system), it wastes too much time on the CPU, because the Linux Scheduler (Scheduler) (x86 architecture alone) It usually takes at least 10-30 milliseconds before the system is returned to your itinerary (process). Therefore, a short delay, using the function Usleep (3) results in a delay usually greater than the value you specify in the parameter, about at least ten Ms.

Nanosleep ()

In the Linux 2.0.x series of core distributions, there is a new system call, Nanosleep () (refer to the Nanosleep (2) documentation), which allows you to rest or delay a short time (several microseconds or more).

if the delay time <= 2 ms, if (and only if) your execution of the stroke (process) Set the software's immediate scheduling (that is, using function Tt/sched_setscheduler ()/), call Function Nanosleep () is not using a Busy loop to delay time; Just like the function of Usleep () to give up the use of the CPU to rest.

This busy loop is achieved using the function Udelay () (a core internal function that is often used by a driver) and calculates the length of the loop delay using the Bogomips value (Bogomips can accurately measure the speed of such a busy loop). Details of how it is operated (please refer to/ usr/include/asm/delay.h).

use I/O port to delay time

another way to delay the number of microseconds is to use I/O ports. Is the input or output of any byte data from the port address 0x80 (refer to the front) the waiting time should be almost 1 microseconds this depends on the type and speed of your processor. If you want to delay a few microseconds, you can do it a few more times. outputting data to the port address on any standard machine should not have bad consequences-yes (and some core device drivers are using him too).

the {in|out}[bw]_p () function is the method used to generate time delay (refer to the file asm/io.h).

In fact, an I/O port directive that uses a port address range of 0-0X3FF is almost 1 microseconds, so if you want to do this, for example, directly using a parallel port, just add a few inb () functions to read the data from the port address-enclosing byte.

use a combination language to delay time

If you know the processor type and clock speed of the machine on which the program is executed, you can perform some combination language instructions to get a shorter delay (but remember that your journey in action is paused at any time, so sometimes the delay is longer than it actually is). As shown in the table below, The speed of the internal processor determines the number of clock cycles to be used; For example, a 1 MHz processor (486dx-50 or 486dx2-50), a clock cycle will take up to 50 million seconds (=200 nanoseconds).

instruction i386 number of ticks i486 clock cycles

NOP 3 1

xchg%ax,%ax 3 3

or%ax,%ax 2 1

mov%ax,%ax 2 1

Add%ax,0 2 1

(sorry, I do not know pentiums information, perhaps with i486 close to it.) I can't find an instruction that spends only one clock cycle on I386 's profile. If you can use instructions that cost a clock cycle, you can shorten the time by using a new processor with pipeline technology.

the instructions in the above table for NOP and XCHG should not have undesirable consequences. The instruction may change the contents of the banner register at the end, but it doesn't matter because GCC will handle it. Instructions NOP is a good choice.

To Use these instructions in your program, you need to use ASM ("instruction"). The syntax of the instruction is like the usage of the table above, and if you want to use multiple instructions in a single ASM () narrative, you can separate them with semicolons.
For example,
asm ("NOP; NOP; NOP; NOP ")

Four NOP instructions will be executed and four clock cycles will be delayed in the i486 or Pentium processor (or i386 will delay 12 clock cycles).

GCC translates asm () into a single-line combination language code, so there is no load on the calling function.

There is no time lag in the Intel x86 architecture that is shorter than a clock cycle.

using function RDTSC on Pentiums processors

for the Pentiums processor, you can use the following C language code to get the number of clock cycles since the last reboot to the present:

extern __inline__ unsigned long long int rdtsc ()

{

unsigned long long int x;

__asm__ volatile (". Byte 0x0f, 0x31": "=a" (x));

return x;

}


you can ask for reference to this value in order to delay the number of clock cycles you want.

It may be easiest to use the function time () when you want to be accurate for a second. For more precise time, the function gettimeofday () can be about the exact microsecond (but as previously described, it is affected by CPU scheduling). For Pentiums processors, use the process Code snippet can be accurate to a clock cycle.

If you want your execution (process) to be notified after a period of time (get a signal), you have to use the function Setitimer () or alarm (). For details, refer to the usage documentation for the function .

Application:

#include <syswait.h>

usleep (n)//n μs

Sleep (N)//n Ms

sleep (N)//n sec

drivers:

#include <linux/delay.h>

mdelay (n)//milliseconds its implementation

#ifdef notdef

#define MDELAY (n) (\

{unsigned long msec= (n); while (msec--) Udelay ()})

#else

#define MDELAY (n) (\

(__builtin_constant_p (n) && (n) <=max_udelay_ms)? Udelay ((n) *1000): \

({unsigned long msec= (n); while (msec--) Udelay ()}))

#endif

calling Asm/delay.h's udelay,udelay should be nanosecond-delay.

 

Dos:

sleep (1);//stay 1 seconds

delay (100);//Stay 100 ms

Windows:

Sleep (100);//Stay 100 ms

Linux:

sleep (1);//stay 1 seconds

usleep (1000);//stay 1 ms

Each platform is not the same, it is best to define a set of cross-platform macro control seconds or microseconds?

about the delay function sleep ()

because the sleep () function is required to write a piece of code, in my Mind, sleep (10) seems to be dormant for 10 microseconds, and the result is 10 seconds of hibernation (under Linux). It's strange, because the chief remembers it as if it were microseconds. So I looked it up a bit.

The original Sleep function prototype under Linux is:

unsigned int sleep (unsigned int seconds);

and the Sleep function prototype in MFC is:

void Sleep (DWORD dwmilliseconds);

That is, the sleep () function is in seconds, sleep (1), or dormant for 1 seconds, under Linux (the library used by GCC). The sleep () function under MFC is measured in microseconds, sleep (1000); is dormant for 1 seconds. Oh, yes. If you sleep with a subtle unit under Linux, you can use the thread sleep function: void Usleep (unsigned long usec); Of course, don't forget the # include <system.h> oh when you use it.

also worth mentioning is that Linux has a delay () function, the prototype is extern void delay (unsigned int msec), it can delay msec*4 milliseconds, that is, if you want to delay a second, you can use the delay (250 );


when a device driver needs to handle its hardware response time, the latency involved is often up to a few milliseconds.

kernel functions Ndelay, Udelay, and mdelay are useful for short delays, respectively, delaying the execution of a specified number of nanoseconds, microseconds, or milliseconds. Their prototypes are:

#include <linux/delay.h>
void Ndelay (unsigned long nsecs);
void Udelay (unsigned long usecs);
void Mdelay (unsigned long msecs);
there is another way to get milliseconds (and longer) delays without involving busy waiting. File <linux/delay.h> Declare these functions:

void msleep (unsigned int millisecs);
unsigned long msleep_interruptible (unsigned int millisecs);
void ssleep (unsigned int seconds)
The first 2 functions allow the calling process to enter sleep for a given number of milliseconds. A call to Msleep is non-interruptible; you can ensure that the process sleeps at least a given number of milliseconds. If your driver is in a waiting queue and you want to wake up to interrupt sleep, use msleep_interruptible. The return value from msleep_interruptible is normally 0; If, however, the process is awakened early, the return value is the number of milliseconds remaining in the initial request sleep cycle. The call to Ssleep causes the process to enter a non-interruptible sleep given the number of seconds.

Notes Accurate delay under Linux, #include <linux/delay.h> call error

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.