[C++ op Linux] non-blocking getch(): waar te vinden?

Pagina: 1
Acties:
  • 258 views sinds 30-01-2008
  • Reageer

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
Hallo,

Ik heb overal gezocht, maar ik kon niet vinden wat ik zoek. Ik heb een programma voor Linux gemaakt, waarin ik een whileloop heb die op invoer wacht. Het probleem is nu dat ik elke minuut een logscherm wil updaten, wat dus niet kan terwijl getch() aan het wachten is. Weet iemand hoe ik in linux kan wachten op gebruikersinput, maar ook iets anders kan doen? Een timeout op getch() bijvoorbeeld, of een functie die kijkt of er input is? Voor zover ik weet is zo'n functie er wel voor windows (kbhit() ), maar niet voor linux.
Wie helpt me uit de brand?

Omschrijving programma: ik heb een programma gemaakt, dat dmv corba verbinding maakt naar een server, en met NCURSES een eenvoudig te begrijpen interface via putty neer kan zetten. Daarin zit o.a. een log-venster, en die moet elke minuut ofzo worden geupdate.

  • Ghost(NL)
  • Registratie: December 2000
  • Niet online
Even diep nadenken :) Hoe was het ook alweer ?

Hm geloof als volgt:

Mischien een idee om te forken, ik weet niet of je weet wat dat is ? maar dat houd in dat het multithreaded word waardoor je twee procesjes hebt die kunnen dan semi tegelijkertijd runnen en doen wat je wil.

i5-12600K PRIME Z690M-PLUS D4 64GB 980 Pro M.2 1TB  MBA M1 13" 8GB 256GB (Late '20)


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Kijk eens naar de 'select' functie. (man 2 select).

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
En dat wilde ik nou net een beetje vermijden.
Ik had het programma in windows m.b.v. TThread multithreaded wat betreft het uitlezen van de hardware (jaja, 150-200 windmeters, die nog steeds niet zijn geleverd door electro :( ), alleen dat kan ik voor linux niet vinden.
Er waren diverse redenen om over te stappen op linux, en daarbij wil ik het niet moeilijker maken dan het is. Ik heb nog tot vrijdag, en wilde dit nog 'effe' toevoegen. Forken wordt te veel werk, en te grote kans op fouten die voor iemand anders niet meer op te lossen zijn. Multithreaded wil ik best wel doen, als ik een goeie implementatie van TThread kan vinden, die wel kan compileren |:(

Ik had zelf een beetje richting interrupts zitten denken, maar dat schijnt ook niet al te makkelijk te zijn :)

  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 31-03 16:47

CyberSnooP

^^^^ schrijft --->

Waarom vereis je TThread? Wat bied dat voor extra functionaliteit boven de standaard Linux Threads (waar bergen info over te vinden is, in zowel boeken als op internet)?

|_____vakje______|


  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
Infinitive schreef op 20 januari 2004 @ 20:15:
Kijk eens naar de 'select' functie. (man 2 select).
Waarom heeft niet iemand een getch(int waitsec) gemaakt? Bedankt, die ga ik gebruiken, als het lukt :)

  • Ghost(NL)
  • Registratie: December 2000
  • Niet online
CyberSnooP schreef op 20 januari 2004 @ 20:19:
Waarom vereis je TThread? Wat bied dat voor extra functionaliteit boven de standaard Linux Threads (waar bergen info over te vinden is, in zowel boeken als op internet)?
Ja idd wat CyberSnoop zegt kijk bijvoorbeeld eens Hier

Als je niet wilt dat is natuurlijk je goed recht :) maar het lijkt me wel een aardige oplossing.

En zou je mischien willen/kunnen toelichten waarom je TThread moet gebruiken ?

i5-12600K PRIME Z690M-PLUS D4 64GB 980 Pro M.2 1TB  MBA M1 13" 8GB 256GB (Late '20)


  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
CyberSnooP schreef op 20 januari 2004 @ 20:19:
Waarom vereis je TThread? Wat bied dat voor extra functionaliteit boven de standaard Linux Threads (waar bergen info over te vinden is, in zowel boeken als op internet)?
TThread? Omdat ik daar al wat voor heb gemaakt, en het effe snel nog moet. Ik heb een implementatie gemaakt die random waardes teruggeeft (bij gebrek aan windmeters), en zou graag die willen hergebruiken. Ik schat dat ik weer 5 uur bezig ben voor ik 'iets' met pthreads heb gemaakt, en dat wil ik niet meer. Ik heb nog een paar dingen die af moeten zijn :)
Waarom ik ooit voor TThread had gekozen? omdat ik in Borland C++ Builder was begonnen, en met voortschreidend inzicht (en de specs van de pc) bleek linux beter voor die taak. Helaas was C++ Builder X nog niet uit toen ik begon :)

edit:
waarom geen fork? Omdat ik niet wist dat daar een klasse voor was, en omdat ik daar wat nachtmerries aan over heb gehouden door een slechte leraar, 1,5 jaar geleden :)

[ Voor 11% gewijzigd door MBV op 20-01-2004 20:28 ]


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Waarom heeft niet iemand een getch(int waitsec) gemaakt? Bedankt, die ga ik gebruiken, als het lukt :)
Het is niet zo heel moeilijk om een getch(int waitsec) te maken met behulp van select :)

