rolphin |
Un problème récurrent évoqué sur le forum est le fameux read
bloquant, je vous propose d'y voir un peu plus clair.
Mettre un fd en mode non bloquant:
Code :
- #include <fcntl.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <errno.h>
- int main()
- {
- int mode;
- int ret;
- char buf[512];
- int fd;
- int data = 1;
- int timeout = 3;
- fd = 0;
- mode = fcntl(fd, F_GETFL, 0);
- mode |= O_NONBLOCK;
- fcntl(fd, F_SETFL, mode);
- while ( data ) {
- ret = read(0, buf, 512);
- switch (ret) {
- case -1:
- if ( errno == EAGAIN ) {
- printf("degoute, rien a lire, j'attends %d secondes\n", timeout);
- sleep(timeout);
- continue;
- }
- break;
- case 0:
- data = 0;
- break;
- default:
- /* je ne mets pas de 0 terminal,
- ** car je n'affiche que 'ret' caractères...
- */
- printf(">> %.*s\n", ret, buf);
- }
- }
- return 1;
- }
|
Ce programme n'est pas capable d'executer quelquechose à l'instant
ou la donnée est disponible, il va forcément faire le
sleep(timeout) en entier.
Il faut utiliser select ou mieux poll pour sortir dès qu'une donnée
est disponible...
Code :
- int wait_for_input()
- {
- int ret = 0;
- struct pollfd fds;
- /* on regarde sur l'entree standard */
- fds.fd = 0;
- fds.events = POLLIN;
- if ( ! poll(&fds, 1, 5000) ) {
- printf("rien à lire\n" );
- /* ici ca fait 5 secondes que rien n'est
- ** arrivé
- */
- }
- if ( fds.revents & ( POLLOUT | POLLERR | POLLHUP ) ) {
- printf("Deconnexion ... fin de fichier\n" );
- /* ici on sait que le read va retourner 0 */
- }
- if ( (ret = read( 0, buf, 512 )) < 0 ) {
- printf("Probleme de lecture..." );
- /* ici le read à foiré */
- }
- /* ici 'buf' est rempli de 'ret' caractères */
- }
|
Cadeau bonus, Spécial flex....
Code :
- %{
- #include <poll.h>
- /* variable externe utilisée dans une boucle quelconque permettant
- * d'arreter le déroulement du programme...
- *
- extern int fatal;
-
- static void fatal_error(const char *msg);
- #define YY_FATAL_ERROR(msg) fatal_error(msg);
-
- /* timeout de 5 secondes */
- #define YY_INPUT(buf, result, max_size) \
- do { \
- int ret = 0; \
- struct pollfd fds; \
- fds.fd = 0; \
- fds.events = POLLIN; \
- if ( ! poll(&fds, 1, 5000) ) { \
- fatal = 1; \
- result = 0; \
- YY_FATAL_ERROR("input in flex scanner failed timeout reading" ) \
- goto skip_reading; \
- } \
- if ( fds.revents & ( POLLOUT | POLLERR | POLLHUP ) ) { \
- fatal = 1; \
- result = 0; \
- goto skip_reading; \
- } \
- if ( (result = read( 0, (char *) buf, max_size )) < 0 ) { \
- YY_FATAL_ERROR( "input in flex scanner failed" ) \
- } \
- skip_reading: \
- } while (0)
-
- %}
-
- %%
-
- %%
-
- static void fatal_error(const char *msg)
- {
- printf("fatal error: %s\n", msg);
- fatal = 1;
- }
|
|