5

I would like to know if it's possible to access processor interrupts from a c++ code (I imagine I will need to use assembly code).

Here's the thing. I am used to working with embedded systems (PIC, ARM7 and Atmel processors) and I can program my interrupts without any problem (I use C). All registers are mapped, and all in all it's farely easy, depending on the application. Now I'm working with x86 and x64 architecture and I want (emphasis on WANT) to be able to do the same in these processors.

For example: I want to have a thread in c++ running a code that constantly verifies the key being pressed at the moment without pressing the enter key (cin, getchar, etc). I want to program a timer interrupt so I will be able to perform actions at an specific time. I understand that many of the things I want to do can be done via the operating system, but I really want to have the freedom to do so on my own.

Currently I'm using Linux (Ubuntu), but I will certainly be working with Windows soon, if that's an information needed to answer that question

morcillo
  • 1,091
  • 5
  • 19
  • 51
  • 7
    Trust me, this is just the wrong road to go down. Learn to do this the *right* way on Linux. You will never write good code if you insist on writing code in one environment the way that's only appropriate for a completely different environment. The OS owns the interrupts. That's the way desktop OSes work. – David Schwartz Aug 29 '12 at 22:18
  • @DavidSchwartz So ... I should somehow get the interrupts from the OS? Where could I get the information? As you may have noticed I'm rather new to C++ and higher level coding. – morcillo Aug 29 '12 at 22:20
  • Why are you thinking about interrupts? Think about how to do what you want to do. Interrupts are one of the ways you get things done -- what are the things you are trying to do? (To do something at a particular time, you can use a thread or `setitimer`, for example.) – David Schwartz Aug 29 '12 at 22:21
  • 5
    @morcillo: If you have an OS, then you interact with the hardware through device drivers. These provide an abstraction of how the hardware works, and don't (usually) allow you to control it or receive interrupts directly. You'll have to learn the driver's API and interact with that instead. – Mike Seymour Aug 29 '12 at 22:23
  • @DavidSchwartz I've had to program interrupts since the first month I started learning about embedded systems. I've always needed them to perform time critical activities, such as refreshing screen so the user will se an animation. Poll data from AD channels for temperature control, etc. Working with – morcillo Aug 29 '12 at 22:24
  • @DavidSchwartz Working with C++ I've noticed that some functions require the enter key (cin .. etc) and I just started wondering if I could rewrite, or even better, write my own code to access the procfessor in the lower levels in order to do anything I want. Apparently that's the wrong thing to do – morcillo Aug 29 '12 at 22:25
  • @morcillo: Most drivers allow you to receive input events in (more or less) real time; on Linux, that will be through a blocking `read` or `poll` system call. But there's also a boundary between the kernel (which can access the hardware directly) and user-land (which usually can't), so you have to use the device drivers to cross that boundary. That's the price you pay for the convenience and protection of an OS. – Mike Seymour Aug 29 '12 at 22:29
  • 1
    @morcillo: Surely when working with interrupts previously you did minimal work in the ISR context and instead signalled (with a semaphore or flag) some other component (like a task or monolithic processing loop) to do the real work. It works the same way with an OS/driver except now you have a user-space task blocking until it receives data from the driver. – indiv Aug 29 '12 at 22:33
  • 1
    You cannot access the interrupt descriptor table (IDT) to manage interrupts on x86/x64 from user-level code modern OSes like Windows and Linux. Both run user code at CPL 3, but you need to be at CPL 0 to modify the IDT with the LIDT instruction. To run at CPL 0, you either need to write a driver/kernel extension or write your own OS. – Adam Rosenfield Aug 29 '12 at 22:43

2 Answers2

5

For user-level processes, interrupts are replaced by signals. You can arrange to have a signal sent to your process by calling setitimer. But most likely, the best way to do what you're trying to do is one of two things:

  1. Use an event loop. Basically, write your program as a giant loop that periodically checks to see if there's anything it needs to do. In the loop, check the time, check for keypresses, and so on. Do a little bit of work on whatever you need to do, and loop again.

  2. Use threads. You can have a thread just to watch the time and trigger timer jobs. You can have a thread that blocks on a read to act like an interrupt when data arrives.

Likely it was drilled into your head that you do minimal work in the interrupt handler itself, typically just passing on information to other code that runs in a normal context. Well, the OS already does that part for you. You just have to write the code that waits for the interrupt handler (or whatever is needed) to detect and begin processing the event.

I want to have a thread in c++ running a code that constantly verifies the key being pressed at the moment without pressing the enter key (cin, getchar, etc).

So do that. That requires a thread and it requires changing the terminal's input mode to one that doesn't require an enter key. That has nothing to do with interrupts.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • This means that I can access the processor's flags indirectly. That actually helps me a lot. If you could edit your question a little bit (so everyone will see it clearly), adding if those signals are dependant on the operating system, that would be perfect for me and everybody else that has the same question. Also ... any recommended literature on this topic? I know google is my friend and I should use it, but doing that will probably make me start the wrong way, and I really want to get knowledge that will stick in my brain for later use. – morcillo Aug 29 '12 at 22:33
  • 1
    In 2022, I think a third option (which may actually deserve to be at the top) could be 3) use a future and some async code, right? This would be maybe better adapted to this kind of IO tasks than using a thread, and simpler to keep track on than using an event loop when the program grows? – Zorglub29 Aug 09 '22 at 09:23
0

For Windows:

Windows does a very good job in hiding low level hardware access (like accessing cpu interrupts) and the reason is because the win kernel is using them for switching between processes and other internal stuff. So you will need to write a driver to get direct hardware access or to get you code executed in an execution ring < 3 (user mode).

But for educational purposes you can use DOS or even a Windows DOS window, even interrupts are emulated. And of course you will be using some compiler like Borland C++ 3.x (dos 16bit). setvect and getvect are available there for interrupt hooking.

kcsoft
  • 2,917
  • 19
  • 14