tags:

views:

70

answers:

2

I need to know which interrupt in linux checks if any key was pressed.

Thanks.

A: 

Sorry, I wasn't clear. I meant which service. (e.g service number 4 is for writing)

Sason
+1  A: 

I'm assuming that you want this on a terminal emulator (and not on an X client), and that you don't care about key release.

The Linux way to do this would be to use termios(3) to set the terminal to non-canonical or to raw mode, then read stdin using the usual libc functions.

System call numbers on Linux are on /usr/include/asm/unistd.h (or unistd_64.h), but the termios functions end up getting converted to ioctl()'s. So, if you can't call libc for some strange and unusual reason, you'll have to lookup the syscall number for ioctl, and the ioctl's corresponding to termios functions.

Edit:

Apparently, you're assuming that Linux uses the same model as DOS, in which the console input is an abstraction of a keyboard (with functions like KEYPRESSED, GETC, ...) and the console output is an abstraction of a character-oriented display.

Unix/Linux abstraction is about terminals, which can be the physical console, a terminal (or terminal emulator) on a serial port, an xterm, ... An important point here is that by default, input lines are not made available to programs until the terminal (or terminal emulator) sees a line delimiter.

On POSIX, these terminals are controlled by the termios(3) functions. Linux ends up translating those to ioctl() calls, as follows (see tty_ioctl(4)):

  • tcgetattr(fd, arg) => ioctl(fd, TCGETS, arg)
  • tcsetattr(fd, TCSANOW, arg) => ioctl(fd, TCSETS, arg)
  • tcsetattr(fd, TCSADRAIN, arg) => ioctl(fd, TCSETSW, arg)
  • tcsetattr(fd, TCSAFLUSH, arg) => ioctl(fd, TCSETSF, arg)
  • ...

So, a C program to do what you asked for, using termios(3) and poll(2) (error checking stripped for brevity and clarity):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <termios.h>
#include <sys/ioctl.h>

static sig_atomic_t end = 0;

static void sighandler(int signo)
{
    end = 1;
}

int main()
{
    struct termios oldtio, curtio;
    struct sigaction sa;

    /* Save stdin terminal attributes */
    tcgetattr(0, &oldtio);

    /* Make sure we exit cleanly */
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = sighandler;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGQUIT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    /* This is needed to be able to tcsetattr() after a hangup (Ctrl-C)
     * see tcsetattr() on POSIX
     */
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = SIG_IGN;
    sigaction(SIGTTOU, &sa, NULL);

    /* Set non-canonical no-echo for stdin */
    tcgetattr(0, &curtio);
    curtio.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(0, TCSANOW, &curtio);

    /* main loop */
    while (!end) {
            struct pollfd pfds[1];
            int ret;
            char c;

            /* See if there is data available */
            pfds[0].fd = 0;
            pfds[0].events = POLLIN;
            ret = poll(pfds, 1, 0);

            /* Consume data */
            if (ret > 0) {
                    printf("Data available\n");
                    read(0, &c, 1);
            }
    }

    /* restore terminal attributes */
    tcsetattr(0, TCSANOW, &oldtio);

    return 0;
}

Now, ioctl and poll are syscalls, and you can find their numbers on /usr/include/asm/unistd.h (54 and 168 on x86), and /usr/include/asm/ioctls.h has the ioctl constants you need (on x86: TCGETS=0x5401, TCSETS=0x5402, TCSETSW=0x5403, TCSETSF=0x5404).

ninjalj
I want to use an interrupt service. I KNOW there's such a service for dos interrupts, so I figured there's also for linux...
Sason
No, ninjalj has described what you need. On Linux (i386 architecture), you can make system calls using int 0x80 with the service number in eax. However, unlike DOS there is no direct call for "check if a key is pressed". For the reasons see http://en.wikipedia.org/wiki/Ring_%28computer_security%29 and http://en.wikipedia.org/wiki/User_space. Unix-like systems use the terminal abstraction, and you must follow ninjalj's instructions unless you want to modify Linux itself.
Robie Basak