TTY 포트의 개행 문자에서 버퍼 플러시 방지

TTY 포트의 개행 문자에서 버퍼 플러시 방지

C를 사용하여 ttyACM 포트(cdc 복합 장치)에 512B를 쓰려고 합니다.
문제는 내 컴퓨터(Ubuntu 18.04)의 Linux 드라이버가 데이터를 청크로 전송하여 각 개행 문자(0x0A)에 대해 새 청크를 생성한다는 것입니다.
어떻게 예방할 수 있나요? cfmakeraw 함수를 사용해 보았지만 성공하지 못했습니다.
이것은 내 C 코드입니다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>

#define BUFFER_SIZE_ACM 512

int main() {
FILE *acm, *file;
unsigned char buffer[BUFFER_SIZE_ACM];

struct termios termios_p;

if((acm = fopen( "/dev/ttyACMX" ,"wb")) == NULL ) {
    printf("ERROR\n");
    return -1;
  }

  if((file = fopen( "/path/to/img/file" ,"rb")) == NULL ) {
    printf("ERROR\n");
    return -1;
  }

  cfmakeraw(&termios_p);
  tcsetattr( fileno(acm),TCSANOW , &termios_p);

  /*read data from file*/
  if(fread(buffer, 1 , BUFFER_SIZE_ACM, file) == NULL) {
      printf("ERROR\n");
      return -1;
    }
   /*write data*/
   fwrite(buffer, 1, BUFFER_SIZE_ACM, acm);
   fflush(acm);
   return 0;
}

파일에서 읽은 데이터에 0x0A 바이트가 없으면 512B 블록에 기록됩니다.
원치 않는 행동의 예:
512B 콘텐츠:

00000000  65 e4 9f 40 a2 37 4f b6  d2 d0 ae 99 ac e2 a4 22
00000010  8f 99 b4 45 4a 2e a4 d1  99 22 23 e7 e0 d2 06 3d
00000020  72 92 ce af 25 ea 7e 59  d7 56 01 0a be 4d 91 13
00000030  b0 4b 33 62 f1 84 62 30  56 a0 2e 2a fb 07 70 e7
00000040  9a c9 64 62 02 15 19 e5  a1 f7 85 53 8b 94 d7 e7
00000050  8e b8 7e 06 0c 9a 53 90  77 60 ff 9f e8 65 87 bd
00000060  ad 8a 2c 70 a5 12 f9 d5  44 48 7d 47 79 d0 83 63
00000070  96 f3 d0 67 f0 4f 49 63  4a 5e 6e 10 52 3f 09 c5
00000080  cd 9e 2c c2 aa 55 9e 31  ed 6d e5 a9 2a 1f 4c 72
00000090  d2 c8 96 02 3a 8a 4a 14  9b 26 af 99 78 fb 15 e3
000000a0  52 5f 53 d1 c0 21 59 a2  00 0c 6f 5b ae 15 f2 19
000000b0  dc d3 81 e3 11 ed 68 90  0a 18 a1 41 ad 60 b6 1f
000000c0  5b 54 98 93 04 1e 00 8e  e2 fc 37 9c e8 c2 99 76
000000d0  a5 8b c2 f7 43 60 7a 39  17 b3 8b 20 31 02 c4 0d
000000e0  86 2b 5c ac 4a 1f 4e b3  07 7b 63 5f 81 ad a5 b3
000000f0  ef 82 06 60 46 0a 24 7b  7f 75 f5 72 d4 b0 47 55
00000100  06 f9 5f c9 9e d2 d7 bf  6f 39 9f 0c 37 11 35 12
00000110  4a 2c c6 8b 5a a8 a9 a5  ce bb eb e9 66 81 57 66
00000120  e2 5c 0f 85 d9 de 59 1c  0e df 15 e7 08 30 5d ca
00000130  a7 33 7e 69 d4 39 67 18  d7 55 b3 e3 1e 9a 11 b9
00000140  1f 5e fe 98 34 fb f3 30  7f dd d9 29 dc 8c 16 50
00000150  1a 2b 48 00 5d 62 6e 10  e4 c5 1d 59 5d b4 6c 1a
00000160  25 32 5f 5f 9b 1b 8f d4  ce 94 9c e6 76 3d fc a6
00000170  45 2a dd 2f f2 8e 20 d0  69 66 1b 5e 9d f9 26 6c
00000180  bc 41 12 cb 10 2f f3 06  24 7a 2d 6d f2 8d 9b bd
00000190  6c a5 6a a5 9a 68 b1 be  7a e6 b9 12 aa 43 51 d6
000001a0  20 1c c3 0a 0b 33 4c 9a  e4 94 06 02 7e 79 f4 6c
000001b0  2b e4 26 65 71 b4 b9 1d  8a aa df 77 9a ae fd 05
000001c0  5f 9d 6e 18 d9 a0 ed d1  68 80 1d fe bc 11 89 21
000001d0  30 d9 ab e2 83 6a d4 59  12 43 13 08 2f 57 37 35
000001e0  cf 47 b3 7d 54 a1 a9 6d  a8 ce a9 c2 64 8e 4b c9
000001f0  0f e4 d6 f8 13 54 25 89  83 6f e7 cf b4 6f 87 bb
00000200

