Hallo,
gerade bin ich dabei, ein Programm in C zu schreiben, welches
Temperaturdaten vom Arduino empfängt und in einer Datenbank ablegt.
Das Programm macht inzwischen, was ich möchte.
Das Problem ist, dass ich eine Schleife geschrieben habe, die eine
bestimmte Zeit misst und nicht optimal ist.
Dummerweise hat diese Art der Programmierung den Nachteil, dass die CPU
immer in Beschäftigung ist.
Wie kann ich unter Linux einen Timer programmieren, der am Besten
interruptgesteuert ist, so wie ich es auch beim AVR machen würde?
Hier ist mein kleines Programm:
Bitte erschlagt mich nicht, falls ich grundlegende Dinge nicht beachtet
haben sollte. Es ist mein erstes Programm unter Linux. Für konstruktive
Hinweise bin ich natürlich dankbar.
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<time.h>
4
#include<sys/types.h>
5
#include<fcntl.h>
6
#include<mysql.h>
7
8
// globale Variablen deklarieren
9
intport;
10
charpuffer[100];
11
charpuffer2[150];
12
MYSQL_RES*res;
13
MYSQL_ROWrow;
14
intbytes;
15
charbuffer[1];
16
inti=0;
17
intx;
18
inty;
19
20
// Instanz von mysql
21
MYSQL*mysql;
22
23
/* Bricht bei Fehler (mysql_error != 0) das Programm ab. */
Hier noch mehr: (SEE ALSO beachten)
USLEEP(3)
Linux Programmer's Manual
USLEEP(3)
NAME
usleep - suspend execution for microsecond intervals
SYNOPSIS
#include <unistd.h>
int usleep(useconds_t usec);
Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):
usleep(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
DESCRIPTION
The usleep() function suspends execution of the calling process
for (at least) usec microseconds. The sleep may be lengthened slightly
by any system activity or by the time spent pro‐
cessing the call or by the granularity of system timers.
RETURN VALUE
0 on success, -1 on error.
ERRORS
EINTR Interrupted by a signal; see signal(7).
EINVAL usec is not smaller than 1000000. (On systems where that
is considered an error.)
CONFORMING TO
4.3BSD, POSIX.1-2001. POSIX.1-2001 declares this function
obsolete; use nanosleep(2) instead. POSIX.1-2008 removes the
specification of usleep().
On the original BSD implementation, and in glibc before version
2.2.2, the return type of this function is void. The POSIX version
returns int, and this is also the prototype used
since glibc 2.2.2.
Only the EINVAL error return is documented by SUSv2 and
POSIX.1-2001.
NOTES
The type useconds_t is an unsigned integer type capable of
holding integers in the range [0,1000000]. Programs will be more
portable if they never mention this type explicitly. Use
#include <unistd.h>
...
unsigned int usecs;
...
usleep(usecs);
The interaction of this function with the SIGALRM signal,
and with other timer functions such as alarm(2), sleep(3), nanosleep(2),
setitimer(2), timer_create(2), timer_delete(2),
timer_getoverrun(2), timer_gettime(2), timer_settime(2),
ualarm(3) is unspecified.
SEE ALSO
alarm(2), getitimer(2), nanosleep(2), select(2), setitimer(2),
sleep(3), ualarm(3), time(7)
COLOPHON
This page is part of release 3.23 of the Linux man-pages project.
A description of the project, and information about reporting bugs, can
be found at http://www.kernel.org/doc/man-
pages/.
2007-07-26
USLEEP(3)
Guido Scheidat schrieb:> Wie kann ich unter Linux einen Timer programmieren, der am Besten> interruptgesteuert ist, so wie ich es auch beim AVR machen würde?
man setitimer
Das ist exakt das Pendat zun einem Interrupt-Timer. Statt eines
Interrupts bekommst du ein Signal, aber die Handhabung ist sehr ähnlich.
Du hast dann aber immer noch eine Hauptschleife, die die CPU-Last auf
100% hält, wenn du da nicht was dagegen tust. Das kannst du z.B. machen,
indem du in der Haupstschleife mit select() ohne Dateideskriptoren und
einer sehr langen Wartezeit wartetst. Das wird durch das Signal
automatisch unterbrochen. Der Rest ist dann wie am µC: Im Signal-Handler
ein Flag setzen (Als Typ empfielt sich sig_atomic_t) und in der
Hauptschleife testen.
Vielen, vielen Dank!
Ich habe jetzt USLEEP eingesetzt. Die Genauigkeit reicht für diesen
Zweck aus. Es funktioniert ganz Klasse, die Idle-Time der CPU liegt bei
99-100%. So hatte ich es mir vorgestellt.
Danke!
Wenn man eh select() nimmt, kann man dem doch auch gleich die Wartezeit
geben?
Rolf Magnus schrieb:> indem du in der Haupstschleife mit select() ohne Dateideskriptoren und> einer sehr langen Wartezeit wartetst
Klaus Wachtler schrieb:> Wenn man eh select() nimmt, kann man dem doch auch gleich die Wartezeit> geben?
Kommt halt drauf an, was das Ziel ist. Wenn man ein Timing will, das
nicht davonläuft, kommt man um einen periodischen Timer nicht rum. Denn
zu der Wartezeit des select() kommt ja immer noch die (womöglich
variable) Laufzeit für den Rest der Schleife dazu.
Wenn das egal ist, kann man sich den Timer natürlich sparen.
Ich hatte mich hier auch speziell auf diese Frage bezogen:
Guido Scheidat schrieb:> Wie kann ich unter Linux einen Timer programmieren, der am Besten> interruptgesteuert ist, so wie ich es auch beim AVR machen würde?
Die von mir genannte Variante ist der Art, wie man beim AVR mit
Timer-Interrupts arbeitet, am ähnlichsten, ohne dabei aber 100% CPU-Last
zu produzieren.