본문 바로가기

Academy I/Tech Academy

Unix System Programming 8

Unix System Programming 8  - :namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />김성호(moohou) :namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

_________________________________________________________________________

 

8. 단말기

 

8.1. 서론

 프로그램과 사용자가 단말기를  통해 교신할 때는 언제나 보기보다 훨씬  많은

일들이 벌어진다. 예를 들어  프로그램이 단말기 장치에 문자열을 쓸 때  이 문

자열은 단말기 장치  구동기라는 커널의 한부분에 의해 우선 처리된다.  시스템

이 유지하는 상태 플래그가 갖는 값에 따라서, 문자열은  축약된 형태로 전달되

기도 하고 구동기에 의해 변형되기도 한다.

 

 - 프로그램

     이는 출력 문자열을 생성하고 입력 문자열을 해석한다.

 - 단말기 장치 구동기

     이는 kernel  의 일부,   소프트웨어의 일종이다. 구동기  주요부분은

컴퓨터가 단말기와 통신하도록  해 주는 특정 하드웨어와 상호작용을 한다. 

말기 장치 구동기  주요 기능은 프로그램과 단말기 장치 사이에  자료를 전달

하는 것이다.

 - 키보드와 화면

     이들 두 노드는 단말기 자체를 나타내며 단말기가 두가지  측면을 갖고 있

음을 강조한다.  단말기의 키보드는 입력  장치에 해당하고 화면은  출력장치로

작동한다.

 

 두가지 주의할 점이  있다. 첫째, 우리는 UNIX에서 사용되는 단말기의  대부분

인 비동기식 단말기 만을 다룬다. 둘째, UNIX 나 그  변중에서의 단말기 조작은

서로 일치하지 않는 것으로 악명이 높다.

 

8.2. UNIX 단말기

  4 장에서 언급했듯이 단말기는 특수화일로 인식된다.  (그리고 단말기의 특

성상 문자 장치 로서 취급된다). 단말기 이름으로는 다음의 것  들이 많이 쓰인

.

 

  /dev/console

  /dev/tty01

  /dev/tty02

  /dev/tty03

 

 tty 는 단말기를 지칭하는 UNIX 용어이다.

 

8.2.1. 제어 단말기

 프로세스의 표준 화일  기술어를 통하여 접근할 수 있는 단말기를  프로세스와

프로세스 그룹의 제어  단말기라 한다. 프로세스가 자신의 화일 기술어  상태와

무관 하게 제어  단말기에 접근하려면 /dev/tty 란 화일이름을 사용하면  된다.

이는 항상 프로세스 의 현재 제어 단말기를 가리킨다.

 

8.2.2. 자료전송

 단말기 장치 구동기  프로그램과 단말기 장치 사이에 문자를 전달하는  것이

주 임무이다.

 

8.2.3. 반향과 미리 쳐넣기

 가장 기초적인  편의 기능으로는 문자의  반향(echoing)을 꼽을수 있다.  이는

사용자가 키보드 에서 문자  'A' 를 칠때 화면에 'A' 가 나타나게 하는  기능이

. 이는  프로그램이 화면에 출력 하는  도중에 사용자가 입력을 하는  경우에

출력 의 중간에 입력의  반향이 나타나는 상황을 초래 한다. 다른  시스템의 경

우에는 프로그램이 입력 을 읽을 준비를 갖출 때까지 반향이 억제된다.

 

8.2.4. 규준모드, 라이편집, 특수문자.

 UNIX 구동기는 단순하고 라인 중심이며 대화식인 용도에 특별히  맞춘 작동 모

드를 제공한다. 이는 규준 모드(canonical mode)라 하며 쉘이나  ed 편집기,

리고 기타  유사한 프로그램에서 많이  사용된다. 규준모드에서 사용되는  편집

키 중 가장 친숙한  것은 erase 문자이다. 이를 누르면 해당 라인의 앞서의 

자가 지워진다.

 

  $whp<erase>o

 

 쉘 수준에서 이를 정하는 방법은 stty 를 사용하는 것이다.

 

  $stty erase "^h"

 

  erase 문자로서  CTRL-H 를 지정한다. 이는  backspase 의 또 다른  이름이

. 이때 CTRL-H 문자를  직접 입력하지 않아도 문자열 '^h'   사용하면 된다

는 사실에  주목하라. erase, kill, 또는  eof 문자의 특수 의미를  제거하려면

바로 앞에 역 슬래쉬 문자(\)를 사용한다. 이 경우에는 특수  문자에 결부된 기