Je zult het file-descriptior-number voor de standaard input moeten hebben. Deze is volgens mij gedefineerd als het getal 0. Anders is er geloof ik ook een constante voor (?) en anders heb je ook nog ergens een functie rondhangen die onder linux uit een FILE* het file-desctriptor-number haalt (die je dan met STDIN kan voeden)...

Verder werkt deze functie op een array van filedescriptors. In jouw geval is dit dus een array met één elementje erin. Namelijk dat nummer.

Met select kan je trouwens ook nog wel wat mooiers doen: ik weet niet waar je die log-data vandaan haalt, maar als dit uit een 'pipe'/'socket' vandaan komt, dan kun je dat ook in de select stoppen en zo op het moment dat er nieuwe data is meteen het scherm bijwerken :9

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
zoals ik al zei, het gaat om een textbased UI, waar mensen door menu'tjes heen kunnen wandelen. Zoiets als de textbased installers enzo.
Ik heb het voorbeeld dat onderaan de man-page stond omgetoverd in een functie die max X sec. wacht, en vervolgens teruggeeft of er wel of geen IO is geweest. Ik ga hem zo testen (is een P75 van school waar ik het op moet compileren :'( ), als hij het werkt zal ik hier de code wel posten.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
Je kunt ook de zg canonical mode ( line buffered ) mode van de console uitzetten met tcsetattr

Je moet dan echter de stdio lib ook nog unbuffered maken, volgens mij met setbuf( stdin, NULL )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int waitkey(int sec)
{
    fd_set rfds;
    struct timeval tv;
    int retval;
        
    /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
     /* Wait up to timeout seconds. */
    tv.tv_sec = sec;
    tv.tv_usec = 0;
    retval = select(1, &rfds, NULL, NULL, &tv);
    if (retval)
        return 1;
    else
    return 0;
}

Dit werkte voor mij. Blijkt alleen dat je ervoor een refresh() aanroep moet doen, als je in NCurses mode zit. Hij geeft een 1 terug als er invoer is geweest, en 0 als er binnen 'sec' seconden niets is ingevoerd.

GPL bladibla, disclaimer bladibla, not made to be usefull for anything, bladibla :)

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Is fileno(stdin) in plaats van 0 niet iets netter en veiliger?

[ Voor 15% gewijzigd door Olaf van der Spek op 24-01-2004 13:33 ]


  • MBV
  • Registratie: Februari 2002
  • Laatst online: 19-05 21:26
Geen idee, zoals gezegd heb ik het voorbeeld gepakt, en heb ik eigenlijk geen idee wat tussen regel 8 en 13 gebeurt :)
Dit werkte, misschien is dat voor iemand anders wel beter. Ik heb het project afgerond, en ga er zodoende niets meer aan veranderen :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

OlafvdSpek schreef op 24 januari 2004 @ 13:32:
Is fileno(stdin) in plaats van 0 niet iets netter en veiliger?
volgens mij is het gedefinieerd dat 0 altijd stdin is, 1 stdout en 2 stderr

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Misschien, maar zelf ben je zo te zien ook niet zeker en voor een ander is het ook niet zo duidelijk wat er gebeurd.

  • flok
  • Registratie: April 2003
  • Laatst online: 11-03-2023

flok

www.vanheusden.com

als je alleen wilt kijken OF er iets klaar staat en vervolgens gewoon door wilt gaan in het andere geval, dan kun je beter even met poll() ipv select() poken

www.vanheusden.com


  • Wirf
  • Registratie: April 2000
  • Laatst online: 13:25
uuh.. heb je al eens naar de man page van getch() gekeken?
DESCRIPTION
The getch, wgetch, mvgetch and mvwgetch, routines read a character from
the window. In no-delay mode, if no input is waiting, the value ERR is
returned.
In delay mode, the program waits until the system passes
text through to the program. Depending on the setting of cbreak, this
is after one character (cbreak mode), or after the first newline
(nocbreak mode). In half-delay mode, the program waits until a charac-
ter is typed or the specified timeout has been reached.
Dat is toch precies wat je wil?

nog ff het stukje uit de man page van cbreak:
#include <curses.h>

int cbreak(void);
int halfdelay(int tenths);
int nodelay(WINDOW *win, bool bf);

Normally, the tty driver buffers typed characters until a newline or
carriage return is typed. The cbreak routine disables line buffering
and erase/kill character-processing (interrupt and flow control charac-
ters are unaffected), making characters typed by the user immediately
available to the program. The nocbreak routine returns the terminal to
normal (cooked) mode.

The halfdelay routine is used for half-delay mode, which is similar to
cbreak mode in that characters typed by the user are immediately avail-
able to the program. However, after blocking for tenths tenths of sec-
onds, ERR is returned if nothing has been typed. The value of tenths
must be a number between 1 and 255. Use nocbreak to leave half-delay
mode.

The nodelay option causes getch to be a non-blocking call. If no input
is ready, getch returns ERR. If disabled (bf is FALSE), getch waits
until a key is pressed.
(met wat knip- en plakwerk van mij)

Heeft sinds kort zijn wachtwoord weer terug gevonden!

Pagina: 1