C write () does not send data until close (fd) is called

So, I have this test code to send "HELLO" via a USB serial port:

int fd; struct termios tty; if((fd = open("/dev/ttyUSB0", O_WRONLY|O_NONBLOCK|O_NOCTTY)) == -1){ err(1, "Cannot open write on /dev/ttyUSB0"); } tcgetattr(fd, &tty); tty.c_iflag = 0; tty.c_oflag = 0; tty.c_lflag = 0; tty.c_cflag = 0; tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] = 0; cfsetospeed(&tty, B19200); cfsetispeed(&tty, B19200); tty.c_cflag |= CREAD|CRTSCTS|HUPCL|CS8; tcsetattr(fd, TCSANOW, &tty); printf("Write: %i\n", write(fd, "HELLO", 5)); sleep(5); if(close(fd) != 0){ warn("Could not close write fd"); } 

The program runs fine and "HELLO" is sent, but there is one problem. "HELLO" does not seem to be sent when the write () function is called, but rather when the file descriptor is closed. I added the sleep line (5) above to test this theory and, of course, "HELLO" is sent 5 seconds after the program is executed. How can I get a "HELLO" message right after the write () command instead of the close () function?

+7
c linux tty serial-port
source share
8 answers

On the write() page:

A successful return from write () does not guarantee that the data was written to disk. In fact, with some implementation errors, it does not even guarantee that space has been reserved for data. The only way to make sure that you call fsync (2) after you finish writing all your data.

You need to call fsync() on the file descriptor to make sure that the data is actually committed.

+5
source share

The device is a tty device, so fsync will not help, maybe not fflush.

By default, the device operates in canonical mode, which means that the data is packed in units of rows. You will probably find that adding a cr / lf pair to your data will send it.

You need to make sure that canonical mode is turned off. In addition, the R-answer will be useful.

http://en.wikibooks.org/wiki/Serial_Programming/termios

+7
source share

Output ports are often buffered, so there is a greater or lesser gap between what you write to the output stream and what is actually sent to disk, a string, or something else. This is usually for effectiveness.

See fflush (3) for a buffer to be bound to the output.

You can also open the output descriptor so that it is not buffered, but using fflush to say this, I ended up probably better.

+2
source share

First of all, I don’t know why you first set all termios fields to 0, and then later, without any changes to this 0, which precedes it, decide to set the usual rs232 flags to cflag. (instead of doing it without a direct OR, where you now set it to 0).

what you might like is - instead of setting all these flags - only the cfmakeraw () field of the termios field.

also sync (); without any parameters (NOT fsync !;), it seems to send all the pending output to ALL filedescriptors, not just block devices. also tcp sockets and rs232 ..

and also open () has the O_SYNC option (O_SYNC and O_ASYNC confuse the names, but have nothing to do with the synchronized serial line protocol, it immediately writes (), and the other generates a signal to capture when the input becomes available (sort of like irq based rs232 on dos;)

setting O_SYNC in open () may already solve your problem.

also "reading data at the other end" ... there are things called "LEDs" and "resistors" that you can simply connect to TXD and view the data;) there are also things called "rs232 breakthrough" field "or area visibility, which can make it visible - directly) - is much easier than "guessing" which side is not behaving correctly.

WARNING: NOT A TEST CODE. it compiles. but I have all my ttyUSB0 cables in another building. but I think your main problem is O_SYNC anyway. setting all termios crap to 0 is pretty much like cfmakeraw () ... also why install CREAD if you open it for writing only? (why open it only for writing, and not read in any case?), as well as writing only, you will not need to be afraid that he will become the manager of tty (O_NOCTTY;), so if you write, this is not required ..

just noticed that% i (same for% dbtw) formatter also triggers a ssize_t type mismatch warning return value write (), so it is different from (int)

 #include<termios.h> #include<stdio.h> #include<unistd.h> #include<fcntl.h> void main(){ int fd; struct termios tty; fd=-1; while(fd<0){fd=open("/dev/ttyUSB0",O_WRONLY|O_NONBLOCK|O_NOCTTY|O_SYNC);sleep(1);}; cfmakeraw(&tty); tty.c_cflag=CREAD|CRTSCTS|HUPCL|CS8; cfsetospeed(&tty,B19200); cfsetispeed(&tty,B19200); tcsetattr(fd,TCSANOW,&tty); printf("Write: %i\n",(int)write(fd,"HELLO",5)); sync();//if all else fails, also try without, O_SYNC should already fix that. close(fd); }; 
+2
source share

the buffer is not flushed. fflush.

0
source share

See this question . BASically, you need to clear the file so that IO runs whenever you want.

0
source share

Try to do

 fflush( NULL ); 

after write() . Perhaps there is an internal buffer that is not flushed.

0
source share

Change this line:

 tty.c_cc[VMIN] = 0; 

:

 tty.c_cc[VMIN] = 1; 
0
source share

All Articles