능이 수행되지 않고 문자 자체가 프로그램으 로 전달된다.

 

  aa\<erase>b<erase>c

 

 은 단말기에서 입력을 얻는 프로그랩에게 aa\<erase>c 로 전달된다.

 

8.3. 프로그램의 관점

 지금부터는 단말기를 사용하는 프로그램의 관점에서 살펴보자.

 

8.3.1. open 시스템 호출

 open 은 보통의 디스크 화일과 매우 유사한 방법으로  단말기를 개방하는데 사

용된다.

 

  fd = open("/dev/tty0a", O_RDWR);

 

8.3.2. read 시스템 호출

 화일에 접근하는 기본 호출 중에서 단말기 특수 화일을  사용하는 경우에 가장

큰 영향을 받는 것이  read 시스템 호출이다. read 호출은 항상 newline  

력되어야 끝난다.

 

  nread = read(0, buffer, 256);

 

8.3.3. write 시스템 호출

 이는 단말기와  함깨 사용되는 한 매우  간단하게 수행된다. 단지  제한접이란

해당 단말기의 출력 큐가  모두 차 있는 경우에 write 가 블럭되는 것  뿐이다.

프로그램의 수행이 재개되려면  큐에 남아있는 문자들이 일정수준 이하로  빠져

나가야 한다.

 

8.3.4. ttyname isatty

 ttyname 은 개방된 단말기 화일 기술어의 해당 단말기 장치에  대한 이름을 돌

려준다. isatty 는 화일 기술어가 단말기 장치의 것이면 1 , 아니면  0 을 돌

려준다.

 

  int filedes, bool;

  char *name, *ttyname();

  .

  .

  name = ttyname(filedes);

 

  bool = isatty(filedes);

 

 두기지 경우 모두 filedes 는 개방된 화일 기술어를 나타낸다.  filedes 가 단

말기를 나타내지 않으면 ttynam NULL 을 돌려준다.

 

8.3.5. termio 구조를 사용하여 단말기 특성을 변경하는 법

 쉘에서는 단말기의 특성을  변경하기 위하여 stty 명령을 사용했다.  프로그램

에서는 ioctl 시스템 호출과 termino 구조를 사용하여 같은 일을 할 수 있다.

 

 - 생략

 

8.3.6. MIN TIME 인수

 인수 MIN TIME 은 플래그 ICANON 0 일때만 효력을  갖는다. 이들은 자료

의 입력, read  호출에 대한 프로그의 제어권을 정밀하게 조정한다.  MIN

단말기에 대한 read 호출이 끝나기 전에 단말기 구동기가 받아  들여야 하는 문

자의 최소 갯수를 나타낸다.  TIME 는 또 다른 제어권으로서 시간  종료의 기간

을 나타 낸다.

MIN TIME 의 값에는 다음의 4 가지 경우가 있을 수 있다.

 1. MIN TIME 모두 0 일때.

  이 때는 read 호출이 항상 즉시 끝난다. 해당 단말기의 입력 큐에 문자가 들

  어 있으면(입력은 아무때고 도착한다는 것을 상기하라), 프로그램 버퍼에 옮

  겨진다.

 2. MIN 0 보다 코고 TIME 0 과 같을때.

  이 경우에는 타이머가 아무 역할도 하지 않는다. read 호출이 끝마쳐 지려면

  읽혀지길 기다리는 문자가 MIN 만큼은 있어야 한다.

 3. MIN 0 이고 TIME 0 보다 클때.

  이 경우 MIN 은 아무일도 하지 못한다. 타이머는 read 가 호출되는 순간부터

  작동한다.

 4. MIN TIME 모두 0 보다 큰 경우.

  이 경우가 가장 유용하고도 유연성이 있다. 타이머가 작동되는 순간은 이제

  read 가 호출된 순간이 아니라 첫번째 문자가 들어왔을 때이다. 시간이

  종료되면 그 순간까지 입력 큐 에 있는 문자들만이 프로그램에 전달된다.

 

8.3.7. ioctl 시스템 호출

 ioctl 문자형  특수 화일이 나타내는 외부장치를 제어하기 위한  다목적 호

출로서 인수의 유형이  매우 다양하다. 단말기에 대한 ioctl 호출은  크게 기본

호출과 추가호출의 두가지 유형으로 분리된다. 기본호출의 사용법은  다음과 같

.

  #include <termio.h>

 

  struct termio targ;

  int ttyfd, cmd, retval;

  .

  .

  retval = ioctl(ttyfd, cmd, &targ);

 

 ttyfd 는 단말기에 대한  개방된 화일 기술어라야 한다. targ   termio 구조

