1

Suppose I have some code that does this:

while(1) {
      scanf("%c", &key);
      // if E or e, exit
      if (key == 'E' ||  key == 'e')
          break;
}

This obviously does not take up all the resources of even a single core. It just... "sits" there until someone actually presses an E. My question is: how does the runtime find out that it should not take up all the resources of a core just waiting for a scanf? Is scanf a special case in that it is I/O and as such the OS schedules it out until a key is effectively pressed? Can I somehow force it to be whileing all the time by say, adding a a++ inside the loop?

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
Dervin Thunk
  • 19,515
  • 28
  • 127
  • 217
  • Wait, are you trying to use up all CPU time, intentionally? – BlackVegetable Apr 18 '13 at 15:57
  • @BlackVegetable: No. I'm trying to find out why it doesn't. – Dervin Thunk Apr 18 '13 at 15:58
  • Perhaps someone will press CTRL+Z on Windows, or CTRL+d on Linux, and you'll notice that this question is invalid because when that happens, the CPU-hogging nature of this infinite loop will dawn upon you. I say it way too often: *Remember to check the return value!* This goes for *every* function. Your loop should look more like: `while (scanf("%c", &key) == 1) { /* ... */ }` – autistic Apr 18 '13 at 15:58
  • @modifiablelvalue: I've no idea what you're saying... sorry. :) – Dervin Thunk Apr 18 '13 at 15:59
  • 1
    @DervinThunk, I'm saying: **Always** check the return value of `scanf`, or your code might malfunction in subtle or devastating ways. – autistic Apr 18 '13 at 16:02
  • @DervinThunk The point of the above is that when the input stream is closed, then `scanf` will return immediately (returning `EOF`) and then the loop _will_ take up all CPU resources the OS gives the process. – Daniel Fischer Apr 18 '13 at 16:11

1 Answers1

6

Is scanf a special case in that it is I/O and as such the OS schedules it out until a key is effectively pressed

That's exactly what is happening. In this case scanf is a blocking operation. That is, if it can't be executed immediately (nothing in the input buffer) the OS simply puts your process to sleep, remembering to wake it up when something turns up.

Can I somehow force it to be whileing all the time by say, adding a a++ inside the loop

An a++ won't change anything. You won't be able to peg the CPU as long as you have long-waiting blocking calls.


until a key is effectively pressed

In Linux input is usually "cooked". That is, pressing a single key isn't typically enough (you also need to hit return before your process gets a chance to look at the data).


As Basile correctly mentions in the comments scanf itself may not always block. If there's enough input in the stdio buffer scanf will just return it. If not it will then call read(2) which can block.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • are there "blocking" ops that are not IO? – Dervin Thunk Apr 18 '13 at 15:57
  • @DervinThunk Interesting question. Look for `pause(2)`. In practice all the system call needs to do (in Linux) is call `wait_event_interruptible` or similar. So it's not strictly for I/O. – cnicutar Apr 18 '13 at 15:59
  • Alright. I'll look it up. Thanks, I'm trying to accept your answer but it seems they've recently changed it and now it's timed. I will accept as soon as possible. – Dervin Thunk Apr 18 '13 at 16:01
  • @DervinThunk Wait! Don't accept it just yet. Wait some more, perhaps better stuff turns up. – cnicutar Apr 18 '13 at 16:02
  • @DervinThunk, some examples of blocking non-IO sysalls are: [nanosleep()](http://linux.die.net/man/2/nanosleep) (ok, that one is pretty obvious) and [vfork()](http://linux.die.net/man/2/vfork). – shakurov Apr 18 '13 at 16:04
  • 2
    Actually (at least on Linux), `scanf` will call a blocking operation (the `read(2)` syscall). `scanf` is not always blocking (if the `stdin` file buffer has bytes, it could use them) but it may call a blocking primitive (`read(2)` on Posix systems). On Windows, you have equivalent things. – Basile Starynkevitch Apr 18 '13 at 16:12
  • @BasileStarynkevitch That's right. If there's sufficient input in the stdio buffer `scanf` won't block. – cnicutar Apr 18 '13 at 16:18