fifo non-blocked



  • Hallo,

    ich versuche gerade einen Fifo-Zugriff ungeblockt hinzubekommen, da mein Programm neben der fifo auch die serielle schnittstelle auslesen soll.

    so habe ichs probiert:

    //read from pipe:
    		//fp = fopen(FIFO_FILE, "r");
    		if((file=open(FIFO_FILE,O_RDONLY))==(-1))
    		{
    			perror("Failure 'open pipe'");
    		}
    		//set non-blocking
    		int flags;
    		if ((flags = fcntl(file, F_GETFL, 0))==-1) flags = 0;
    		fcntl(file, F_SETFL, flags | O_NONBLOCK);
    
    		//fgets(readbuf, 80, fp);
    		res=(length = read(file, readbuf, 80));
    		readbuf[length]='\0';
    		printf("Received string (Pipe): %s", readbuf);
    		//fclose(fp);
    		close(file);
    

    leider blockiert das read der FIFO immer noch :(, weis jemand, wie ich das umgehen kann?



  • Wäre es vielleicht eine Alternative, mit select zu arbeiten?



  • habe das select zwar bei dem beispiel für die serielle Schnittstelle gesehen, verstehe das aber nicht so ganz
    ich weis auch nicht, ob das mit fifos funktioniert, und wenn Daten von der fifo zur seriellen Schnittstelle geschickt werden...

    dachte mit dem non-blocked-flag ist einfacher 😉



  • gib das O_NONBLOCK flag mal direkt bei open an



  • damit scheint es nonblocked zu sein, aber es treten andere Fehler auf (Resource temporarily unavailable und force-close der sendenden konsole)

    ich glaube, ich muss doch auf select umsteigen

    Edit:
    habe jetzt mal select eingebaut, so wie ich es verstanden habe....

    /*
        serial.c - serielle Schnittstelle
    */
    
    //gcc -Wall serial.c -o serial
    # include <stdio.h>
    # include <unistd.h>
    # include <fcntl.h>
    # include <termios.h>
    # include <errno.h>
    
    //fifo
    #include <sys/stat.h>
    //#include <linux/stat.h>
    
    //# define TERM_DEVICE "/dev/ttyS0"   /* = COM1 */
    //# define TERM_DEVICE "/dev/ttyACM0"
    # define TERM_DEVICE "/dev/arduinoUNO"
    //# define TERM_SPEED B19200      /* Bit/Sek */
    # define TERM_SPEED B9600      /* Bit/Sek */
    
    #define FIFO_FILE       "/tmp/arduinoUNO"
    
    int main()
     {
      //vars for serial access
      int fd_serial;
      ssize_t length;
      char buffer[16];
      //vars for fifo
      //FILE *fp;
      int fd_fifo;
      char readbuf[80];
    	//for select (input switch)
    	fd_set input_fdset;
    
      /* Create the FIFO if it does not exist */
      umask(0);
      mknod(FIFO_FILE, S_IFIFO|0666, 0);  
    
      struct termios term_attr;
    
      if ((fd_serial = open(TERM_DEVICE, O_RDWR)) == -1)
       {
        perror("terminal: Can't open device " TERM_DEVICE);
        return(1);
       }
                /* RS232 konfigurieren */
      if (tcgetattr(fd_serial, &term_attr) != 0)
       {
        perror("terminal: tcgetattr() failed");
        return(1);
       }
      term_attr.c_cflag = TERM_SPEED | CS8 | CRTSCTS | CLOCAL;
      term_attr.c_iflag = 0;
      term_attr.c_oflag = OPOST | ONLCR;
      term_attr.c_lflag = 0;
      if (tcsetattr(fd_serial, TCSAFLUSH, &term_attr) != 0)
        perror("terminal: tcsetattr() failed");
    
    	//open fifo
    	if((fd_fifo=open(FIFO_FILE,O_RDONLY))==(-1))
    	{
    		perror("Failure 'open pipe'");
    	}
    
    	while (1)
    	{
        FD_ZERO(&input_fdset);
        FD_SET(fd_serial, &input_fdset);
        FD_SET(fd_fifo, &input_fdset);
        if (select(fd_serial+1, &input_fdset, NULL, NULL, NULL) == -1)
          perror("terminal: select() failed"); 
    
    		if (FD_ISSET(fd_serial, &input_fdset))
        { 
    			int res=(length = read(fd_serial, buffer, 16));
    			if (res == -1)
    			{
    				perror("terminal: read() failed");
    			} else
    				write(STDOUT_FILENO, buffer, length);
    
    			printf("[serial] res: %d, length:%d, errno: %d\n",res,length,errno);
    		}
    		if (FD_ISSET(fd_fifo, &input_fdset))
    		{
    			//read from pipe:
    			int res=(length = read(fd_fifo, readbuf, 80));
    			readbuf[length]='\0';
    			printf("Received string (Pipe): %s", readbuf);
    			printf("[FIFO] res: %d, length:%d, errno: %d\n",res,length,errno);
    			if (errno!=0) perror("[PIPE error]");
    			//write(fd, buffer, length); //write to serial fd
        }
    		sleep(1);//sleep for 1 second
    	}
      printf("Aborted.\n");
      //clean up
      close(fd_fifo);
      close(fd_serial);
      remove(FIFO_FILE);
    
      return(0);
     }
    

    hier muss ich aber erstmal was in die pipe schicken, bevor etwas von der seriellen schnittstelle angezeigt wird. dann wird die serielle Sst dauerhaft ausgelesen, aber die pipe nicht mehr 😞

    scheinbar habe ich das nicht so ganz richtig verstanden

    Gruß Frank



  • irgenwie bekomme ich das select nicht so ganz hin...es wird immer auf die fifo gewartet. wenn da mal was kam, wird auch die serielle ausgelesen und beides geht gleichzeitig. aber wie kann man dieses erste senden vermeiden?

    ich habe auch schon mit timeout probiert, aber auch ohne erfolg...das nonblocked-flag scheint zu funktionieren, aber es ist wahrscheinlich besser über select, oder?

    /*
        serial.c - serielle Schnittstelle
    */
    
    //gcc -Wall serial.c -o serial
    # include <stdio.h>
    # include <unistd.h>
    # include <fcntl.h>
    # include <termios.h>
    # include <errno.h>
    
    //fifo
    #include <sys/stat.h>
    //#include <linux/stat.h>
    
    //# define TERM_DEVICE "/dev/ttyS0"   /* = COM1 */
    //# define TERM_DEVICE "/dev/ttyACM0"
    # define TERM_DEVICE "/dev/arduinoUNO"
    //# define TERM_SPEED B19200      /* Bit/Sek */
    # define TERM_SPEED B9600      /* Bit/Sek */
    
    #define FIFO_FILE       "/tmp/arduinoUNO"
    #define true 1;
    #define false 0;
    /*
    int fileexists(const char *file)
    {
    	FILE *fp = fopen("file","r");
    	if( fp ) 
    	{
    		fclose(fp);
    		return true;
    	}else return false;
    }*/
    
    int fileexists(const char *file)
    {
    	if (access(file, F_OK) == 0)
    	{
      	return true;
    	}else return false;
    }
    
    int main()
     {
      //vars for serial access
      int fd_serial;
      ssize_t length_serial,length_fifo;
      char buffer_serial[16];
      //vars for fifo
      //FILE *fp;
      int fd_fifo;
      char buffer_fifo[80];
    	//for select (input switch)
    	fd_set input_fdset;
    
      /* Create the FIFO if it does not exist */
      if (!fileexists(FIFO_FILE))
      {
      umask(0);
      mknod(FIFO_FILE, S_IFIFO|0666, 0);  
      }
      struct termios term_attr;
    
      if ((fd_serial = open(TERM_DEVICE, O_RDWR /*| O_NONBLOCK*/)) == -1)
      {
        perror("terminal: Can't open device " TERM_DEVICE);
        return(1);
      }
                /* RS232 konfigurieren */
      if (tcgetattr(fd_serial, &term_attr) != 0)
      {
        perror("terminal: tcgetattr() failed");
        return(1);
      }
      term_attr.c_cflag = TERM_SPEED | CS8 | CRTSCTS | CLOCAL | CREAD;
      term_attr.c_iflag = 0;
      term_attr.c_oflag = OPOST;// | ONLCR;
      term_attr.c_lflag = 0;
      if (tcsetattr(fd_serial, TCSAFLUSH, &term_attr) != 0)
        perror("terminal: tcsetattr() failed");
    
    	//open fifo
    	if((fd_fifo=open(FIFO_FILE,O_RDONLY /*| O_NONBLOCK*/))==(-1))
    	{
    		perror("Failure 'open pipe'");
    	}
    
      int max;
      if (fd_serial>fd_fifo) max=fd_serial;else max=fd_fifo;
    
      //timeout für select
      struct timeval tv;
      tv.tv_sec = 0;
    	tv.tv_usec = 500;
    
    	while (1)
    	{
    
        FD_ZERO(&input_fdset);
        FD_SET(fd_serial, &input_fdset);
        FD_SET(fd_fifo, &input_fdset);
    
        if (select(max+1, &input_fdset, NULL, NULL, &tv) == -1)
          perror("terminal: select() failed"); 
    
        if (!fileexists(TERM_DEVICE))
        {
          perror("<Symlink removed!!!>");
          break;
        }
        int res_serial;
        if (FD_ISSET(fd_serial, &input_fdset)) 
        {
    		  errno=0;
    		  res_serial=(length_serial = read(fd_serial, buffer_serial, 16));
    			printf("[SERIAL] res: %d, length:%d, errno: %d\n",res_serial,length_serial,errno);
    			if (errno!=0) perror("[SERIAL error]");
    		}
    		int res_fifo;
    		if (FD_ISSET(fd_fifo, &input_fdset)) 
    		{
    			errno=0;
    			res_fifo=(length_fifo = read(fd_fifo, buffer_fifo, 80));
    			printf("[FIFO] res: %d, length:%d, errno: %d\n",res_fifo,length_fifo,errno);
    			if (errno!=0) perror("[PIPE error]");
    		}
    		if (res_serial>0)
        { 
    			buffer_serial[length_serial]='\0';
    			printf("[SERIAL] Received string: %s\n",buffer_serial);
    		}
    
    		if (res_fifo>0)
    		{
    			buffer_fifo[length_fifo]='\0';
    			printf("[PIPE] Received string: %s\n", buffer_fifo);
    			write(fd_serial, buffer_fifo, length_fifo); //write data from fifo to serial fd 
        }
    		sleep(1);//sleep for 1 second
    	}
      printf("Aborted.\n");
      //clean up
      close(fd_fifo);
      close(fd_serial);
      remove(FIFO_FILE);
    
      return(0);
     }
    

Anmelden zum Antworten