//termios.h
구조
typedef unsigned long tcflag_t;
typedef unsigned char cc_t;
typedef unsigned long speed_t;
struct termios {
tcflag_t c_iflag; /* input flags */
tcflag_t c_oflag; /* output flags */
tcflag_t c_cflag; /* control flags */
tcflag_t c_lflag; /* local flags */
cc_t c_cc[NCCS]; /* control chars */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
함수
__BEGIN_DECLS
speed_t cfgetispeed(const struct termios *);
speed_t cfgetospeed(const struct termios *);
int cfsetispeed(struct termios *, speed_t);
int cfsetospeed(struct termios *, speed_t);
int tcgetattr(int, struct termios *);
int tcsetattr(int, int, const struct termios *);
int tcdrain(int) __DARWIN_ALIAS_C(tcdrain);
int tcflow(int, int);
int tcflush(int, int);
int tcsendbreak(int, int);
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
void cfmakeraw(struct termios *);
int cfsetspeed(struct termios *, speed_t);
#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
__END_DECLS
1. 터미널 정보 제어
# 터미널 가져오기
int tcgetattr(int fildes, struct termios *termios_p);
파일의 터미널의 정보를 가져온다
# 터미널 세팅 하기
int tcsetattr(int fildes, int optional_actions, const struct termios *termios_p);
파일에 터미널 정보를 세팅한다
/*
* Commands passed to tcsetattr() for setting the termios structure.
*/
#define TCSANOW 0 /* make change immediate */
#define TCSADRAIN 1 /* drain output, then change */
#define TCSAFLUSH 2 /* drain output, flush input */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define TCSASOFT 0x10 /* flag - don't alter h.w. state */
#endif
세팅시 옵션값이다
TCSANOW = 변경 사항을 바로 적용
TCSADRAIN = 출력에 있는 버퍼를 기다린다 그후 적용한다
TCSAFLUSH = 버퍼를 지우고 적용한다
TCSASOFT = This is a flag bit that you can add to any of the above alternatives. Its meaning is to inhibit alteration of the state of the terminal hardware. It is a BSD extension; it is only supported on BSD systems and GNU/Hurd systems. (추가가 가능하고 터미널 하드웨어상 변경을 막는 기능같다)
2. 터미널 속도 제어
# input 터미널 속도 가져오기 (c_ispeed를 가져온다)
speed_t cfgetispeed(const struct termios *);
# input 터미널 속도 세팅하기 (c_ispeed 가 변경된다)
int cfsetispeed(struct termios *, speed_t);
# output 터미널 속도 가져오기 (c_ospeed를 가져온다)
speed_t cfgetospeed(const struct termios *);
# output 터미널 속도 세팅하기 (c_ospeed를 변경된다)
int cfsetospeed(struct termios *, speed_t);
3. 전송
# 기록된 출력 대기
int tcdrain(int) __DARWIN_ALIAS_C(tcdrain);
# 기록 혹은 출력을 일시 정지함 (action 옵션값 확인);
int tcflow(int, int);
tcflow(int fildes, int action);
tcflow :: action // options;
#define TCIFLUSH 1
#define TCOFLUSH 2
#define TCIOFLUSH 3
#define TCOOFF 1
#define TCOON 2
#define TCIOFF 3
#define TCION 4
# 기록 혹은 출력에 버퍼를 지움 (action 옵션값 확인);
int tcflush(int, int);
//https://www.thegeekdiary.com/serial-port-programming-tcflush-tciflushtcoflush-example/
int tcflush(int fildes, int action);
#define TCIFLUSH 1
#define TCOFLUSH 2
#define TCIOFLUSH 3
#define TCOOFF 1
#define TCOON 2
#define TCIOFF 3
#define TCION 4
# 터미널에 일정한 시간동안(duration) 0을 전송한다
int tcsendbreak(int, int);
//int tcsendbreak(int fildes, int duration);
//https://pubs.opengroup.org/onlinepubs/009696699/functions/tcsendbreak.html
#define _POSIX_SOURCE
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
main() {
if (tcsendbreak(STDIN_FILENO, 100) != 0)
perror("tcsendbreak() error");
else
puts("break sent");
}
내용 보기
//terminal_print.c
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define FALSE 0
#define TRUE 1
//volatile int STOP=FALSE;
int main(void)
{
int fd,c, res;
struct termios oldtio;
struct termios newtio;
char buf[255];
char *modemdevice;
modemdevice = ttyname(STDIN_FILENO);
printf("modemdevice L %s \n", modemdevice);
fd = open(modemdevice, O_RDWR | O_NOCTTY );
if (fd <0) {perror(modemdevice); exit(-1); }
tcgetattr(fd, &oldtio);
printf("================ struct termios ================\n");
printf("oldtio.c_iflag\t%lu\n", oldtio.c_iflag);
printf("oldtio.c_oflag\t%lu\n", oldtio.c_oflag);
printf("oldtio.c_cflag\t%lu\n", oldtio.c_cflag);
printf("oldtio.c_lflag\t%lu\n", oldtio.c_lflag);
printf("oldtio.c_ispeed\t%lu\n", oldtio.c_ispeed);
printf("oldtio.c_ospeed\t%lu\n", oldtio.c_ospeed);
printf("\n============== c_cc ==================\n");
printf("oldtio.c_cc[VEOF]\t%d\n", oldtio.c_cc[VEOF] );
printf("oldtio.c_cc[VEOL]\t%d\n", oldtio.c_cc[VEOL] );
printf("oldtio.c_cc[VEOL2]\t%d\n", oldtio.c_cc[VEOL2] );
printf("oldtio.c_cc[VERASE]\t%d\n", oldtio.c_cc[VERASE] );
printf("oldtio.c_cc[VWERASE]\t%d\n", oldtio.c_cc[VWERASE] );
printf("oldtio.c_cc[VKILL]\t%d\n", oldtio.c_cc[VKILL] );
printf("oldtio.c_cc[VREPRINT]\t%d\n", oldtio.c_cc[VREPRINT] );
printf("oldtio.c_cc[VINTR]\t%d\n", oldtio.c_cc[VINTR] );
printf("oldtio.c_cc[VQUIT]\t%d\n", oldtio.c_cc[VQUIT] );
printf("oldtio.c_cc[VSUSP]\t%d\n", oldtio.c_cc[VSUSP] );
printf("oldtio.c_cc[VDSUSP]\t%d\n", oldtio.c_cc[VDSUSP] );
printf("oldtio.c_cc[VSTART]\t%d\n", oldtio.c_cc[VSTART] );
printf("oldtio.c_cc[VSTOP]\t%d\n", oldtio.c_cc[VSTOP] );
printf("oldtio.c_cc[VLNEXT]\t%d\n", oldtio.c_cc[VLNEXT] );
printf("oldtio.c_cc[VDISCARD]\t%d\n", oldtio.c_cc[VDISCARD] );
printf("oldtio.c_cc[VMIN]\t%d\n", oldtio.c_cc[VMIN] );
printf("oldtio.c_cc[VTIME]\t%d\n", oldtio.c_cc[VTIME] );
printf("oldtio.c_cc[VSTATUS]\t%d\n", oldtio.c_cc[VSTATUS] );
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VEOL] = 255; /* '\0 ' */
newtio.c_cc[VEOL2] = 255; /* '\0 ' */
newtio.c_cc[VERASE] = 127; /* Ctrl-? del('\177') */
newtio.c_cc[VWERASE] = 23; /* Ctrl-W */
newtio.c_cc[VKILL] = 21; /* Ctrl-U */
newtio.c_cc[VREPRINT] = 18; /* Ctrl-R */
newtio.c_cc[VINTR] = 3; /* Ctrl-C */
newtio.c_cc[VQUIT] = 28; /* Ctrl-\\ */
newtio.c_cc[VSUSP] = 26; /* Ctrl-Z */
newtio.c_cc[VDSUSP] = 25; /* Ctrl-Y */
newtio.c_cc[VSTART] = 17; /* Ctrl-Q */
newtio.c_cc[VSTOP] = 19; /* Ctrl-S */
newtio.c_cc[VLNEXT] = 22; /* Ctrl-V */
newtio.c_cc[VDISCARD] = 15; /* Ctrl-O */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VSTATUS] = 20; /* Ctrl-T */
/*
VEOF EOF ^D
VEOL EOL _POSIX_VDISABLE
VEOL2 EOL2 _POSIX_VDISABLE
VERASE ERASE ^? ‘\177’
VWERASE WERASE ^W
VKILL KILL ^U
VREPRINT REPRINT ^R
VINTR INTR ^C
VQUIT QUIT ^\\ ‘\34’
VSUSP SUSP ^Z
VDSUSP DSUSP ^Y
VSTART START ^Q
VSTOP STOP ^S
VLNEXT LNEXT ^V
VDISCARD DISCARD ^O
VMIN --- 1
VTIME --- 0
VSTATUS STATUS ^T
*/
close(fd);
}
bash 터미널 설정 보기
bash-3.2$ ./a.out
modemdevice L /dev/ttys000
================ struct termios ================
oldtio.c_iflag 27394
oldtio.c_oflag 3
oldtio.c_cflag 19200
oldtio.c_lflag 536872399
oldtio.c_ispeed 38400
oldtio.c_ospeed 38400
============== c_cc ==================
oldtio.c_cc[VEOF] 4
oldtio.c_cc[VEOL] 255
oldtio.c_cc[VEOL2] 255
oldtio.c_cc[VERASE] 127
oldtio.c_cc[VWERASE] 23
oldtio.c_cc[VKILL] 21
oldtio.c_cc[VREPRINT] 18
oldtio.c_cc[VINTR] 3
oldtio.c_cc[VQUIT] 28
oldtio.c_cc[VSUSP] 26
oldtio.c_cc[VDSUSP] 25
oldtio.c_cc[VSTART] 17
oldtio.c_cc[VSTOP] 19
oldtio.c_cc[VLNEXT] 22
oldtio.c_cc[VDISCARD] 15
oldtio.c_cc[VMIN] 1
oldtio.c_cc[VTIME] 0
oldtio.c_cc[VSTATUS] 20
1. c_iflag
input 설정
//https://www.gnu.org/software/libc/manual/html_node/Input-Modes.html
// https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=choi125496&logNo=130034222760
/*
* Input flags - software input processing
*/
#define IGNBRK 0x00000001 /* ignore BREAK condition */
#define BRKINT 0x00000002 /* map BREAK to SIGINTR */
#define IGNPAR 0x00000004 /* ignore (discard) parity errors */
#define PARMRK 0x00000008 /* mark parity and framing errors */
#define INPCK 0x00000010 /* enable checking of parity errors */
#define ISTRIP 0x00000020 /* strip 8th bit off chars */
#define INLCR 0x00000040 /* map NL into CR */
#define IGNCR 0x00000080 /* ignore CR */
#define ICRNL 0x00000100 /* map CR to NL (ala CRMOD) */
#define IXON 0x00000200 /* enable output flow control */
#define IXOFF 0x00000400 /* enable input flow control */
#define IXANY 0x00000800 /* any char will restart after stop */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define IMAXBEL 0x00002000 /* ring bell on input queue full */
#define IUTF8 0x00004000 /* maintain state for UTF-8 VERASE */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
IGNBRK = 직렬 통신의 beark 를 무시한다 break 는 연속적인 0( tcsendbreak() 함수 사용하엿을경우 )로 정의한다. 즉 tcsendbreak() 함수를 받을지 말지 설정
BRKINT =
If this bit is set and IGNBRK is not set, a break condition clears the terminal input and output queues and raises a SIGINT signal for the foreground process group associated with the terminal.
If neither BRKINT nor IGNBRK are set, a break condition is passed to the application as a single '\0' character if PARMRK is not set, or otherwise as a three-character sequence '\377', '\0', '\0'.
(IGNBRK 가 설정되있지 않을경우 터미널의 queues을 지우고 SIGINT(시그널)로 대신 받는다는 뜻 같음)
#include <sys/signal.h>
#define SIGINT 2 /* interrupt */
// 2 SIGINT terminate process interrupt program
IGNPAR = parity_bit(전송 오류를 확인하는 비트) 에러를 무시한다.
// Parity_bit info
// https://en.wikipedia.org/wiki/Parity_bit
// https://stackoverflow.com/questions/20132316/parmrk-termios-behavior-not-working-on-linux
PARMRK = parity_bit 오류가 있는 바이트를 마킹하여 전송
INPCK = parity_bit 오류를 확인(ISTRIP 에대한 검사)
ISTRIP = parity_bit 설정(사용시 8비트중 1비트를 parity_bit로 사용 데이터를 7 비트씩 사용하게됨)
INLCR = '\n' 으로 입력된 값을 '\r'로 변경하여 전달
IGNCR = '\r'(enter키 누르면 생성)으로 입력된 값을 추가하지 않는다.(enter키가 암것도 안한다)
ICRNL = (IGNCR)가 설정되지 않았으면 '\r' 가 '\n' 으로 전달된다. (INLCR와 반대)
IXON = 출력에 대한 시작과 멈춤을 제어할 수 있다 VSTART VSTOP
//https://www.ibm.com/docs/en/aix/7.3?topic=files-termiosh-file
VSTART
Indexes the START special character (Ctrl-q), which is recognized on input if the IXON flag is set, and generated on output if the IXOFF flag is set. The START character can be used to resume output that has been suspended by a STOP character. If the IXON flag is set, the START character is discarded when processed. While output is not suspended, START characters are ignored and not read. VSTRT is an alias for VSTART.
VSTOP
Indexes the STOP special character (Ctrl-s), which is recognized on input if the IXON flag is set, and generated on output if the IXOFF flag is set. The STOP character can be used to with terminals to prevent output from disappearing before it can be read. If the IXON flag is set, the STOP character is discarded when processed. While output is suspended, STOP characters are ignored and not read.
IXOFF = 입력에 대한 시작과 멈춤을 제어할 수 있다 VSTART VSTOP
IXANY = start가 아닌 다른 문자가 와도 전송 시작
IMAXBEL = 입력큐가 max 값이 되면 소리가남 (아스키코드 0x07 출력됨)
IUTF8 = maintain state for UTF-8 VERASE (유니코드 상태유지)
2. c_oflag
output 설정
/*
* Output flags - software output processing
*/
#define OPOST 0x00000001 /* enable following output processing */
#define ONLCR 0x00000002 /* map NL to CR-NL (ala CRMOD) */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define OXTABS 0x00000004 /* expand tabs to spaces */
#define ONOEOT 0x00000008 /* discard EOT's (^D) on output) */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
OPOST = 출력시 '\n'같은거 변경하여 전송
ONLCR = '\n'을 '\r''\n' 으로 변경 전송
OXTABS = 텝을 공백으로 변환
ONOEOT = 0x04 문자 무시 (아스키코드)
3. c_cflag
컨트롤러 설정(터미널에 대한 상태 설정)
/*
* Control flags - hardware control of terminal
*/
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define CIGNORE 0x00000001 /* ignore control flags */
#endif
#define CSIZE 0x00000300 /* character size mask */
#define CS5 0x00000000 /* 5 bits (pseudo) */
#define CS6 0x00000100 /* 6 bits */
#define CS7 0x00000200 /* 7 bits */
#define CS8 0x00000300 /* 8 bits */
#define CSTOPB 0x00000400 /* send 2 stop bits */
#define CREAD 0x00000800 /* enable receiver */
#define PARENB 0x00001000 /* parity enable */
#define PARODD 0x00002000 /* odd parity, else even */
#define HUPCL 0x00004000 /* hang up on last close */
#define CLOCAL 0x00008000 /* ignore modem status lines */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define CCTS_OFLOW 0x00010000 /* CTS flow control of output */
#define CRTSCTS (CCTS_OFLOW | CRTS_IFLOW)
#define CRTS_IFLOW 0x00020000 /* RTS flow control of input */
#define CDTR_IFLOW 0x00040000 /* DTR flow control of input */
#define CDSR_OFLOW 0x00080000 /* DSR flow control of output */
#define CCAR_OFLOW 0x00100000 /* DCD flow control of output */
#define MDMBUF 0x00100000 /* old name for CCAR_OFLOW */
#endif
CSIZE = 문자당 비트수 변환 CS5 ~ 8 로 설정
CS5 = 문자 비트 5개로설정
CS6 = 문자 비트 6개로설정
CS7 = 문자 비트 7개로설정
CS8 = 문자 비트 8개로설정
CSTOPB = stop 비트를 2개 사용 (off 1개사용)
CREAD = 터미널에서 입력을 읽을 수 있음
PARENB = parity_bit 사용
PARODD = parity_bit 홀수 (off 짝수)
HUPCL = 마즈막 프로세스 종료시 disconnect 가 발생( 모뎀 끊기 신호)
CLOCAL = Ignore modem control lines.
//https://ingorae.tistory.com/1521
DTR - Data Terminal Ready
DSR - Data Set Ready
RTS - Request To Send
CTS - Clear To Send
CCTS_OFLOW = CTS선 출력 사용
CRTSCTS = (not in POSIX) Enable RTS/CTS (hardware) flow control. [requires _BSD_SOURCE or _SVID_SOURCE]
CRTS_IFLOW = RTS선 입력 사용
CDTR_IFLOW =DTR선 입력 사용
CDSR_OFLOW = DSR선 출력 사용
CCAR_OFLOW = CAR선 출력 사용
MDMBUF = If this bit is set, enable carrier-based flow control of output.
4. c_lflag
로컬 설정 (터미널 설정 내부에 대한 설정)
/*
* "Local" flags - dumping ground for other state
*
* Warning: some flags in this structure begin with
* the letter "I" and look like they belong in the
* input flag.
*/
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define ECHOKE 0x00000001 /* visual erase for line kill */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
#define ECHOE 0x00000002 /* visually erase chars */
#define ECHOK 0x00000004 /* echo NL after line kill */
#define ECHO 0x00000008 /* enable echoing */
#define ECHONL 0x00000010 /* echo NL even if ECHO is off */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define ECHOPRT 0x00000020 /* visual erase mode for hardcopy */
#define ECHOCTL 0x00000040 /* echo control chars as ^(Char) */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
#define ISIG 0x00000080 /* enable signals INTR, QUIT, [D]SUSP */
#define ICANON 0x00000100 /* canonicalize input lines */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define ALTWERASE 0x00000200 /* use alternate WERASE algorithm */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
#define IEXTEN 0x00000400 /* enable DISCARD and LNEXT */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define EXTPROC 0x00000800 /* external processing */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
#define TOSTOP 0x00400000 /* stop background jobs from output */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define FLUSHO 0x00800000 /* output being flushed (state) */
#define NOKERNINFO 0x02000000 /* no kernel output from VSTATUS */
#define PENDIN 0x20000000 /* XXX retype pending input (state) */
#endif /*(_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */
#define NOFLSH 0x80000000 /* don't flush after interrupt */
ECHOKE = (not in POSIX) If ICANON is also set, KILL is echoed by erasing each character on the line, as specified by ECHOE and ECHOPRT. [requires _BSD_SOURCE or _SVID_SOURCE](화면의 한 라인을 지운다)
ECHOE = ERASE 문자가 오면 이전문자를 지움
ECHOK = If ICANON is also set, the KILL character erases the current line (ICANON이 켜져있다면 character erases 다음라인을 kill을 한다?)
ECHO = 입력한 것을 터미널에 출력해줌
ECHONL = ECHO 와 무관하게 '\n'문자를 출력한다
ECHOPRT = ERASE 문자(백 스페이스를 말하는거 같음) 지운문자를 표시한다
ECHOCTL = ECHO 가 켜져있으면 ctrl + 키 같은 것을 출력함
ISIG = signal 을 받고 제어할수 있음 (cc_t에 설정 필요함)
ICANON = 문자를 아스키코드처럼 단위로 받음
ALTWERASE = 단어를 영어, 숫자, _와 같이 인식하여 스페이스바 단위로 나눔 (main argv에 들어가는거처럼? 설정해줌)
IEXTEN = POSIX.1 gives IEXTEN implementation-defined meaning, so you cannot rely on this interpretation on all systems. On BSD systems and GNU/Linux and GNU/Hurd systems, it enables the LNEXT and DISCARD characters. See Other Special Characters. (이건 컴터마다 다른듯 사용자 설정이라는 거같음)
EXTPROC = external processing (외부처리라는데)
TOSTOP = Send the SIGTTOU signal to the process group of a background process which tries to write to its controlling terminal.(백그라운드에서 멈처있는다는 뜻같음..)
FLUSHO = (not in POSIX; not supported under Linux) Output is being flushed. This flag is toggled by typing the DISCARD character. [requires _BSD_SOURCE or _SVID_SOURCE] (output being flushed (state) 라는데 아우풋을 깨끗이 하는거같음 )
NOKERNINFO = no kernel output from VSTATUS (커널 정보가 없는걸 만드는거같은데?)
PENDIN = If this bit is set, it indicates that there is a line of input that needs to be reprinted. Typing the REPRINT character sets this bit; the bit remains set until reprinting is finished. See Characters for Input Editing. (https://www.gnu.org/software/libc/manual/html_node/Editing-Characters.html 여기와 이어져있고 아직잘모르겟음)
NOFLSH = Normally, the INTR, QUIT, and SUSP characters cause input and output queues for the terminal to be cleared. If this bit is set, the queues are not cleared.( intr, quit, susp 로 터미널 입출력 대기열이 지워지지 않게 하는거 같음)
5. cc_t
시그널에 대한 처리방법 설정 (ctrl + z 등) 사용하려면 lflag에 ISIG 설정을 켜주어 야한다
https://cer3214.tistory.com/entry/%EC%95%84%EC%8A%A4%ED%82%A4-%EC%BD%94%EB%93%9C%ED%91%9CASCII-Code
아스키 코드표(ASCII Code)
DEC HEX OCT Char DEC HEX OCT Char DEC HEX OCT Char 0 00 000 Ctrl-@ NUL 43 2B 053 + 86 56 126 V 1 01 001 Ctrl-A SOH 44 2C 054 , 87 57 127 W 2 02 002 Ctrl-B STX 45 2D 055 - 88 58 130 X 3 03 003 Ctrl-C ETX 46 2E 056 . 89 59 131 Y 4 04 004 Ctrl-D EOT 47 2F 057
cer3214.tistory.com
여기 아스키 대로 적용되어 실행된다
어느 키를 넣어줄지 설정하여야 한다
6. c_ispeed
'42Seoul' 카테고리의 다른 글
ft_printf 여러가지 설명들 (0) | 2022.06.08 |
---|