의 변섭 단말기의 상태를  저장한다. 인수 cmd ioctl   수행양식을 지정하

termio.h 에 정의된 바와 같이 다음과 같은 값을 가질 수 있다.

 

  TCGETA

   이는 icctl 이 단말기의 현재상태를 targ 에 복사하게 한다.

  TCSETA

   TCGETA 의 역으로서, targ 에 있는 값으로 단말기의 상태를 지정한다.

  TCSETAW

   이는 TCSETA 와 같은 기능을 하지만 새로운 값을 지정하기전에 현재의 출력

   큐가 비워질 때까지 기다린다.

  TCSETAF

   이는 TCSETA 의 또 다른 형태로서 출력 큐가 비워질 때까지 기다린 후에 입

   력 큐를 청소하고 난 다음에야 단말기의 상태를 targ 의 값으로 지정한다.

 

 이는 기본  호출과 추가 호출 경우에  모두 적용된다. 추가적인 ioctl  호출은

프로그래머에게 단말기 구동기가 관리하는 입출력 큐에 대한  어느 정도의 제어

권을 부여한다.

 

  #include <termio.h>

 

  int ttyfd, cmd, arg, retval;

  .

  .

  retval = ioctl(ttyfd, cmd, arg);

 

 여기서 ttyfd cmd 의 의미는 앞에서의 경우 동일하다.  arg 는 정수형로 추

가적인 정보를 전달한다. 추가 ioctl 호출에서 사용할 수 있는  cmd 의 값은 다

음과 같다.

 

  TCFLSH

   arg 0 이면 입력 큐를 청소한다. 즉 입력 큐의 모든 문자를 무시한다.

   arg 1 이면 큐를 청소한다. arg 2 이면 입출력 큐를 모두 청소한다.

  TCXONC

   이것은 단말기 구동기에 대한 중단/재개를 제어한다. arg 0 면 출력이

   중단된다. 중단된 출력을 재개하려면 arg 값을 1 로 해서 ioctl 을 다시 호

   출해야 한다.

  TCBRK

   이것은 break 를 전송하는 데 사용된다. 이것은 1/4 초동안 0 비트들을 전

   송하는 것과 같다. 이 기능은 출력 큐가 빈 다음에만 사용되어야 한다.

 

8.3.8. 단절 시그널

 6 장에서 프로세스 그룹 리더가 제어 단말기를 갖고 있을  때 수행이 종료되면

해당 프로세스그룹의  구성원들에게 단절 시그널  SIGHUP 이 전달됨을  보았다.

여기에는 또 다른 용도가 있어서, 컴퓨터와 단말기 사이의  접속이 끊어져서 단

말기 라인의 반송파가 검출되지  않는 상황을 대변 할 수 있다.  이러한 상황은

단말기가 전화선이나  지역 네트워크를 사용하여 연결된  경우에 발생할 수 

. 이런 상황이  발생하면, 단말기 구동기는 해당 단말기를 제어  단말기로 하

는 모든 프로세스에게 SIGHUP 을 보낸다. (SIGINT와는 달리 SIGHUP  은 쉘을 정

상적으로 로그아웃되게 한다.) 보통의 경우 프로그래머는 SIGHUP  에 손대지 말

아야 한다. 이는 훌륭한 안전장치를 제공한다. 그러나  때에 따라서는 프로그램

이 이를 포착하여 마무리 작업을 수행해야 할 필요성이 있을 수 있다.

 

8.4. connect 의 예

 connect 는 통신 프로그램으로서 두가지 작동모드를 갖는다.  하나는 사용자가

두 개의 UNIX 컴퓨터를  연결하게 해준다. 다른 하나는 두 컴퓨터  간에 텍스트

화일을 전송하게 해준다. 우선 헤더화일 connect.h 를 살펴보자.  이 화일은 다

termio.h  와 같은 시스템 헤더  화일을 포함한다. 이외에도 다수의  상수가

정의 되어 있다.   중에서 STARTCOM 이란 문자열은 현지 컴퓨터에서  원격 컴