이는 5개의 서로 다른 블록으로 작성됩니다.

   65 E4 9F 40 A2 37 4F B6    D2 D0 AE 99 AC E2 A4 22 
   8F 99 B4 45 4A 2E A4 D1    99 22 23 E7 E0 D2 06 3D
   72 92 CE AF 25 EA 7E 59    D7 56 01 0A
   BE 4D 91 13 B0 4B 33 62    F1 84 62 30 56 A0 2E 2A 
   FB 07 70 E7 9A C9 64 62    02 15 19 E5 A1 F7 85 53
   8B 94 D7 E7 8E B8 7E 06    0C 9A 53 90 77 60 FF 9F
   E8 65 87 BD AD 8A 2C 70    A5 12 F9 D5 44 48 7D 47 
   79 D0 83 63 96 F3 D0 67    F0 4F 49 63 4A 5E 6E 10
   52 3F 09 C5 CD 9E 2C C2    AA 55 9E 31 ED 6D E5 A9
   2A 1F 4C 72 D2 C8 96 02    3A 8A 4A 14 9B 26 AF 99
   78 FB 15 E3 52 5F 53 D1    C0 21 59 A2 00 0C 6F 5B
   AE 15 F2 19 DC D3 81 E3    11 ED 68 90 0A
   18 A1 41 AD 60 B6 1F 5B    54 98 93 04 1E 00 8E E2
   FC 37 9C E8 C2 99 76 A5    8B C2 F7 43 60 7A 39 17
   B3 8B 20 31 02 C4 0D 86    2B 5C AC 4A 1F 4E B3 07
   7B 63 5F 81 AD A5 B3 EF    82 06 60 46 0A
   24 7B 7F 75 F5 72 D4 B0    47 55 06 F9 5F C9 9E D2
   D7 BF 6F 39 9F 0C 37 11    35 12 4A 2C C6 8B 5A A8
   A9 A5 CE BB EB E9 66 81    57 66 E2 5C 0F 85 D9 DE
   59 1C 0E DF 15 E7 08 30    5D CA A7 33 7E 69 D4 39
   67 18 D7 55 B3 E3 1E 9A    11 B9 1F 5E FE 98 34 FB 
   F3 30 7F DD D9 29 DC 8C    16 50 1A 2B 48 00 5D 62 
   6E 10 E4 C5 1D 59 5D B4    6C 1A 25 32 5F 5F 9B 1B
   8F D4 CE 94 9C E6 76 3D    FC A6 45 2A DD 2F F2 8E
   20 D0 69 66 1B 5E 9D F9    26 6C BC 41 12 CB 10 2F
   F3 06 24 7A 2D 6D F2 8D    9B BD 6C A5 6A A5 9A 68
   B1 BE 7A E6 B9 12 AA 43    51 D6 20 1C C3 0A
   0B 33 4C 9A E4 94 06 02    7E 79 F4 6C 2B E4 26 65
   71 B4 B9 1D 8A AA DF 77    9A AE FD 05 5F 9D 6E 18 
   D9 A0 ED D1 68 80 1D FE    BC 11 89 21 30 D9 AB E2 
   83 6A D4 59 12 43 13 08    2F 57 37 35 CF 47 B3 7D 
   54 A1 A9 6D A8 CE A9 C2    64 8E 4B C9 0F E4 D6 F8 
   13 54 25 89 83 6F E7 CF    B4 6F 87 BB

답변1

stdio 대신 버퍼링되지 않은 등을 사용해 write(2)보세요 . 기본적으로 stdio는 라인 버퍼를 tty에 씁니다.open(2)fwrite(3)

또는 정말로 stdio를 사용해야 한다면 unbuffered로 만드세요 setvbuf(fileno(acm), 0, _IONBUF, 0).

tcgetattr(3)그런데: 먼저 다음을 사용하여 실제 termios cfmakeraw(3)매개변수를 가져와야 합니다.그 다음에로 설정 tcsetattr(3)하고 이 모든 함수의 반환 값을 확인하세요. tcsetattr(3)(포함된 스택의 쓰레기로 인해 termios_p) 실패할 가능성이 높지만 이를 알 수 있는 방법이 없습니다.

또한 tcsetattr(3)실행할 수 있으면 성공할 것입니다.어느(아니요모두), 따라서 tcgetattr(3)다른 termios 구조로 다시 호출하고 그 내용을 사용된 것과 비교 해야 합니다 tcsetattr(3).

관련 정보