Linux 사용자 공간 · POSIX termios

직렬 통신 코드는 읽은 길이부터 확인합니다

termios 설정의 수명과 read/poll 결과를 구분하는 C 예제입니다.

tcgetattr가 성공한 뒤에 구조체를 사용합니다

tcgetattr가 실패하면 출력 구조체에 올바른 설정이 들어 있다고 볼 수 없습니다. 원래 설정을 보관하고 사본을 수정한 다음 tcsetattr로 적용합니다. 직렬 장치의 baud rate, 데이터 비트, parity, stop bit, 흐름 제어는 상대 장치와 맞춰야 합니다.

struct termios saved, next;
if (tcgetattr(fd, &saved) == -1) {
    perror("tcgetattr");
    return -1;
}
next = saved;
next.c_lflag &= ~(ICANON | ECHO);
next.c_cc[VMIN] = 1;
next.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &next) == -1) {
    perror("tcsetattr");
    return -1;
}

이 부분 코드는 비정규 입력과 echo만 바꿉니다. 완전한 바이너리 직렬 설정은 아닙니다. tcsetattr는 일부 설정만 적용되어도 성공할 수 있으므로 중요한 설정은 다시 읽어 확인합니다. 종료 때 saved로 복원하며 복원 실패도 확인합니다.

read는 문자열을 만들어 주지 않습니다

#include <errno.h>
#include <unistd.h>

ssize_t read_retry(int fd, void *buffer, size_t capacity)
{
    ssize_t n;
    do {
        n = read(fd, buffer, capacity);
    } while (n < 0 && errno == EINTR);
    return n;
}

양수이면 그 바이트 수만 유효합니다. %s로 출력하려면 별도의 NUL 종료 공간과 텍스트라는 조건이 필요합니다. 바이너리는 NUL을 포함할 수 있으므로 길이를 기준으로 처리합니다. 음수이면 errno를 확인하며, EAGAIN은 비차단 입력에서 지금 읽을 데이터가 없을 수 있다는 뜻입니다.

TTY에서 0 반환의 뜻은 설정에 따라 다릅니다. 비정규 모드의 VMIN=0에서는 데이터가 없거나 VTIME이 만료되어도 0이 될 수 있습니다. 모든 0을 장치 연결 종료로 처리하면 안 됩니다. VTIME의 단위는 0.1초이며 VMIN과 조합한 동작을 확인해야 합니다.

poll의 반환 개수와 revents를 따로 봅니다

결과처리
poll = -1errno를 확인합니다. EINTR이면 종료 요청과 재시도 정책을 판단합니다.
poll = 0지정한 대기 시간이 지났습니다.
poll > 0revents가 설정된 항목의 개수입니다. 각 항목의 비트를 검사합니다.
POLLIN과 POLLHUP동시에 올 수 있습니다. 남은 데이터를 읽을지와 종료 처리를 함께 설계합니다.
POLLERR / POLLNVAL오류와 잘못된 fd입니다. 단순한 데이터 도착으로 처리하지 않습니다.
입력을 읽고 사용하는 순서
  1. 준비 상태 확인poll 결과와 revents를 검사합니다.
  2. 실제 read 결과 확인준비 상태 이후에도 경쟁이나 오류가 생길 수 있습니다.
  3. n바이트만 처리프로토콜의 프레임이 완성됐는지 별도로 판단합니다.

한 번의 poll이나 read가 메시지 하나의 완성을 보장하지 않습니다. 상자는 처리 순서입니다.

쓰기와 오류 보고도 길이와 반환 규약을 따릅니다

write가 요청한 길이보다 적게 쓸 수 있으므로 남은 범위를 처리해야 합니다. 상대 장치가 메시지를 처리했다는 확인은 write 성공과 별개입니다. close만으로 다른 프로세스에도 공유되는 터미널 설정이 이전 상태로 돌아온다고 가정하지 않습니다.

perror는 현재 errno를 설명하므로 실패 직후 사용하거나 errno를 보존합니다. pthread 함수들은 보통 오류 번호를 반환하므로 pthread_create의 실패를 perror로 설명하면 다른 오류를 출력할 수 있습니다. 반환값을 strerror에 넘기는 등 API의 오류 규약에 맞춰야 합니다.

확인한 문서

Linux 사용자 공간 · POSIX termios