Avatar billede skrewz Nybegynder
06. maj 2004 - 01:23 Der er 5 kommentarer og
2 løsninger

Mikrosekundstiming i linux

Hej. Jeg har stillet spørgsmålet før, men da jeg tilgik spørgsmålet sidst, fik jeg et spørgsmål om noget andet - eksperten har genbrugt mit spørgsmålsnummer.

Men, under alle omstændigheder, så har jeg brug for at kunne time i mikrosekunds præcision i linux. Jeg er blevet foreslået at bruge select(), og implementeringen foregik nogenlunde. Imidlertid er det mere besværligt end det, ser det ud til, og jeg fik i hvert fald ikke mikrosekunds præcision af det. Ærligt taget ser det ud til at jeg kan styre ned til 1/100 sekunder med denne implementering.

Sig til, hvis der er behov for mere information.
SKREWZ.
Avatar billede noden Nybegynder
06. maj 2004 - 01:56 #1
Du kan ikke garantere at lige din unixclon giver så præcist et tidspunkt.
Ej heller selv om du bruger struct timeval som skulle kunne modtage mikrosekunder kan du være sikker på din kerne ikke har afrundet og faktisk givet et mindre præcist svar.
..Underordnet om du benytter select() eller andet!

Hvad skal det bruges til?
Select er jo som regel brugt til descriptors!
Avatar billede arne_v Ekspert
06. maj 2004 - 08:04 #2
Spørgsmål stillet lige før nedbruddet gik tabt og spørgsmåls numrene bliver
genbrugt (der røg også en måned længere tilbage i tiden men de numre bliver
ikke genbrugt).
Avatar billede s.nielsen Nybegynder
06. maj 2004 - 12:30 #3
select er den mest portable måde at implementere en mikrosekund timer på. Det er også ret simpelt:

int usecsleep(int usecs)
{
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = usecs;

    return select(0, NULL, NULL, NULL, &tv);
}

Hvis den ikke er præcis nok, er det kernens skyld. Men det er nok urealistisk at forvente at en almindelig linux maskine kan levere den slags præcision. Hvis det er meget vigtigt kan du eventuelt overveje at skifte til Timesys Linux, der har højere opløsning på timere end normale linux systemer.
Avatar billede skrewz Nybegynder
08. maj 2004 - 19:07 #4
Okay, jeg har stillet for store krav. Jeg troede at det var muligt at skabe præcision nok, på denne måde, men, nej. Det er imidlertid interessant, for jeg fik stykket noget kode sammen, som lavede en "busy wait" ved at fylde en struct timeval med gettimeofday(), for så at tjekke om det passede med éns ønsker. Det var såmænd også meget godt, men ubrugeligt i den forstand at OS'et tog tiden fra min "applikation", og antallet af mikrosekunder nåede at passere det kritiske tal. Heller ikke, da jeg rundede ned, og bare tjekkede om antallet af hele hundrede mikrosekunder passede, virkede det.

Imidlertid har jeg rodet lidt, og hvis man tænker sig om, så bør et hvilketsomhelst OS kunne arbejde i den slags præcision. Hvad gør printerdrivere ellers, hvis de skal skrive til parallelporten?


Jeg poster, hvis jeg finder en acceptabel løsning, og ellers kan I smide svar, såfremt I vil have goodwill-point. (Derfor at dette er et svar).
Iøvrigt skal det bruges til at skrive output til en ekstern enhed, som er sluttet til en parallelport. Det er smartere at lave parallelport-interfaces selv, i forhold til at købe færdigvarer.
Avatar billede s.nielsen Nybegynder
08. maj 2004 - 22:04 #5
Jeg ved ikke hvordan printerdrivere fungerer, men generel kommunikation over parallelporten kræver jo ikke den slags timing. Mig bekendt kan man ikke uden videre opnå den slags præcision...
Avatar billede segmose Nybegynder
10. maj 2004 - 09:14 #6
Selve tidstagningen kan i sig selv betyde at din tid forekommer unøjagtig, prøv følgende:

Tråd 1:

i = 0;
gem start tid.
while (i++ < 100000) // 100 sekunder;
  usecsleep(1000); // 1ms
gem slut tid.

tråd 2.

gem start tid.
sleep(100); // vent 100 sekunder
gem slut tid.

Hovedtråd check tid.

Parallelport bruger som regel interrupt men de er skjult af diverse drivere og ikke direkte tilgængelige for almindelige programmøre, du kan dog selv gå ind og se i linux hvordan de gør.

Måske findes der en anden løsning på dit problem hvis du ville fortælle hvad det er?
Avatar billede skrewz Nybegynder
27. maj 2004 - 20:21 #7
En udmærket løsning på mit problem var at erstatte min 2.4.22-10mdk-kernel med en 2.6.6'er. Flere steder i konfigurationen af kernelen har man mulighed for at vælge alle mulige timere til og fra. Ultimativt må der være mange hardwaretimere i en i386-kompatibel, siden jeg kunne genere dette output (mens jeg havde en anden CPU-krævende process kørende):

[root@le-skrewz sleepTester]# ./main
i = 1
i = 127620
i = 124655
i = 153812
i = 56953
i = 146475
i = 104472
i = 69490
i = 138346
i = 126544
i = 161218
i = 141071

(hvor i er antallet af usleep(1) på et sekund). Mere information skal jeg gerne supplere. Ellers uddeler jeg hermed de omtalte goodwill-point, da ingen har suppleret en reel løsning på mit problem, men blot forklaringer af det.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester