Non buffered getc(3) under GNU/Linux

By Olivier Mehani <shtrom-kb@ssji.net>

Abstract

This explains a method to disable line-buffering on streams in order to get every datum as soon as it arrives, for example keypresses.

Introduction

GNU/Linux standard I/O functions (stdio et. al) provide an efficient way to dealing with data streams. By default, they provide a line-buffered behavior. Most of the time, this is not important, but it may be sometime needed to have no bufferring at all. This can be useful when immediate handling of keypresses is needed.

The getchar() function, as implemented under DOS, is unbuffered, allowing direct keypresses catching. With GNU/Linux's buffered I/O this behavior is not directly accessible. The first idea is to play with fcntl(2) or the flags passed to open(2), but this doesn't work well (or at least, I didn't managed to do what I wanted this way).

Playing with termios

Under GNU/Linux, several terminal handling functions are provided. These are called the termios functions, I guess this means Terminal Input/Ouput Setting. They allow setting the behavior of terminal related functions (including getc(3)). They allow configuration of serial lines too, but it's another story.

Sample code

Here is a sample piece of code to show how to configure unbuffered I/O:

#include <stdio.h>
#include <unistd.h>
#include <termios.h>

int main()
{
	struct termios old_tio, new_tio;
	unsigned char c;

	/* get the terminal settings for stdin */
	tcgetattr(STDIN_FILENO,&old_tio);

	/* we want to keep the old setting to restore them a the end */
	new_tio=old_tio;

	/* disable canonical mode (buffered i/o) and local echo */
	new_tio.c_lflag &=(~ICANON & ~ECHO);

	/* set the new settings immediately */
	tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);

	do {
		 c=getchar();
		 printf("%d ",c);
	} while(c!='q');
	
	/* restore the former settings */
	tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);

	return 0;
}

Compile

You can compile this file with (assuming the file is called unbufgetc.c):

$ gcc unbufgetc.c -o unbufgetc

Then you just have to run this program without parameters and see the characters' ASCII code printing on the screen as soon as you press the key. When you're done, press q (lowercase) to exit.


Page generated: 2012-04-01T12:11:24+10:00
Source: $Id: getc.xml 66 2010-06-18 04:16:48Z shtrom $
Stylesheet: $Id: page.xsl 68 2010-06-18 05:01:18Z shtrom $