기말고사 시험기간인데 다들 공부 잘 하고 계신지 모르겠네요.
저는 이번 기말고사 션하게 말아먹을 것 같습니다. ㅠ
기말고사 시즌인 관계로 이번 블로그는 머리를 식힐겸 퍼즐을 하나 준비했습니다.
이건 18-2기 여러분들 들어오셨을 때 집중세미나 시간에 했던거 재탕인데요.. 뭐 뒷북이지만 괜찮겠지여 ㅋㅋ
지뢰찾기 퍼즐
지뢰찾기는 다 해보셨으리라 생각되므로 자세한 설명은 생략하겠습니다.
위의 지뢰판에서 숫자는 자기과 양옆의 칸에 있는 지뢰의 수를 알려줍니다. 한 칸에는 최대 하나의 지뢰만이 있을 수 있습니다.
그렇다면 위의 그림에는 몇 개의 지뢰가 있을까요?
지뢰찾기 고수분들은 그림 대충 보고 지뢰가 어디에 있는지 금방 찾으실거라 생각되는데여 사실 지뢰찾기 한 번도 해보지 않은 사람이라도 이 문제의 해법은 상당이 간단합니다.
답부터 말하자면 지뢰의 수는 2 + 1 + 1 + 2 = 6 입니다.
위 그림을 보면 어째서 2 + 1 + 1+ 2 가 답인지 눈치를 채실 수 있으리라 생각합니다.
붉은 색으로 표시된 칸에 적힌 숫자는 그 칸을 포함하여 양옆까지 총 3개의 칸에 존재하는 지뢰의 수를 알려줍니다. 즉 연속한 3칸을 한 단위로 보면 그 중 가운데 칸이 그 한 단위에 있는 지리의 수를 알려주는겁니다. 그렇다면 우리는 단순히 지뢰밭을 3개를 한단위로 나누어 그 각 단위별로 지뢰수를 모두 더하면 전채 지뢰밭에 있는 지뢰 수를 알게 되는 거지요.
그런데 여기에는 문제가 있습니다. 바로 이 방법은 3의 배수일때만 가능하다는 겁니다. 아래의 경우를 봅시다.
위와 같이 3개를 한단위로 쪼개보겠습니다.
그림을 보면 처음 9개의 칸에는 모두 5개의 지뢰가 있는 것을 알 수 있지만 마지막 칸에 지뢰가 있는지 없는지 확신을 가질수가 없습니다. 결국 지뢰찾기를 다 해봐야 전체 지뢰의 갯수를 알 수가 있게 됩니다. 하지만 여기에 간단한 해결책이 있습니다.
어떤가요? 전체 지뢰 갯수가 1 + 1 + 2 + 1 = 5 라는 것을 한 눈에 알 수 있습니다.
이제 우리는 아래 지뢰판에 지뢰가 몇 개인지도 쉽게 알 수 있습니다.
10 * 10 크기의 지뢰판인데여.. 지뢰가 어디있는지 찾으려면 힘들지만 지뢰가 몇개인지 아는 것은 이제 문제가 안됩니다.
가로세로 모두 크기가 10 (3n+1의 형태) 이므로 양쪽끝 단위의 길이는 2, 가운데는 3이 되도록 나눈뒤 가운데 칸의 수만 다 더하면 됩니다.
총 지뢰수는 1 + 2 + 1 + 2 + 2 + 2 + 1 + 2 + 1 + 3 + 2 + 2 + 2 + 1 + 2 + 4 = 30 이네요..
아래의 지뢰 지도를 보면 지뢰가 30개 맞다는 것을 알 수 있습니다.
(처음 지뢰판을 보고 정답표를 맞추기는 쉽지 않을것 같습니다;;)
오늘 포스팅은 여기서 마치겠습니다.
당장 보기에 어려워 보이는 문제라도 살짝 다른 시각에서 보면 간단한 해법이 존재할 수 있다는 것을 생각하시기 바랍니다.
안녕하세요. ^_^ 다들 너무 오랜만이죠? ㅎㅎ
너무 오랫동안 포스팅을 안해서 벌금이.. 후덜덜덜
그래서 오늘은 멤버십 컴퓨터에 MSSQL 2008을 설치해서 DB 생성과 삭제에 관한 것들에 짧게나마 알아보고자 합니다.
우선 MSSQL 2008의 Microsoft SQL Server Management Studio를 켭니다.
서버에 접속을 하시구요.
접속을 해서 보시면 왼쪽편에 데이터베이스, 보안, 서버계열.. 등등등 여러가지가 보이실텐데요.
이제 데이터베이스를 생성해보도록 하겠습니다.
데이터베이스가 생성이 되었습니다.
생성된 데이터베이스에 데이터들을 입력하기 전에 CREATE문에 대해 잠시 살펴보도록 하겠습니다.
이렇게 3가지 예제를 보셨는데요.
DB를 생성하는 것은 그다지 어렵지 않죠??
그러면 이번에는 데이터베이스 사이즈 늘리기를 중심으로 관리하는 방법을 살펴보겠습니다.
- 데이터베이스 관리란?
- 데이터 증가에 따른 파일 사이즈 변경
- 트랜잭션 로그 모니터링
- 필요에 따른 데이터베이스 사이즈 줄이기
- 데이터베이스 삭제
- 데이터베이스 사이즈 늘리기
데이터베이스 사이즈를 늘리는 방법은 다음의 세가지가 있습니다.
- 자동으로 증가하도록 데이터베이스 옵션 설정
- 데이터 파일의 사이즈 확장
- 데이터 파일 추가
1) 데이터베이스 지동 증가 옵션 설정
CREATE DATABSE문 사용시 사이즈 증가에 대한 SIZE, MAXSIZE FILEGROWTH옵션을 사용하면 됩니다.
데이터베이스를 만들 때 이 옵션들을 이용해서 필요한 경우 사이즈가 자동으로 증가하게 해 주는 것이 좋습니다. 또한 중요한 것은 데이터베이스가 꽉 차는 사태가 없어야하는 것입니다. 아무리 사이즈 자동 증가가 되게 했다 하더라도 하드디스크가 여유공간이 없어지면 데이터베이스 사이즈 증가가 더이상 불가능하게 됩니다.
2) 데이터 파일의 사이즈 확장
ALTER DATABASE MyDB
MODIFY FILE (NAME = MyDB_Data, SIZE = 30MB)
GO
MODIFY FILE을 이용하여 MyDB_Data 파이르이 사이즈를 30MB로 바꾸었습니다.
3) 데이터 파일 추가ALTER DATABASE MyDB
ADD FILE (NAME = MyDB_Data2,
FILENAME = 'D:\Data\MyDB2.ndf',
SIZE = 10MB,
MAXSIZE = 50MB,
FILEGROWTH = 5MB)
GO
ADD FILE을 사용하여 사이트가 10MB인 파일을 추가함으로써 데이터베이스 사이즈를 늘렸습니다.
하드웨어 개발자의 종착역은 결국, 디바이스 드라이버가 됩니다.
처음엔 땜질을 하면서 이것저것 배우게 되고,
그 다음에는 기본적인 MCU를 배우게 됩니다.
이때 인터럽트라는 개념에서 한 번 뱅글뱅글 돌게 되지요.
그러다가 이제는 설정 레지스터 에서 뱅글뱅글 돌게 되고요...
이렇게 저렇게 발전 하다보면, OS의 필요성을 절실히 느끼게 됩니다.
그만큼 성장을 해서 관리해야할 자원들이 많아지거든요..
그럼 스 자원 관리를 위해서 OS를 올리게 되는데
일반적으로 TinyOS - RTOS - linux 순으로 올라가게 됩니다.
리눅스를 올리게 되면 커널을 통해서 디바이스를 제어하게 되므로,
결국 리눅스 커널상에서 디바이스 드라이버가 돌아가게 만들어야 합니다.
아래 내용은 그 디바이스 드라이버에 대해서 간단하게나마 개념을 잡아주도록 설명을 해주고 있습니다.^^
디바이스 드라이버
아주 오래 전에는 컴퓨터에 달린 모든 장치에 대해 프로그래머가 모든 장치 제어에 대해 프로그램을 직접 작성해야 했습니다. 이러다 보니 프로그래머나 판매자, 사용자 모두 힘들었습니다. 예를 들어 아무리 좋거나 저렴한 프린터라도 프로그래머가 제어할 방법을 모른다면 사용할 수 없었습니다. 만일 사용자가 특정 제품을 사용하겠다고 고집하면 하는 수 없이 프로그래머는 학습과 코딩 수정이 필요했습니다.
그러나 디바이스 드라이버라는 개념이 생긴 후로는 프로그래머는 자신의 프로그램에 더욱 충실할 수 있었습니다. 즉, 외부 장치에 대해서는 제품을 만든 회사에서 함께 제공되는 드라이버를 이용하면 되기 때문입니다.
거기다가 이 드라이버를 사용하는 방법이 완전히 같지는 않아도 대동소이 하다면 그야말로 프로그래머는 장치에 대한 부담에서 많이 자유로워 질 것입니다.
그러나 장치에 따라 디바이스 드라이버도 서로 다릅니다. 만들어진 회사도 다를 수 있습니다. 장치를 쉽게 다룰 수 있도록 디바이스 드라이버까지 만들어서 제공해 준 것 까지는 좋은데, 사용하는 방법이 디바이스 드라이버 마다 매우 다르다면 응용 프로그래머에게는 부담이 매우 클 것입니다. |
|
디바이스 드라이버 사용 예
가상 파일 시스템이라는 내용을 이해해 보도록 하겠습니다. 이전에 시리얼 통신 강좌 시리즈 중에 시리얼 통신 - 통신포트 열기 글에서 디바이스 드라이버에 대해 말씀을 드린 적이 있습니다. 그 중에 일부를 올립니다.
시리얼 포트의 장치명
/dev 디렉토리에 있는 시리얼 포트의 목록을 보면 아래와 같은 내용이 출력됩니다. 도대체 뭔소리인지 하나씩 알아 보겠습니다.
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10)crwxrwxrwx 1 root tty 4 64 Jan 1 2006 ttyS00 crwxrwxrwx 1 root tty 4 65 Jan 1 2006 ttyS01 crwxrwxrwx 1 root tty 4 66 Jan 1 2006 ttyS02 crwxrwxrwx 1 root tty 4 67 Jan 1 2006 ttyS03 (1) 접근 권한을 보면 crwxrwxrwx 로 c로 시작하는 것은 장치가 "문자 장치"임을 알려 줍니다. c 가 아닌 b로 시작한다면 "블록 장치"를 말하는데, 예로 하드디스크와 같이 블럭 단위로 읽거나 쓰기를 하는 장치가 되겠습니다.
(5) 의 4는 메이저 장치 번호, (6)의 64, 65, 66 등은 마이너 장치 번호입니다. 우리가 작성하는 프로그램은 하드웨어 장치를 직접 제어하는 것이 아니라 커널을 통해 제어하게 됩니다. 하드웨어를 파일 개념으로 처리할 수 있는 것도 중간에 커널이 가상 파일을 만들어서 제공하기 때문에 가능 한 것입니다.
프로그램에서 하드웨어 장치에 대해 어떤 작업을 커널에게 요청하면, 커널은 메이저 번호를 가지고 어떤 디바이스 드라이버 사용할 지를 결정하게 됩니다. 디바이스 드라이버는 커널로부터 받은 정보 중 마이너 장치 번호를 가지고 자기에게 할당 된 장치 중 어떤 장치를 제어할 지를 결정하게 됩니다.
위의 장치 목록을 보시면 메이저 번호가 모두 4 로 똑 같습니다. 대신에 마이너 번호만 다르죠. 커널은 메이저 번호로 따라 디바이 드라이버를 선택하고 다음 처리를 넘기면 디바이스 드라이버는 마이너 번호를 가지고 어느 장치를 사용할 지를 결정한다는 얘기가 되겠습니다.
이렇게 하드웨어 장치 제어 흐름을 본다면 ttyS0, ttyS1 과 같은 이름은 별로 중요하지 않죠. 중요한 것은 메이저 장치 번호와 마이너 장치 번호가 되겠습니다.
위 내용을 조금 더 쉽게 이해하기 위해 통신 포트를 open 하는, 즉 통신 포트를 사용하기 위한 프로그램 코드를 보겠습니다.
fd = open( "/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK );
통신 포트라는 장치를 사용하기 위해서 /dev/ttyS0를 open했습니다. 그렇다면 /dev/ttyS0 가 디바이스 드라이버일까요? 디바이스 드라이버도 응용프로그램과 장치 사이에서 실행되는 프로그램이라고 생각한다면 /dev 에서 장치 목록을 출력할 때, 주 장치 번호와 부 장치 번호 뿐만 아니라 파일 사이즈도 나와야 할 것입니다. 파일 사이즈도 파이에 대한 중요 정보이니까요.
그리고 만약에 /dev/ttyS0 가 디바이스 드라이버라면 문제가 있습니다. 예로 시리얼포트가 8개가 있다고 한다면,
]$ ls -al | grep ttyS crw-rw---- 1 root uucp 4, 64 7월 3 14:18 ttyS0 crw-rw---- 1 root uucp 4, 65 7월 3 14:18 ttyS1 crw-rw---- 1 root uucp 4, 66 7월 3 2007 ttyS2 crw-rw---- 1 root uucp 4, 67 7월 3 2007 ttyS3 crw-rw---- 1 root uucp 4, 68 7월 3 2007 ttyS4 crw-rw---- 1 root uucp 4, 69 7월 3 2007 ttyS5 crw-rw---- 1 root uucp 4, 70 7월 3 2007 ttyS6 crw-rw---- 1 root uucp 4, 71 7월 3 2007 ttyS7
이렇게 통신 포트별로 이름을 바꾸면서 다비이스 드라이버를 작성해서 올려야 합니다. 포트 번호만 다르고 처리하는 방법은 같은데, 통신 포트 개수만큼 소스를 수정하고 모두 컴파일해서 등록해야 된다면 매우 불편할 것입니다.
insmod
그래서 실제로는 하나의 디바이스 드라이버를 만들어서 커널을 올립니다. 커널을 올릴 때, 다른 디바이스 드라이버와 구별할 수 있도록 번호를 앞 가슴에다 부착하고 커널에 올립니다. 이 번호가 주 장치 번호, 주 번호가 되겠습니다.
insmod user_device_name
이렇게 insmod 명령을 실행하면 user_device_name 디바이스 드라이버 안에 주 번호를 몇 번으로 등록할 지 커널에 요청하는 코드가 들어 있습니다. 즉, user_device_name 디바이스 드라이버를 만들 때부터 프로그래머에 의해 주 장치 번호가 경정됩니다. 커널은 디바이스 드라이버에서 요청하는 장치 번호로 user_device_name 디바이스 드라이버를 커널 영역으로 로드합니다.
여기 글에서는 user_device_name 가 주 번호를 250을 사용한다고 하겠습니다.
mknod
이제 커널에서는 디바이스 드라이버를 사용할 준비가 되었습니다. 그러나 아직 커널만 알고 밖에서는 아무도 모릅니다. 커널 밖에서도 이 디바이스 드라이버를 사용할 수 있도록 공개해 주어야 하는데, 그냥 공개하기 보다는 응용 프로그램이 접근하기 쉽도록, 또한 같은 장치이면서 내부에 처리하는 번호가 다르다면 하나의 디바이스 드라이버에서 모두 처리할 수 있도록, 결국 응용프로그램에서 쉽게 사용할 수 있도록 가상 파일 시스템으로 제공해 줍니다.
그것이 바로 /dev/장치명이 되겠습니다.
]# mknod /dev/user_device_S0 c 250 0
]# mknod /dev/user_device_S1 c 250 1
]# mknod /dev/user_device_S2 c 250 2
]# mknod /dev/user_device_S3 c 250 3
]# mknod /dev/user_device_S4 c 250 4
/dev 안에 있는 아이템을 계속 장치명이라고 말씀드렸습니다만 정확한 명칭이 node 라고 하더군요. 그래서 명령어 이름이 mknod 인것으로 생각됩니다.
응용프로램과 커널 그리고 디바이스 드라이버
자, 이제 응용프로그램에서 다시 보겠습니다.
fd = open( "/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK );
프로그램에서는 /dev/ttyS0 만 언급햇습니다. 실제 디바이스 드라이브 파일 명이 아닙니다. 이 프로그램 코드는 당연히 커널로 전송되어지고 커널에게 부탁하게 됩니다. 커널은 /dev/ttyS0에서 주 장치 번호를 확인합니다. 또한 주 장치를 보고 커널에 등록된 디바이스 드라이버중에 장치 번호에 해당하는 디바이스 드라이버를 찾아서 응용 프로그램의 open()에 대한 명령을 전송해 줍니다. 이때, 함께 전송되는 것이 /dev/ttyS0에 해당하는 부 장치 번호입니다.
디바이스 드라이버는 커널로부터 받은 부 장치 번호를 가지고 자신이 처리하는 여러 장치 중 어느 장치를 처리할 지를 파단하게 됩니다.
(1) |
(2) |
(3) |
(4) |
(5) |
(6) |
(7) |
(8) |
(9) |
(10) |
crwxrwxrwx | 1 | root | tty | 4 | 64 | Jan | 1 | 2006 | ttyS0 |
crwxrwxrwx | 1 | root | tty | 4 | 65 | Jan | 1 | 2006 | ttyS1 |
crwxrwxrwx | 1 | root | tty | 4 | 66 | Jan | 1 | 2006 | ttyS2 |
crwxrwxrwx | 1 | root | tty | 4 | 67 | Jan | 1 | 2006 | ttyS3 |
즉, /dev/ttyS0 장치를 사용한다면,
- 커널은 /dev/ttyS0 의 주 장치 번호 4번에 해당하는 디바이스 드라이버를 찾고
- 디바이스 드라이버에 부 장치 번호 64를 전송해 주면,
- 디바이스 드라이버는 자기가 처리하는 여러 통신 포트 중에 부 장치 번호인 64로 처리할 포트를 알게 됩니다.