리눅스 시스템 프로그래밍
다른 프로그램들과 다른 점을 알아보자.
시스템과 어플리 케이션은 정확한 구분을 줄 수는 없지만, 굳이 말하자면, 주목적이 운영체재가 필요한 프로그램 이냐// 사람이 사용하기위한 프로그램이냐로 볼수는 있지만,코드자체로는 별 구분이 없다.
우리가 말하는 리눅스, 윈도우, ios , 등의 운영체재들은 커널이라고 하는 종류의 이름이다.
커널을 쉽게 쓰기 위해서 만든 유틸리티(시스템 정보를 직접적으로 사용하는 조각모음)와, 오락같은 어플리케이션 (메모장, 계산기), 커널에 포함되어 있는 드라이버등이 있다.
커널에는 셸(shell : 조개껍질) 이라는 것이 있는데, 이는 중간 번역기(명령어 해석기) 라고도 하며, 커널에 접근하여 헤당하는 함수를 호출할 수 있게 하는 역활을 한다. 우리가 윈도우에서 아이콘을 더블 클릭을 하면 실행되는 것도, 실제로는 셸에 명령어가 링크되어 전달 되어 실행 되는 것이다.
쉘은 운영체재를 보호하기 위해 존재하는데, 일반 사용자가 운영체제에 접근하지 못하도록, 해당하지 않은 명령어는 버린다.
리눅스는 셸의 종류가 많은데 (A,B,C셸등). 그 중에서도 b셸을 업그레이드 시킨 베쉬셸을 많이 사용된다. 베쉬은 자동완성 기능을 최초로 지원했다. 리눅스에서 A를 누르고 TAP키를 누르면, 검색해주는 것을 본적이 있을 것이다.
데몬 : 문지기 프로그램 으로 컴퓨터는 각 문에 번호를 붙이는데 이를 포트라고 부른다. 데몬 중에는 웹데몬이라는 것이 있는데 이는 다른 말로 웹서버라고도 한다.
이 데몬은 운영체재가 실행 시키는 한, 유지되야 한다.헤킹 프로그램들은 이 데몬을 많이 이용한다.(상주 되어 있다.)
고수준 추상화 : C에서는 동적할당을 받으면, free로 다시 거두어 들여야 하지만, 자바의 경우, 대신 처리해 주는데, 이처럼 가상머신을 만들어 우리가 만드는 프로그램에만 집중할 수있게 해준다.
대표적인것이 안드로이드로로 프로그램에만 집중하여 만들면, 가상머신이 해당기기 (하드웨어에) 맞게 만들어 주는 것이다.
이때, 내부적인 것은 추상화 시키고, 더욱 이런 추상화를 높게 만들면, 양질의 프로그램을 만들수 있다는 베이스 개념을 말한다. => (포인트, 객체 최적화 ) 자바 가상머신
우리가 시스템 프로그래밍을 통해 프로그래밍 능력을 키울수 있다. (공부 목적)
자바 스크립트에서 스크립트란 (컴파일 되지 않은것을 말하는데 쉽게 말해 소스가 보이는 것을 말한다. 이는 바로 소스를 해석 한다(바로 컴파일)된다는 말이다.
만약 인터넷에 A,B의 사용자가 구글이라는 창을 보고 있다면, 같은 HTML을 보고 있는 것이다. 이때, A사용자가 로그인등 개인적인 정보가 더해지면 PHP 같은 자바 스크립트 언어가 (HTML정보 + 자신정보 = HTMP) 새로운 정보로 바꾸어 A사용자에게 보여준다.
PHP(무료),ASP( 윈도우용 ),JSP(무료/유료) 서버에 설치되어 있어야 한다.
HTML + 자신정보 = HTMP 정적에서 동적으로 바꾸는 역활을 한다.
사용자 영역의 응용은 커널과 연결 되지 못한다. (헤킹과 운영체재 손상) 그래도 커널과 연결되어야 함수를 사용 할 수 있으므로, 시그널을 이용, API함수 제공한다.
이렇게 어플리 케이션도 시스템 호출(커널사용)을 하지만, 시스템 프로그램보다 적다.이처럼 둘 의 구분이 얼마나 많이 시스템 호출을 하느냐가 기준인데 이가 애매하다.
어셈블리에서 인터럽트 호출사용 EAX에 5를 넣고 인트럽트 명령어 INIT(인트럽트 번호)를 사용하면 된다.
API는 우리가 자주 사용 해서 알 것이고, ABP (B는 Binary)는 함수의 일부분을 컴파일된 것을 말한다 (이들의 모음). 이는 API는 여러 CPU에서 컴파일러에 의해 컴파일되면, 각각에 사용 될 수 있지만,
ABI는 한 CPU에 맞게 일부컴파일된 것이므로, CPU의 종류에 영향을 받는다.
이는 리눅스 프로그램을 윈도우나 ARM등 여러 CPU에 지원 할경우 레지스터등 일부분을 각각의 CPU에 맞게 컴파일된 해당하는 ABI를 호출하게 되고, 그러면 사용이 가능하게 된다.
이름은 동일 함수가 여러 cpu 여기서는 윈도우나 arm의 프로그램 헤당하는 ABI가 호출 된다.( STST LDST를 일부를 해당하는 CPU ABI를 만들면, 사용이 가능 )
추상화 = 시스템 프로그래밍으로 마우스 , 키보드 , 파일등을 쓰고 읽을 수있다. 이 세가지는 서로 다르지만 read / wirt 할 수 있다. 이는 하드웨어에 구애 받지않고, 프로그램만 (read / wirt ) 할 수 있다는 이야기다. 즉, 추상화 했다는 것 하드웨어를
프로그램과 프로세스 그리고 프로세서 (CPU)
프로세서는 CPU를 말하고, 프로세스는 실행중인, 프로그램을 말한다.
시그널이란 소프트웨어 인트럽트로서 윈도우의 메세지처럼 시스템의 흐름을 제어한다. 예로 프로그램 실행중에 컨트롤 + C 누르면 프로그램이 빠져 나오는 것을 우리는 사용한 적이 있다.
프로세스간 통신이 가능한대 이는 내부에서 두 프로그램이 서로 읽고 쓰기를 할 수있는 것을 말하고 이를 내부 IPC ( 인터 프로세서 커뮤니케이션) 라고 부른다.
이 커뮤니케이션이 외부의 어떤 것과의 읽고 쓰기가 가능하다는 것은 네크워크라 한다.
에러 메세지를 출력하는 기본적인 소스 프로그램을 실행 시켜 보자.
먼저, 시스템 프로그래밍에서는 특수한 변수 errno를 써서 구체적인 이유를 알 수 있다. 이를 사용하기 위해서는 <errno.h>파일을 include시켜 줘야 하다. 정의는 다음과 같다.
exturn int errno;
오류가 발생하면, errno의 값이 바뀌고, 이 번호에 대한 에서 메세지는 #define으로 문자열이 숫자와 대응되어 있다. <책 48page 참고>
이를 확인해 보면, 루트로 이동하고, cd / cd /usr/include 에서 vi 편집기로 errno.h를 열어보면,
다음과 같이 extern int errno; 라고 정의 되어 있는 것을 확인 할 수 있다. 이는 우리가 헤더만 추가해주면, 프로그램내에 있는 듯이 사용 할 수 있다는 것이다.
그리고, 번호에 대한 디파인된 문자열 정의가 보이지 않는데, 이는 bits경로에 있는 errno.h 파일을 include 해서 사용하는데, 이를 찾아보면, cd .. 으로 상위로 이동 후, bits 이동 후, errno.h 파일을 열면,
다음과 같이 defne EDON 33 처럼 헤당하는 번호에 대해 문자열 정의가 디파인 되어 있다. 세가지 경우 밖에 없는데, 다시 위의 코드를 보면, linux 경로에 errno.h파일을 include 하고 있는 코드가 있다. 다시 찾아가 보면,
asm 경로에 errno.h 파일을 include 하고 있다. 지친다 끝은 어디일까? 끝까지 가보자.
우리가 그토록 확인해 보고 싶은 결과를 볼 수 있다. 번호에 따라 문자열 정의가 define 되어 있다. 마찬가지로, 문자열 정의는 다시 메세지 출력할 내용을 define하고 있을 것이다.
여기 까지 확인하고, errno에 대한 간단한 예제를 실습해 보자.
첫 번째로, errno변수에 0이 입력되면, success라는 메세지를 출력한다.
이때, perror이라는 함수로 오류메세지를 출력한다. 이때, perror의 정의는 void perror(const char *str);이다.
인자는 문자열로 결과에서 보듯 이 문자열이 출력 되고 : 이후에 에러 메세지를 출력한다.
이를 응용하면, 큰 프로그램에 여러함수에 인자에 함수이름이나 구분할 문자열을 입력하면, 어디에서 어떤 에러가 나타났는지 쉽게 파악 할 수 있다.
두 번째로, 디파인된 문자를 대입해도 해당하는 오류메세지를 출력한다.
앞에서 언급한데로 인자에 구분가능한 함수이를을 넣어 보았다.
세 번째로. 중간에 함수를 넣어 보면, 에러 메세지가 바뀐것을 볼 수있다. 여기서 알 수 있는 것은 함수가 실행 될때, 함수가 errno의 변수에 값을 넣어 준다.
일반적으로 에러가 없으면, 0 에러가 발생하면, 헤당하는 에러의 번호가 errno에 저장된다.
또다른 에러 검출 함수인 strerror에 대해 알아보자 먼저 <string.h>헤더에 선언 되어있고, 원형은 char *strerror (int errnum); 이다.
이는 해당하는 에러 번회를 인자로 주게 되면 이해 해당하는 문자열 주소를 반환한다. 이를 코드를 통해서 알아보자.
첫 번째로 printf함수로 %s 로 받아 출력하면, 위와 같은 결과가 나타난다. 이때, %S로 받질않고, printf( strerror (E2BIG) ); 를 넣어도, 같은 결과가 출력 된다.
이는 printf원형 int printf( const char *format [, argument]... ); 에서 printf(" ",가변인자); 에서 " "는 주소 이기 때문아다.
다음은 포인트를 사용해서, 결과 값을 출력한 프로그램이다. 당연히 strerror함수가 문자열의 주소가 반환되고, 이는 char포인트에 대입되고, 출력이 된다.
이와 같은 strerror이란 함수는 구현이 가능한데,
typedef struct EMB
{
int iNum;
char *pChar;
}EMB;
char *strerror(int errnum)
{
int iCnt;
EMB emb[] ={
{1,"E2BIG"}
,{2,"EACCESS"}
......
,{100, "EXDEV"}
}
for( iCnt = 0 ;100 > iCnt ;++iCnt)
{
if ( emb[iCnt].iNum == errnum)
{
return (emb[iCnt].pChar);
break;
}
}
return 0;
}
구조체를 만들어 구조체 배열에헤당하는 에러 번호와 이를 정의된 문자열의 주소를 초기화 시킨다.
for문으로 헤당하는 번호를 찾으면, 문자열 주소값을 리턴 하고, (에러 발생하지 않음) 맞는 것이 없으면, 0을 리턴 결과값을 출력하면, success라고 출력 될 것이다.
'코스웨어 > 12년 내장형하드웨어' 카테고리의 다른 글
FAT 포맷형식, 다중입출력 (0) | 2012.09.20 |
---|---|
09.20 배운것 (0) | 2012.09.20 |
size_t (0) | 2012.09.20 |
read(), write() (0) | 2012.09.20 |
64비트 리눅스 배포판에서는 errno.h 의 위치가 다를 수 있습니다. (0) | 2012.09.19 |
errno (1) | 2012.09.19 |
수업일지 리눅스 시스템 프로그래밍 (1) | 2012.09.19 |
요청글 (1) | 2012.09.17 |