альтернатива printf при использовании «define _GNU_SOURCE» - PullRequest
0 голосов
/ 30 июня 2019

После прочтения https://www.quora.com/How-can-I-bypass-the-OS-buffering-during-I-O-in-Linux Я хочу попытаться получить доступ к данным на последовательном порту с помощью опции O_DIRECT, но единственный способ, которым я могу это сделать, - добавить определение GNU_SOURCE, но когда я попытался выполнитьпрограмма, на экране ничего не печатается.

Если я удаляю "#define _GNU_SOURCE" и компилирую, то система выдает мне сообщение об ошибке O_DIRECT.

Если я уберу определение и флаг O_DIRECT, то неправильные (возможно устаревшие) данные всегда читаются, но данные выводятся на экран.

Я все еще хочу использовать флаг O_DIRECTи я могу видеть данные, поэтому мне кажется, что мне нужна альтернативная команда для printf и друзей, но я не знаю, как продолжить.

Я прикрепил следующий код:

  #define _GNU_SOURCE

  #include <stdio.h>
  #include <stdlib.h>
  #include <fcntl.h>
  #include <time.h>
  #include <unistd.h>
  #include <termios.h>

  #define TIMEOUT 5


  int main(){
    char inb[3];  //our byte buffer
    int nread=0;  //number bytes read from port
    int n;        //counter
    int iosz=128; //Lets get 128 bytes
    int fd=open("/dev/ttyS0", O_NOCTTY | O_RDONLY | O_SYNC | O_DIRECT); //Open port
    tcflush(fd,TCIOFLUSH);
    for(n=0;n<iosz;n++){
      int s=time(NULL); //Start timer for 5 seconds
      while (time(NULL)-s < TIMEOUT && nread < 1){
        inb[0]='A'; //Fill buffer with bad data
        inb[1]='B';
        inb[2]='C';
        nread=read(fd,(char*)inb,1); //Read ONE byte
        tcflush(fd,TCIOFLUSH);
        if (nread < 0 || time(NULL)-s >= TIMEOUT){
            close(fd); //Exit if read error or timeout
            return -1;
        }
      }
      printf("%x:%d ",inb[0] & 0xFF,nread); //Print byte as we receive it
    }
    close(fd); //program ends so close and exit
    printf("\n"); //Print byte as we receive it
    return 0;
  }

1 Ответ

0 голосов
/ 01 июля 2019

Прежде всего, я не специалист по этой теме, просто мне интересно, так что примите этот ответ с щепоткой соли.

Я не знаю, было ли когда-нибудь возможным то, что вы пытаетесь сделать здесь (если я не смотрю на это неправильно, кажется, что это обход ядра и чтение непосредственно из порта в пространство пользователя) (вы можете найти несколько примеров, например , этот , но я не смог найти ничего должным образом документированного), но с последними ядрами вы должны получить ошибку при запуске кода, но вы ее не поймаете.

Если вы добавите эти строки после объявления вашего порта:

...
int fd=open("/dev/ttyS0", O_NOCTTY | O_RDONLY | O_SYNC | O_DIRECT );    
if (fd == -1) {
    fprintf(stderr, "Error %d opening SERIALPORT : %s\n", errno, strerror(errno));
    return 1;
    }
tcflush(fd,TCIOFLUSH);
....

Когда вы попытаетесь запустить, вы получите: Error 22 opening SERIALPORT : Invalid argument

В моем скромном и ограниченном понимании вы сможете получить тот же эффект, изменив настройки в termios на raw, что-то вроде этого должно сделать:

struct termios t;
tcgetattr(fd, &t);            /* get current port state */
cfmakeraw(&t);                /* set port state to raw  */
tcsetattr(fd, TCSAFLUSH, &t); /* set updated port state */

Есть много хороших источников для termios, но единственное место, где я могу найти, что также относится к O_DIRECT (для файлов), это этот .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...