Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

198
Visualizações
Why is my buffer length ignored?

I'm developing a receiver for a small hardware project. I'm working on a small board that uses UART to transfer data.
The receiver code is shown in full below, I'll explain the problematic bits separately shortly.

#define TTY "/dev/ttys002"

#include <stdio.h>
#include <string.h>
#include <unistd.h> //Unix standard functions
#include <fcntl.h> //File controls
#include <errno.h> //Error numbers
#include <assert.h>
#include <termios.h> //Posix terminal

int open_port(const char * tty) {
    int fd;
    fd = open(tty, (O_RDWR | O_NOCTTY | O_NDELAY));
    assert("__failed to open port__" && fd != -1);
    //Block until read
    fcntl(fd, F_SETFL, 0);
    return fd;
}

void configure_port(int fd) {
    struct termios options;
    //Get current options
    tcgetattr(fd, &options);

    //9600 Baud
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);

    //Receive & local mode
    options.c_cflag |= (CLOCAL | CREAD);

    //Raw output
    options.c_oflag &= ~OPOST;

    //No hardware flow control
    options.c_cflag &= ~CRTSCTS;

    //No parity, 1 stop bit
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;

    //8 data bits
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    //Write options back, set them immediately
    tcsetattr(fd, TCSANOW, &options);
}

int main(int argc, const char * argv[]) {
    int fd = open_port(TTY);
    const size_t count = 8;
    char buf[count + 1];
    ssize_t n;
    configure_port(fd);
    while (1) {
        n = read(fd, buf, count);
        buf[count] = '\0';
        if (n > 0) {
            printf("%s\n", buf);
        }
    }
    return 0;
}

Since I don't have my hardware at hand currently, I decided to test my receiver over a regular tty (#define TTY "/dev/ttys002"). To test it, I simply compiled and ran the above code and then opened a separate terminal and:

echo "text" >> /dev/ttys002

All this works fine and well and I get all the data I'm echoing into the tty.

However, the problem arises when I input a long message into the tty:

echo "this is a longer test message" >> /dev/ttys002

I receive the whole message as a single string in my program output. Why is this so? I would have expected the text to be split up into blocks of 8 chars (const size_t count = 8;).

If it's of importance, I'm using this guide as my go-to for the configuration.

Edit: Please see the comments for further discussion on the issue.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

IMHO, your message is split into blocks of eight chars : n = read(fd, buf, count); cannot give more than count bytes at a time.

But as you do not configure the tty line in RAW mode, is is still in line buffered mode. So the underlying driver blocks the first read until it has a full line terminated with a \n (or exceeding the buffer capacity).

Then the read returns with the first 8 bytes, and next reads immediately return with 8 bytes too since data is available in driver buffer.

You should look at non canonical mode in man termios, if you want to use the raw input mode :

options.c_cflags &= ~ICANON;
/* optionally if defaults are not appropriates */
options.c_cc[VMIN] = vmin; /* default is 1 */
options.c_cc[VTIME] = vtime; /* default is 0 */

But anyway, you read chararacters and never add the terminating null, so buf has no reason to be null terminated. You should only print the number of characters actually read:

const size_t count = 8;
char buf[count];
ssize_t n;
configure_port(fd);
while (1) {
    n = read(fd, buf, count);
    if (n > 0) {
        printf("%.*s\n", n, buf); /* only print the n characters */
    }
}
over 4 years ago · Santiago Trujillo Relatório

0

It seems that your problem has the same name that this site :)

You're allocating 8 bytes of data on the stack for your buf variable. Then, in read function, you're writing "this is a longer test message" string, which length is much more than 8 bytes. When you're using printf function with "%s", printf will stop printing when it will reach a null character(\0) because it expects your string to be null-terminated. In your case, you should make a check whether your buf variable is null-terminated. If it's not, you should make the last byte of the bufto be a null character

over 4 years ago · Santiago Trujillo Relatório

0

What you are looking for is a pseudo tty (PTY).

A simple way to create a PTY is to use socat(1) like so:

socat pty,link=/tmp/testpty stdio

This will create a PTY and attach the current terminal's stdio to its master side. Whatever data you put in here will be sent to the slave side of the PTY.

Now connect to the slave side from your program and it should work as you expect:

#define TTY "/tmp/testpty"
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda