Provádíte IO nesprávně, manuál POSIX a veškerá další související dokumentace výslovně říká nikdy nesměšovat IO provedené na FILE * s a deskriptory souborů. Toto pravidlo jste velmi očividně porušil. Toto pravidlo platí, protože FILE * s pomocí vyrovnávací paměti a to znamená, že po volání na fgets pro read nezbude nic získat, protože fgets již načetl všechna čekající data do vyrovnávací paměti, která je uložena v FILE * struktura.
Takže protože neexistuje způsob, jak zkontrolovat, zda bude metoda ISO C IO blokována, musíme používat pouze deskriptory souborů.
Protože víme, že STDIN_FILENO je pouze číslo 0, můžeme použít
fcntl (0, F_SETFL, O_NONBLOCK);
toto změní všech read s na deskriptoru souboru 0 do neblokovacího režimu, pokud chcete použít jiný deskriptor souboru, abyste mohli ponechat 0, stačí použít dup jej duplikovat.
Tímto způsobem se můžete držet dál od poll kompletně a implementovat ngetc jako
ssize_t
ngetc (char *c)
{
return read (0, c, 1);
}
nebo ještě lépe makro
#define ngetc(c) (read (0, (c), 1))
Získáte tak jednoduchou implementaci toho, co hledáte.
Upravit: Pokud se stále obáváte, že terminál ukládá vstup do vyrovnávací paměti, můžete kdykoli změnit nastavení terminálu, viz Jak z programu zakázat ukládání do vyrovnávací paměti řádku vstupu v xterm? pro více informací o tom, jak to provést.
Upravit: Důvod, proč nelze použít fgetc místo read je ze stejného důvodu jako použití fgets nebude fungovat. Když jeden z FILE * IO funkce jsou spuštěny, čte všechna data z přidruženého deskriptoru souboru. Ale jakmile se to stane, poll se nikdy nevrátí, protože čeká na deskriptor souboru, který je vždy prázdný, a totéž se stane s read . Navrhuji proto, abyste se řídili radami v dokumentaci a nikdy mix streamů (IO pomocí fgets , fgetc , atd.) a deskriptory souborů (IO pomocí read , write atd.)