The proper sequence for using /dev/pit is as follows: 1. Open /dev/pit. pit_fd = open("/dev/pit", O_RDONLY); - Be sure to check for errors! If open fails, pit_fd will be set to -1, and errno will contain the specific error code. 2. If using asynchronous notification, enable SIGIO ahead of time. signal(SIGIO, input_handler); fcntl(pit_fd, F_SETOWN, getpid()); fcntl(pit_fd, F_SETFL, fcntl(pit_fd, F_GETFL) | FASYNC); - Whenever /dev/pit becomes readable (i.e. has a tick), this program will get a SIGIO signal, resulting in an asynchronous call to the input_handler function. - This is useful if the program needs to do long-running yet low-priority calculations and can't afford to spend any time waiting for user input or timer ticks. 3. Set the divisor and start the clock. ioctl(pit_fd, PIT_SET_DIVISOR, &divisor); - The timer now starts ticking, but the computer will ignore any ticks until... 4. Enable timer interrupts. ioctl(pit_fd, PIT_ENABLE_TICKS); - Now timer ticks are registered by the computer. 5. To wait for a timer tick: read(pit_fd, &tick_count, sizeof(tick_count)); - This will return sizeof(tick_count) and store the number of ticks since the previous read in tick_count. - If no ticks have taken place since the previous read, and pit_fd has O_NONBLOCK set (non-blocking I/O), this will instead return -1 and errno will be set to EAGAIN ("try again"). - If no ticks have happened and O_NONBLOCK is not set (default), then this call won't return until a tick occurs, and tick_count will (probably) be set to 1. - or - FD_ZERO(&read_fds); FD_SET(pit_fd, &read_fds); select(pit_fd + 1, &read_fds, NULL, NULL, NULL); - If a tick happened since the last read, select will return immediately. If not, select will wait for a tick. - If the program really has nothing better to do than wait for timer ticks, it's better to just use blocking reads. But if the program needs to watch keyboard input, network traffic, etc. while watching for timer ticks, then select (or better yet, poll) is the way to go. - or - struct pollfd ufds = {pit_fd, POLLIN}; poll(&ufds, 1, 0); - This is a more civilized version of select. See poll(2) for information on how to use it effectively. 6. Loop. - Your program probably wants to wait for more than just one tick, right? :^) 7. Close /dev/pit. close(pit_fd); - Again, check for errors. In this specific case, I'm not sure what can go wrong, but nevertheless, checking the return values of all library functions is a good habit.