퓨터로의 자료전달을 초기화 하는데 사용된다.

 

 

 

  #include <stdio.h>

  #include <fcntl.h>

  #include <termio.h>

  #include <signal.h>

  #include <setjmp.h>

 

  #define ERROR   (-1)

  #define SUCCESS   0

  #define TRUE      1

  #define FALSE     0

 

  #define SENDFILE  1

  #define EXIT      2

  #define MAXTIME   30 

 

  #define STARTCOM\

   "mesg n; stty -opost; cat -> %s; stty

    opost; mesg y"

 

  #define CTRLD   004 

  #define CTRLP   020 

  #define CTRLY   031 

 

 connect 프로그램을 호출 하려면 다음과 같이 명령을 준다.

 

  $connect term-name speed

 

 예를 들어서

 

  $connect /dev/ttya 9600

 

 main 에서  호출하는 함수로는 표준시스템  호출 과 라이브러리루틴을  제외하

, getspeed, ttyopen, cfatal, 그리고 connect 등이 있다.  함수 getspeed

명령어 라인 인수의 두  번째 것을 ioctl 에 적합한 형태로  변환한다. ttyopen

  앞서  소개했듯이   단말기를  개방하는  함수이다(ttyopen     수정하여

connect.h 에 정의된 상수들을 이용하는 것도 고려해보라). 함수  cfatal 은 오

류메시지를 출력하고 프로그램의 수행을 중단시킨다. connect   main 이 호출

하는 마지막 함수이다.  여기서는 두개의 자식 프로세스를 생성하여 화일  전송

을 담당하 는 중추적  역할을 한다. 함수 connect 는 두개의 인수가 있는데 

나는 ttyopen 이 개방한 화일기술어이고, 다른 하나 는 getspeed  가 변환해 준

전송속도이다. 임무 는  프로세스를 두개 생성하여 부모 프로세스는 원격  시스

템에서 오는  문자들을 전달하게 하고 자식  프로세스는 원격 시스템에서  오는

문자들 을 받아들이게 하는 것이다. 필요한 경우에는 원격  시스템으로 화일 전

송을 개시할 수도  있다. 여기서 명심할 사실이 있다. 하나는  자식 프로세스가

수행하는 from 함수는  절대는 끝나지 않는다는 것이다. 따라서 부모  프로세스

kill 함수를 호출해야 한다. 다른 하나는 함수 to  가 돌려주는 변수 status

는 사용자가 입력 하는  명령어에 해당한다는 것이다. SENDFILE EXIT  가 정

의된 곳은 물론 connect.h 이다.

 

8.5. 과거

 UNIX 버전 7   같은 경우에는 termio 구조는 존재하지 않았다.  대신에 단말

기의 상태를 기술하기 위해서  보다 간다한 구조 sgttyb 를 사용했다.  이 구조

의 자료형을 사용했을때는  ioctl 의 기능이 좀 더 제한되었었다.  단말기의 특

성은 gtty 라는 시스템 호출에 의해 얻어지고 stty 에 의해 지정되었다.

 

8.6. 그리고 미래

 스트림이란 본질적으로는 프로세싱 모듈의 선형 구조로서 쉘의  파이프 라인과

유사하지만 모듈 사이의 자료전달이 양방향으로 모두 될 수  있는 점이 다르다.

스트림의 한쪽 끝은 사용자 프로세스에게 연결되어 있고  다른쪽 끝은 스트립을

위한 장치 구동기  연결된다. 사용자 프로세스에게 가장 가까운 모듈은  스트

림에 대한 프로그래머의 인터페이스 역할을 한다. 사용자  프로세스가 write

호출하면 이는 스트림에  전달되는 메시지로 변환되고, read 를 호출되면  가장

가까운 모듈에서 자료를 읽어 들이게 된다. 일관성을 유지하기  위해서 제어 정

보도 모듈간의 메시지와 같은 형태로 전달된다. 스트림이 open  호출을 통해 개

방되면 두개의 말단  모듈이 자동적으로 연결된다. 이것이 스트림의 가장  기본

적인 형태이며 프로그래머에게  매우 원시적인 수준의 인터페이스를  제공한다.

추가적인 모듈이  스트림에 삽입되려면  확장된 형태의 ioctl  을 호출해야 

.(단말기가 최초에 매우 원시적 상태로 개방된다는 사실은  사용자 수준의 코

드를 약간 수정하게 만든다.)


'Academy I > Tech Academy' 카테고리의 다른 글

Linux gdb 사용법 [I]  (0) 2014.12.19
Linux make 사용법 [I]  (0) 2014.12.18
Unix System Programming 10  (0) 2014.12.16
Unix System Programming 9  (0) 2014.12.16
Unix System Programming 7  (0) 2014.12.16
Unix System Programming 6  (0) 2014.12.16
Unix System Programming 5  (0) 2014.12.16
Unix System Programming 4  (0) 2014.12.16