Sida 1 av 1

Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 10:01:17
av Marta
Behöver testa om en tangent har tryckts ned före getchar så den inte blockerar. select() funkar inte, vill tvunget ha en satans Enter för att "släppa" och tycks dessutom eka tangenterna. Vill undvika ncurses.

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 10:25:44
av baron3d
Har du "conio.h" så har du kbhit().

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 11:02:35
av Marta
Den har jag provat, men conio.h saknas. Läste att det är något som bara finns ihop med Microsoft.

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 11:04:34
av hawkan
Här står en massa om detta. Mer än man vill veta kanske.

https://viewsourcecode.org/snaptoken/ki ... wMode.html

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 15:26:03
av Marta
Tack till Er för svar.

Den länkade artikeln förde in på rätt spår. Alla "duktigheter" måste vara bortvalda när select() utförs, annars träder desa in och ställer till det. Trodde denna bara kollade om tecken väntade, men tydligen ingår hela härket som termios specificerat.

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 19:37:34
av Oskar
Jag har gjort ett sådant här Linuxprojekt en gång för många år sedan. I början snodde jag en kbhit() anpassad för Linux som jag använde. Efter att ha studerat denna funktion närmare (den använde select()), så gjorde jag om mitt projekt till att också använda select(). Jag behövde vänta på tecken från serieporten och tangenttryckningar, och det fick inte vara blockerande. Det låter som om ditt scenario är liknande?

Om jag nu mins rätt sätter man upp en bitmask för vilka källor man väntar på input från, sedan sätter man upp en timer och poll:ar select() med lämpligt interval. Skall kika på min gamla kod.

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 20:55:59
av Oskar
Jag hittade mitt program, så här görs testningen:

Kod: Markera allt

		FD_SET(fd_relay,&read_fd);  //set testing for relay card on serial port 
		FD_SET(fd_fifo,&read_fd);  //set testing for input from client program that writes commands to FIFO file
		FD_SET(0,&read_fd);   		//set testing for stdin  (file descriptor = 0 is stdin)
		select(maxfd+1, &read_fd, NULL, NULL, &tv); //check for available I/O
Efter select() anropet kan man testa varje "file descriptor" för sig:

Kod: Markera allt

		if(FD_ISSET(0,&read_fd)) //keyboard input recieved
		{
			key=getch();
			.....
Så gjorde i alla fall jag för att få ihop ett program som kan vänta på input från flera källor och inte blockera. Om du vill kan du få koden till hela projektet om det kan vara till hjälp fär dig, men i så fall bered dig på hemsk läsning, jag är ingen professionell programmerare...

Det är svårt att slippa ncurses om man vill snickra ihop lite mer avancerade console program i Linux, man kan göra mycket mer kraftfulla program om man man vänder det.
EDIT:
Lade även till kbhit.c och kbhit.h
De kan du också använda. Kompilerade fint vad jag mins i gcc under Linux. Som du ser är det select även där.
kbhit.c
kbhit.h

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 21:04:39
av sodjan
Men det är alltså fortfarande en "pollning" hela tiden? Man kan inte bara ange att man
vill ha ett interrupt då någon "händer" på valfri I/O? Jag vet ingenting om Linux...

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 21:09:42
av Oskar
Jo det är en form av pollning, men det sker så snabbt så det är inget problem. Faktiskt så måste man lägga in en usleep() i sin loop, annars äter programmet upp _all_ CPU.

Jodå, man kan använda interrupts också men det blir mer jobb.

Ja, sedan kan säkert någon annan bättre sätt att lösa detta på, återigen - jag är ingen professionell programmerare :)

Re: Linux, testa om tangenttryckning väntar?

Postat: 14 februari 2021, 21:46:21
av sodjan
OK. Jag vet inte något om Linux, men där jag arbetar så har vi något som heter AST, "Asynchronous System Trap".
Man anropar en I/O rutin med adressen (pekare) till den rutin/function som ska anropas då I/O'n utförs som en parameter.
Man man ha flera I/O "outstanding" medan applikationen ligger i "sleep" (eller "hibernate" som det kallas). Ingen pollning
(från applikationen), applikationen gör helt enkelt ingenting under tiden. Inga waits eller någon annan overhead.
Applikationen som väntar på ett I/O tar ingen CPU alls under tiden.

Det liknar lite då man t.ex. startar en ADC omvandling i en microcontroller och sedan går till "sleep"
i väntar på ett interrupt från ADC modulen. Fast implementerat i ett normalt OS. Trevligt.

Jag tänkte att/om Linux hade någon liknande funktion.

Re: Linux, testa om tangenttryckning väntar?

Postat: 15 februari 2021, 01:27:53
av mankan
Select kan sova tills det händer något på en eller flera fildeskriptorer eller timeout sker. (Eller blir avbruten av en signal)

Re: Linux, testa om tangenttryckning väntar?

Postat: 16 februari 2021, 18:27:06
av Marta
Tack för programkoden, det var lätt att anpassa till mitt program.

Linux har inte några callback-funktioner vad jag vet. Används X så är där en eventloop. En funktion anropas som blockerar tills ett av de event som inte är maskerade inträffar. Sedan får en switch(event) fördela ut till vad som skall hantera dem. Det blir ju i princip samma sak, men på ett sätt utan risk for ej avregistrerade callbacks som ligger kvar och orsakar problem.

Det som förvånade mig mycket var att select() gjorde så tangenter ekades och den blockerade till en linefeed om inte detta krafs valts bort med termios innan.

Re: Linux, testa om tangenttryckning väntar?

Postat: 16 februari 2021, 20:30:12
av Oskar
Kul att du fick ordning på det!

Termios är en rolig djungel.
Att lyckas få rätt locale en annan ;)