You are on page 1of 187

Overview of Imbedded System

• Imbedded system : computer system fixed for only a specific purpose different to general PC, but it is
operated under simple OS environment such as imbedded LINUX, or imbedded RTOS. It is small and
compact type micro-controller operating with OS since the many functions such as multimedia contents,
network, various I/O drivers are needed within one micro-controller.
• LINUX host PC and target imbedded system (ARM family processor Xscale PXA255)
• ARM chip is very popular in imbedded system because it is RISC type processor
• Hyper-terminal function (minicom exec-file on LINUX) to show communication between host and target
- thru serial port
- initial display by boot-loader of target system
• Boot-loader : it is similar to Monitor program.
- this program code is located at Xscale start address.
- initialize all of peripheral chips.
- load Kernel from Flash to the RAM.
- Provides several commands.
Porting Imbedded System (1)

• Porting the boot-loader of target system (blob)


- expand boot-loader compressed file proper to target imbedded system (unique to target H/W) on host
PC : tar exec-file is used on LINUX
- compile boot-loader source file on host PC : ARM cross c-compiler is used on LINUX ( host PC
executes only the executable files compiled by Intel compiler, but target imbedded system operates
only the file compiled by ARM compiler.) The compile procedure on LINUX is to configure a make file
at first and then use this make file to compile (likely batch file).
- Down load the boot loader binary file thru JTAG cable from the parallel port of host PC to JTAG port
of the target system. In order to program a device (flash ROM), JTAG exec file is used.
- The binary boot-loader is localized into the initial start pointer on Flash memory
• Porting the kernel of target system
- expand kernel compressed file proper to target imbedded system on host PC.
- compile kernel source file on host PC.
- Down load kernel binary file (zImage) thru serial cable from the serial port of host PC to serial port of
the target system. In order to transfer zImage file to RAM of target system, the blob command
“download kernel” is used on hyper terminal of host PC. On LINUX prompt, the linux command
“uuencode zImage zImage dev>ttyS0” is used to download zImage file. After finishing download
zImage, the zImage must be moved to flash ROM area by using blob command “flash kernel”, where
“kernel” is predefined location name in bootloader.
- Or the blob command “tftp zImage kernel” is used to transfer zImage file thru ethernet port.
Porting Imbedded System

• bootloader, kernel, ramdisk, user file system are located in flash ROM
• When the imbedded system is booted by power-on, boot-loader is accessed at first. Bootloader
initializes the all peripheral devices, and transfer kernel, ramdisk, userfile from flash ROM to RAM, and
give the control to kernel finally.
Install Linux & Win2000 on Host PC (1)

• MBR(Master Boot Record), boot manager


• In order to make a multi-boot system of Win2000 and LINUX, what must be done ?
- At booting, MBR is first accessed. As the boot-loaders of OS’s are registered in MBR, last installed boot-
loader will be accessed.
- The boot-loader of Win2000 is searched at first. Therefore, Win2000 cannot identify LINUX boot sector.
- LILO(Linux Loader), bootsect.lnx must be set on the root directory of Win2000.
- In “boot.ini” file on root directory of Win2000, the boot OS’s are described in order to be selected by user.
• http://wiki.kldp.org/wiki.php/LinuxdocSgml/LILO for multi-boot
• http://www.multizine.co.kr/index.php?cat=163
• http://hlug.hanyang.ac.kr/~freekgb/html/seminar/lvsp/2-5-윈도우_9x_윈도우2000_리눅스_멀티부팅.html
• http://wowlinux.com/information/freshmanview.html?db=freshman&id=77&view=1
Install Linux & Win2000 on Host PC (2)

• 13GB primary mater IDE HDD( C: , D:) and 4GB primary slave IDE HDD (E:)
• 1.3GB HDD consists of 8GB(C: drive) and 4 GB(D: drive) partitions having NTFS and FAT32 file
systems, respectively.
• Partitions of HDD :
- capacity = Cylinder > track > sector > bytes : 1024 >255>63>512
- head, cylinder, track, sector, cluster.
- primary and extended logic area.
- At most, 4 primary areas(C, D, E, F drives) in one physical HDD.
- Main boot sector is located in primary drive.
- In LINUX, two physical IDE(or SCSI) HDD’s are expressed as “hda” and “hdb”(or “sda” and “sdb”).
- “hda1” and “hda2” are two primary drives in one physical HDD. “hda5” and “hda6” are logical extended
drives.
Install Linux & Win2000 on Host PC (3)

• Install wowlinux paran v7.1:


- Win2000 is installed at C: drive (primary partition 8GB, NTFS), data is at D: drive (extended logic
partition 4GB, FAT32).
- LINUX is installed at 4GB primary slave HDD, as “hdb”.
- partitioned as hdb1: \ ( primary 2.5GB root directory, ext2 file system) , hdb5 : swap ( extended logic
256MB swap directory), hdb6 : \home (extended logic1.3GB home directory, reiser file system)
- At root directory, 554 packages (about 1.3GB) are installed.
- LILO is located at boot sector in “hdb”. “bootsect.lnx” file must be located in “C:\” of Win2000 root
directory, and “boot.ini” file located also in “C:\” of Win2000 root directory, must contains the
information of LINUX boot sector.
- establish root and user login : . /../home/fiberamp …
- GNOME manager of X-window on LINUX , and LINUX terminal program to use LINUX command.
What is LINUX ? Why is imbedded system ?

• Ubuntu, CentOS, Debian, Fedora, Sulinux, wow linux 등 , open source


• 다수의 사용자들이 동시 접속하여 병행 타스크 처리가 가능하고 사용자 관리 및 보안이 강화된 운영체제
• 리눅스 기반의 X-window, GNOME
• 임베디드 시스템의 필요성 : navigator, PMP, MP3 player, home automation gateway, 우리 랩에서 개발
한 원격제어 탐사로보트와 같이 특정한 목적의 복잡한 응용을 수행하는 기기이기 때문에 운영체제가 탑
재될 필요가 있고 이러한 운영체제에서 응용 프로그램만을 인스톨해서 동작시키는 XIP(eXecute In
Place) 기능을 가진다 . 이를 위해 필요한 최소한의 자원으로 구성된 리눅스 커널을 큰 용량의 HHD 가
없는 작은 규모의 저전력 컴퓨터 하드웨어의 메모리에 이식하고 하드가 없기 때문에 ramdisk 개념의 메
모리 가상 하드디스크를 구현해서 사용한다 .
• 개발환경 : HP(Host PC) 에 리눅스 운영체제를 갖추고 거기에 있는 라이브러리 ( 다양한 ~API, 다양한 드
라이버 등 ) 를 제공 받아 응용 프로그램을 개발하고 TB(Target Board) 의 프로세서 타입에 맞는 컴파일러
를 사용해서 실행 이미지를 만든 다음 TB 에 이식해서 TB 의 리눅스 위에서 돌아가도록 한다 .
Getting Fedora 10

• Mirror 및 Bit Torrent 로부터 다운로드 , Bit Torrent 는 P2P 와 같이 같은 그룹의 인접한 relay 분산 다운
로드 방식으로 여러 컴퓨터들이 동시에 나눠서 다운 받아 전달하는 식이다 . Bit Torrent 의 경우 client 프
로그램을 설치할 필요가 있음 .
• i386 은 Intel, AMD 사 프로세서 , x86_64 는 Intel ATOM 230, Core 2 Duo, Xeon, AMD 사의 Athlon 64,
Sempron 64, Opteron 와 같은 병렬프로세서 급 , ppc 는 Macintosh 를 비롯해서 다른 프로세서들은 ppc
• Live, DVD, CD 의 형태로 다운 받을 수 있는데 Live 는 작은 용량으로 일단 부팅시켜 사용해 볼 수 있고
이를 인스톨할 수 있다 . ISO 의 확장자를 가진 미디어 DVD, CD 이미지를 그대로 burning 해서 그것으로
부팅시켜 인스톨한다 . 인터넷 상에서 다운 받으면서 인스톨할 수 있는 최소 부트 CD 가 있다 . 다음은
mirror 에서 다운받을 수 있는 파일들이다 . 여기서 arch 는 인스톨할 컴퓨터의 프로세서 타입 즉 i386,
x86_64, ppc
Full distribution on DVD : fedora/linux/releases/10/Fedora/arch/iso/F-10-arch-DVD.iso
Live image : fedora/linux/releases/10/Live/arch/iso/F-10-arch-Live.iso,
fedora/linux/releases/10/Live/arch/iso/F-10-KDE-arch-Live.iso
Minimal CD boot media : fedora/linux/releases/10/Fedora/arch/os/images/boot.iso
• 다운받을 때 파일 에러 검증을 위해 http://lists.gnupg.org/pipermail/gnupg-
announce/2004q4/000184.html. 에서 SHA1SUM.EXE 를 다운 받아 CMD 창에서 실행함으로써 다운 받
은 ISO 파일에 대해 에러 검색
• 다운 받은 Fedora iso 파일을 CD 또는 DVD, USB flash memory 가 있는데 roxio easy media creator,
nero burning ROM5, Nero express 6, ISO recorder V2 power toy 를 시용하여 구울 수 있다 .
• Fedora 인스톨 도움말 문서 관련 사이트는 http://docs.fedoraproject.org/install-guide/f10/en_US/
• 전반적인 리눅스 관련 사이트 www.linux.co.kr
• 실시간 원격지원 , 이메일 , 포럼 , 문서들을 통해 지원 받을 수 있다 . fedoraproject.org,
docs.fedoraproject.org, forum.fedoraproject.org
Getting Fedora 10

• fedoraproject.org에서 MIRROR 를 통해 다운 받는데 http://fedoraproject.org/ko/get-fedora 거리상 가까


운 일본 사이트에서 LIVE 를 다운 받음 .
• http://fedorahosted.org/liveusb-creator에서 liveusb-creator 를 다운 받아 설치하고 USB 에 live
image 를 심어 부팅할 수 있다 . 잘 않되는 이유는 아마도 대부분의 USB flash memory 의 파일시스템
이 FAT 이고 VFAT, ext2, ext3 가 되어야 할 것 같음 .
Getting Fedora 10

• iso 파일들이 제대로 다운 받았는지 검증하기 위해 sha1sum.exe 를 콘솔창에서 실행시켜 나타난 해쉬


(hash) 들과 생성된 sha1sum 을 notepad 와 같은 텟스트 창에서 열어 동일하면 제대로 모든 내용들이 다
운받게 됨 . 일종의 MD5 check sum 개념과 같음 .
• http://lists.gnupg.org/pipermail/gnupg-announce/2004q4/000184.html 에서 sha1sum.exe 를 다운 받아
iso 파일들이 있는 폴더에 저장하고 실행 . Sha1sum 파일이 생성 않되는데
• ftp://ftp.riken.jp/Linux/fedora/releases/10/Fedora/i386/iso/에서 Fedora-10-i386-DVD.iso을 (3.4GB 정도 )
다운 받아 4.7GB DVD-R 에 Nero Express 6 과 같은 burning 프로그램을 사용해서 굽는다 . 이 때 주의
할 점은 대부분 burning program 이 ISO9660 으로 변환해서 미디어에 굽는데 이 단계를 스킵할 필요 ?
Installation multi boot with Linux

• Druid 를 사용하여 linux 의 boot, swap, root 파티션 나누기


• 하나의 HDD 에 주파티션 (OS 영역 드라이브 C:), 확장파티션 ( 데이터 논리 드라이브 D:, E;)
• 두 개의 HDD 에 하나 (primary master) 는 win98(C 드라이브 ) 및 데이터 (E 드라이브 ) 가 있고 , 다른
하나 (primary slave) 에는 win95(D 드리이브 ) 및 데이터 (F, G 드라이브 ) 가 깔려 있는 PC 에서 두 번
째 psHDD 의 파티션을 삭제하고 거기에 linux 를 설치하고자 한다 .
(4) 먼저 win98 이 돌아 가고 있는 상황에서 도스창에서 fdisk 컴맨드를 사용하여 2 번 HDD(win 95 가 깔
려 있는 드라이브 D 인 기본 도스 분할 영역과 데이터가 있는 드라이브 F, G 인 확장 도스 분할 영역 ) 를
선택하고 먼저 데이터가 있는 확장 도스 분할 영역 파티션을 날린다 . 그리고 나서 win95 운영체제가 깔
려 있는 기본 도스 분할 영역의 파티션을 날린다 . psHDD 의 파티션 삭제는 linux 설치시에 할 수도 있
다.
(5) 다시 PC 를 재부팅하면서 del( 또는 F2) 키를 쳐서 CMOS 셋업에서 CD 에서 먼저 부팅하는 것으로
설정을 하고 나가면 linux 설치 CD 로부터 부트가 되면서 언어 , 지역 , 시간대 , 키보드를 설정하고 자
동 또는 수동 설치 옵션이 나온다 .
(6) psHDD 에 linux 를 설치하고 멀티 부트를 가능하게 하려면 수동 설치를 해야 한다 . 수동 설치 옵션에서
현재 연결되어 있는 HDD 를 보여 주는데 현재 primary 에 두 개의 HDD 가 장착되어 있으므로 IDE1
master, IDE1 slave 로 나타나고 linux 를 까는 대상 HDD 인 IDE1 slave 를 선택한다 . 만약 앞서와 같이
파티션이 삭제되어 있지 않으면 여기서 삭제할 수 있다 . ( 최근의 Fedora 버전에서는 수동 설치로서
Druid 파티션 나누기가 있어서 이를 선택하는데 파티션을 제거한 후 비어 있는 HDD 에 swap 파티션 -
보통 PC 의 메모리의 두 배 , boot 파티션 , root 파티션으로 나눈다 )

http://www.linux.co.kr/에서 멀티 부팅 검색해서
“ 두개의 하드에서의 멀티부팅”
http://www.linux.co.kr/home/lecture/?leccode=10237
Primary master HDD, dev/hda Primary slave HDD, dev/hdb secondary master CD, dev/hdc

Win98, C: drive, dev/hda1 Win95, D: drive, dev/hdb1 data, H: drive, dev/hdc

Data, F: drive, dev/hdb2


secondary slave DVD, dev/hdd
Data, E: drive, dev/hda2

Data, G: drive, dev/hdb3 data, I: drive, dev/hdd

                             

IDE1 IDE0

주파티션 , 기본 도스 분할 영역 확장파티션 > 논리 드라이브들 , 확장 도스 분할 영역

Primary master HDD, dev/hda Primary slave HDD, dev/hdb secondary master CD,
dev/cdrom
Win98, C: drive, dev/hda1 Linux /boot, dev/hdb1

Linux swap, dev/hdb2


secondary slave DVD, dev/?
Data, E: drive, dev/hda2

Linux /root, dev/hdb3

                             

IDE1 IDE0
Installation multi boot with Linux
1) 그 다음에 멀티 부트 기능을 제공하는 부트로더인 LILO 또는 GRUB 가 있는데 여기서는 LILO 의
경우를 설명한다 . LILO installation 메뉴는 다음과 같이 세 가지 선택이 나온다 .
. On C:
. Create a boot disk
. On partition /boot
“ON C:” 를 선택하면 1 번 하드 ( 윈 98 하드 ) 의 마스터 부트레코드 (MBR) 에 LILO 를 설치하여 리
눅스 설치가 끝난 후 피시를 리부팅하면 리눅스로만 부팅할 수 있다 .( 윈 98 하드 내용은 영향이 없
다 . 단지 부팅만 문제된다 ) 그러므로 중간에 설치가 문제가 되어도 윈 98 로 부팅 할 수 없다 . ( 윈
98 의 시동디스크를 사용하여 부팅 후 fdisk /mbr 명령으로 수정이 가능하다 ) 여기서는 가장 안전한
“ Create a boot disk” 를 선택한다 . 이는 리눅스 설치가 완료되었을 때 리눅스를 디스켓에서 부팅하
게 구성하는 것이다 .( 디스켓을 넣지 않으면 윈 98 로 부팅한다 ) 그 후에 리눅스에서 lilo.conf 라는
파일을 수정하여 하드에서 윈 98 과 리눅스를 선택 부팅하게 설정하는 것이다 . 따라서  혹시 리눅스
설치가 잘못되어도 윈 98 이 설치된 1 번 하드의 MBR 을 수정하지 않으므로 윈 98 부팅에는 아무
런 문제가 없다 .
4) Primary ethernet (eth0) 의 IP, subnet mask, gateway 들을 설정 , 시간대 , 방화벽 여부 ( 임베디드
TB 와 LAN 을 연결해서 전송해야 하기 때문에 방화벽을 해제 ) 등을 설정 .
5) 사용자 계정 및 root 암호를 입력한다 .
6) 설치 패키지를 선택해서 설치를 시작한다 . 설치 말기에 앞서 LILO 에서 linux 설치 디스크 옵션에
따라 drive A: 에 포맷된 floppy disk 를 넣으라는 메시지와 함께 floppy 에 linux boot loader 를 설치
하기 시작한다 .
7) 설치가 다 되면 X window 화면에서 그래픽 모드의 로그인 창이 나온다 . 로그인은 root 로 패스워드
는 앞서 설정한 것으로 로그인 한다 . X window 의 터미널을 열어 (ctl+alt+F2) linux text command 창
을 띄우고 여기서 root prompt 가 나타남을 확인한다 . “shutdown –r now” 를 쳐서 다시 부팅을 시킨
다.
Installation multi boot with Linux
1) BIOS 로부터 부트 될 때 del( 또는 F2) 를 쳐서 CMOS 셋업에서 CD 에서 C 로 부트시켜서 win98
이 정상적으로 작동되는지 확인해 본다 .
2) 다시 재부팅해서 CMOS 셋업에서 C 에서 A 로 부트 시켜서 drive A 에 삽입된 linux 부팅 디스켓
으로부터 부팅시켜 X-window 가 나타남을 본다 . 터미널을 열고 여기서 etc/lilo.conf 를 vi 에디터로
열고 설정을 변경해서 BIOS 부트되면서 win98 또는 linux 어떤 것을 선택할 것인가에 대한 선택
메시지가 나타나도록 함으로써 다음 번에는 linux 부팅 디스켓 없이 이 메시지에 의한 선택으로
win98 또는 linux 부팅을 선택하도록 한다 .

etc/lilo.conf

/etc/fstab boot = /dev/hdb1


/dev/hdb1 /boot ext2 defaults 1 1 -> boot = /dev/hda1
/dev/hdb2 swap swap defaults 0 1
/dev/hdb3 / ext2 defaults 1 2 vga = normal
proc /proc proc defaults 0 0 read-only
devpts /dev/pts devpts defaults 0 0 prompt
/dev/cdrom /cdrom iso9660 ro,noauto,user 0 0 timeout = 30
/dev/fd0 /floppy auto noauto,user 0 0 image = /boot/vmlinuz
/dev/hda1 /windows auto noauto,user 0 0 label = linux
root = /dev/hdb3
image = /boot/vmlinuz.suse
label = suse
root = /dev/hdb3

추가 other = /dev/hda1
Label = dos
Table = /dev/hda
Manual partition by using Druid
• 리눅스에서는 HDD 각각을 hda, hdb, hdc… 또는 sda, sdb 로 나눈다 . dos 에서는 EIDE 에 primary
master, promary slave, secondary master, secondary slave 와 같이 네 개의 디바이스들을 연결할 수 있고
primary 의 경우 IDE1, secondary 의 경우 IDE0 로 인식한다 . 일반적으로 EIDE 는 primary, secondary
두개의 포트를 제공하고 하나의 포트에 master/slave 두개의 커넥터를 사용하여 연결할 수 있게 되어 있
고 , primary 에는 HDD 를 master, slave jumper 로 셋팅해서 두 개를 연결하고 secondary 에는 CD,
DVD drive 를 연결해서 사용한다 . 하나의 HDD 에 OS 를 올릴 주파티션과 데이터를 저장할 확장파티션
으로 나누고 확장파티션은 다시 논리 드라이브로 쪼갤 수 있다 . 리눅스에서는 primary master 가 hda 가
되고 여기에 root, swap, boot 파티션을 나눠서 hda1, hda2, hda3 로서 표기한다 . primary slave 에서는
hdb 가 되고 여기에 hdb1, hdb2, hdb3
• Druid 를 사용하여 수동으로 linux 의 root, swap 파티션 나누기 , 기존의 파티션을 삭제할 수도 있다 .
• Swap 영역은 PC 의 주메모리의 용량이 제한되어 있어서 다양한 프로세스를 수행하기 위해 페이징 기법
을 사용하고 별로 사용되지 않는 코드는 주메모리에서 삭제하고 HDD 로부터 필요한 구성 요소들을 주메
모리로 올림으로써 HDD 를 가상메모리로 사용되는데 이 때 HDD 의 주메모리로부터 삭제된 코드 ( 또는
구성 요소들 ) 의 일시 장기 보관소라고 볼 수 있는 swapping 영역이 필요한데 이를 의미한다 . 여기서 주
메모리 사이즈의 두 배 정도이면 충분하고 주메모리가 1GB 라고 해서 swap 파티션 사이즈를 2GB 까지
크게 할 필요는 없고 1GB 라도 무방하다 .

www.linux.co.kr에서 리눅스 탭에서 강좌 리눅스 설치와 초기설정


http://www.linux.co.kr/home/lecture/index.php?cateNo=1&secNo=27&theNo=&leccode=10915
Manual partition by using Druid
(1) 새로생성” 버튼에서 다음 표와 같이 마운트할 지점을 “ /” 로 해서 root 파티션을 만든다 .

메    뉴 설명 및 옵션 예    제
마운트할 지점 디렉토리 경로를 설정 /
파일시스템의 유형을 선택
파일시스템 유형 옵션 ) ext2, ext3, physical volum (LVM), ext3
software RAID, swap, vfat

할당 가능한 드라이브 하드디스크 종류 및 순서를 나타냄 [*]sda

설정하고자는 용량을 MB 단위로 작성


옵션 ) 1000MB(1GB) 로
용량 (MB)    -. 고정용량 설정
   -. 다음의 용량까지 모두 채움 (MB) [*] 고정용량선택
   -. 최대 가능한 용량으로 채움
첫번째 (primery) 파티션으로
파티션의 첫번째에 설정하도록함 선택하지 않음

root
swap
Manual partition by using Druid

(2) 새로생성” 버튼에서 다음 표와 같이 마운트할 지점을 “ ”로 해서 swap 파티션을 만든다 .


(3) 편집 버튼을 눌러 남아 있는 공간까지 root 에 편입시키기 위해 “최대 가능한 용량으로 채움 “

메    뉴 설명 및 옵션 예    제
마운트할 지점 디렉토리 경로를 설정
파일시스템의 유형을 선택
파일시스템 유형 옵션 ) ext2, ext3, physical volum (LVM), swap
software RAID, swap, vfat

할당 가능한 드라이브 하드디스크 종류 및 순서를 나타냄 [*]sda

설정하고자는 용량을 MB 단위로 작성


옵션 )
258MB 로 설정
용량 (MB)    -. 고정용량
[*] 고정용량선택
   -. 다음의 용량까지 모두 채움 (MB)
   -. 최대 가능한 용량으로 채움
첫번째 (primery) 파티션으로
파티션의 첫번째에 설정하도록함 선택하지 않음

LVM(Logical Volume Management)

• LVM 은 여러 개의 물리적 저장장치 ( 물리적 파티션 볼륨 , C: D: drive) 들을 하나의 볼륨 안에 통합


관리 할수 있게 한다 . 즉 작은 하드디스크 두 개를 붙여서 하나의 큰 하드 디스크처럼 사용할 수도
있다 .

• LVM 의 편리성 : 여러 가지 서비스를 사용하다가 용량이 부족할 경우 디스크 교체 없이 하드디스크


를 추가 한 후 같은 볼륨으로 인식시키면 그 즉시 서비스 제공이 가능하다 .

• LVM 과 비교되는 것으로 RAID 라는 것이 있다 . RAID 역시 두 개의 하드디스크를 하나로 묶어서 하


나의 디스크처럼 사용이 가능하다 . RAID 의 목적은 두 개의 하드디스크를 하나로 묶음으로서 하나
의 데이터를 두 곳에 나누어 저장하는 방식으로 응답 속도의 향상을 꾀한다든지 혹은 하나의 데이터
를 두 곳에 똑같이 저장하여 백업의 효과를 나타내는 두 가지의 목적이 있다 .

• LVM 이 RAID 의 첫 번째 목적에는 어느 정도 대처가 가능하나 두 번째 목적은 불가능하다 . 그러나


서비스의 중지 없이 디스크 용량을 늘린다는 것은 RAID 에서는 불가능한 일일 뿐만 아니라 , 해당
용량만큼의 디스크를 준비하고 백업 후 용량 추가 후에는 다시 복원을 해야만 하는 복잡한 과정을 거
칠 필요 없이 바로 추가가 가능하다는 장점은 LVM 의 충분한 사용 이유가 된다 .
GOOGLE 에서 lvm 으로 검색하면
http://blog.naver.com/absolaxis/100065099808

http://coffeenix.net/data_repository/htm/01-05-4.htm
LVM(Logical Volume Management)

• LVM 에 사용할 디바이스명은 /dev/sda6, /dev/sda7, /dev/sda8 의 3 개의 파티션이 존재하며 , 용량


은 각각 60M, 60M, 80M 이다 . 아래 그림과 같이 LV 을 할당한다 .

• 리눅스에서 mkfs –t ext3 /dev/sda3 하면 리눅스 깔리면서 할당된 sda3 파티션을 ext3 파일시스
템으로 만들고 mount -t ext3 /dev/sda3 /mnt/backup 과 같이 /mnt/backup 에 마운트 시켜서 sda3
파티션 ( 일종의 논리 드라이브 ) 를 접근해서 사용하고 끝나면 unmount 시킨다 . fdisk 는 window 에
서의 디스크관리에서 데이터 영역 파티션을 재조정하는 식으로 사용된다 .

dev/sda6(60MB) sda6 sda6 PV0


VG0 LV LV0
dev/sda7(60MB) sda7 sda7 PV1
VG
fdisk -t PV
dev/sda7(80MB) sda8 sda8 PV2 sda8 PV2 sda8 PV2
1. 먼저 fdisk 명령을 사용하여 /dev/sda6(60MB) 과 /dev/sda7(60MB), /dev/sda8(80MB) 을
LVM 파일시스템으로 변경한다 .
[root@localhost ~]# fdisk /dev/sda
Command (m for help): m
Command action
a toggle a bootable flag Command (m for help): p
b edit bsd disklabel Disk /dev/sda: 60.0 GB, 60011642880 bytes
c toggle the dos compatibility255flag
heads, 63 sectors/track, 7296 cylinders
d delete a partition Units = cylinders of 16065 * 512 = 8225280 bytes
l list known partition types
m print this menu Device Boot Start End Blocks Id System
n add a new partition /dev/sda1 * 1 2549 20474811 7 HPFS/NTFS
o create a new empty DOS/dev/sda2
partition table 2550 5099 20482875 7 HPFS/NTFS
p print the partition table /dev/sda3 5100 7139 16386300 83 Linux
q quit without saving changes /dev/sda4 7140 7296 1261102+ f W95 Ext'd (LBA)
s create a new empty Sun disklabel
/dev/sda5 7140 7270 1052226 82 Linux swap / Solaris
t change a partition's system id
/dev/sda6 7271 7278 64228+ 83 Linux
u change display/entry units/dev/sda7 7279 7286 64228+ 83 Linux
v verify the partition table /dev/sda8 7287 7296 80293+ 83 Linux
w write table to disk and exit
x extra functionality (expertsCommand
only) (m for help): l

0 Empty 1e Hidden W95 FAT1 80 Old Minix be Solaris boot


1 FAT12 24 NEC DOS 81 Minix / old Lin bf Solaris
2 XENIX root 39 Plan 9 82 Linux swap / So c1 DRDOS/sec (FAT-
3 XENIX usr 3c PartitionMagic 83 Linux c4 DRDOS/sec (FAT-
4 FAT16 <32M 40 Venix 80286 84 OS/2 hidden C: c6 DRDOS/sec (FAT-
5 Extended 41 PPC PReP Boot 85 Linux extended c7 Syrinx
6 FAT16 42 SFS 86 NTFS volume set da Non-FS data
7 HPFS/NTFS 4d QNX4.x 87 NTFS volume set db CP/M / CTOS / .
8 AIX 4e QNX4.x 2nd part 88 Linux plaintext de Dell Utility
9 AIX bootable 4f QNX4.x 3rd part 8e Linux LVM df BootIt
a OS/2 Boot Manag 50 OnTrack DM 93 Amoeba e1 DOS access
b W95 FAT32 51 OnTrack DM6 Aux 94 Amoeba BBT e3 DOS R/O
CoCommand (m for help): t
Partition number (1-8): 6
Hex code (type L to list codes): 8e
Changed system type of partition 6 to 8e (Linux LVM)

Command (m for help): t


Partition number (1-8): 7
Hex code (type L to list codes): 8e
Changed system type of partition 7 to 8e (Linux LVM)

Command (m for help): t


Partition number (1-8): 8
Hex code (type L to list codes): 8e
Changed system type of partition 8 to 8e (Linux LVM)

2. Fdisk 에서 빠져 나온 후에 리눅스를 reboot 시킨다 . PV(Physical Volume) 를 생성한다 .

[root@localhost ~]# pvcreate /dev/sda6


Physical volume "/dev/sda6" successfully created
[root@localhost ~]# pvcreate /dev/sda7
Physical volume "/dev/sda7" successfully created
[root@localhost ~]# pvcreate /dev/sda8
Physical volume "/dev/sda8" successfully created
[root@localhost ~]# pvscan
PV /dev/sda6 lvm2 [62.72 MB]
PV /dev/sda7 lvm2 [62.72 MB]
PV /dev/sda8 lvm2 [78.41 MB]
Total: 3 [203.86 MB] / in use: 0 [0 ] / in no VG: 3 [203.86 MB]
3. VG(Volume Group) 를 생성한다 . 일단 여기서 두개의 PV 인 /dev/sda6 와 /dev/sda7 의 120MB 를
VG0 으로 만든다 .

[root@localhost ~]# vgcreate VG0 /dev/sda6 /dev/sda7


Volume group "VG0" successfully created "/dev/sda8" is a new physical volume of "78.41 MB"
[root@localhost ~]# vgscan --- NEW Physical volume ---
Reading all physical volumes. This may take a while... PV Name /dev/sda8
Found volume group "VG0" using metadata type lvm2 VG Name
[root@localhost ~]# pvdisplay PV Size 78.41 MB
--- Physical volume --- Allocatable NO
PV Name /dev/sda6 PE Size (KByte) 0
VG Name VG0 Total PE 0
PV Size 62.72 MB / not usable 2.72 MB Free PE 0
Allocatable yes Allocated PE 0
PE Size (KByte) 4096 PV UUID gE0yE2-ansY-emCr-Qkbq-aE71-HpzM-M1bmOY
Total PE 15
Free PE 15
Allocated PE 0 위의 PV 를 보면 앞서 VG0 를 만들 때
PV UUID x7Lvny-9GK9-qJbz-Jiib-2xNi-U4Qu-e0hMrD 2 개의 파티션만 묶었기 때문에
/dev/sda6 과 /dev/sda7 만 Allocatable
--- Physical volume ---
PV Name /dev/sda7
이 YES 로 되어 있다 .
VG Name VG0
PV Size 62.72 MB / not usable 2.72 MB
Allocatable yes
PE Size (KByte) 4096
Total PE 15
Free PE 15
Allocated PE 0
PV UUID Ob922l-zvh5-47VU-BACc-Bf4C-RrFp-0R8r1A
[root@localhost ~]# vgdisplay
--- Volume group ---
VG Name VG0
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0 4. VG0 의 120MB 가운데 100MB 를
Max PV 0 LV(Logic Volume)0 으로 만든다 .
Cur PV 2
Act PV 2 [root@localhost ~]# lvcreate -L 100M -n LV0 VG0
VG Size 120.00 MB Logical volume "LV0" created
PE Size 4.00 MB [root@localhost ~]# lvscan
Total PE 30 ACTIVE '/dev/VG0/LV0' [100.00 MB] inherit
Alloc PE / Size 0/0 [root@localhost ~]# lvdisplay
Free PE / Size 30 / 120.00 MB --- Logical volume ---
VG UUID LV Name
Q0q8CW-Z5JR-kszj-at0C-i65d-gTw5-N4S1MG /dev/VG0/LV0
VG Name VG0
LV UUID j2kU6O-iBSj-zEof-fmCR-PbdY-MeD6-IuFlQk
LV Write Access read/write
LV Status available
# open 0
LV Size 100.00 MB
Current LE 25
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:0
Boot loader(manager) for multi boot with Linux

• GRUB 의 멀티부트 메뉴 화면에서 [a], [c], [e] 키를 누르면 각각의 모드로 진입 할 수 있다 .


• [a] 를 입력한 모드는 kernel 의 파라미터를 추가할 수 있게 하는 모드이다 . 예를 들면 kernel
/boot/vmlinuz-2.6.9-36 ro root=LABEL=/ 라는 부분이 있을 경우 [a] 키를 누르면 ro root=LABEL=/ 이후
부분을 편집할 수 있게 된다 . 이는 시스템에 장애가 발생하여 단일 사용자 모드 (single) 로 들어가야 할
경우가 발생할때 커널 파라미터 맨 뒤에 single 이라고 입력하고 단일 사용자 모드로 진입 할 수가 있다 .
• [e] 모드는 멀티부트 메뉴의 리스트 항목을 직접 편집 할 수 있도록 도와 준다 . 간혹 [a] 키를 눌러 단일
사용자 모드 (single) 진입할 경우 커널패닉 현상이 발생할 수 있다 . 이와 같은 경우 [e] 모드에서
vmlinuz-2.6.9-36 라는 뒤에 single 이라고 추가하고 부팅하면 단일 사용자 모드 (single) 로 안전하게 진입
할 수 있게 된다 .
• Linux 부팅 후에 root 에서 grub 컴맨드를 쳐서 grub 메뉴에 비밀번호를 설정할 수 있다 .

편집모드에서 지원하는 키

e : 해당 라인을 편집한다 .       d : 해당 라인을 삭제한다 .


o : 명령 라인을 추가한다 .       b : 부팅을 시작한다 .
Boot loader(manager) for multi boot with Linux

• Win XP 와 linux 두 개의 운영체제를 다른 파티션에 깔고 부팅 시에 둘 중에 하나를 선택하기 위한 boot


loader 인 GRUB, LILO 가 있는데 GRUB 이 더 나음 .
• grub 의 환경설정을 담고 있는 파일은 /boot/grub/grub.conf 이다 . 대부분의 시스템 환경설정 파일들은
/etc 라는 디렉토리에 위치해 있지만  grub 는 boot 에 관련 되는 부분이므로 /boot/grub 라는 디렉토리에
존재하게 된다 .

① default=1
기본값으로 부팅되도록 설정하는 부분이다 . grub 선택화면에서 특별히 선택하지 않으면 여기에 설정되어
진 값에 해당하는 운영체제를 로딩한다 . 현재 설정인 1 값은 아래 항목중에서 제일 먼저 설정되어 있는
운영체제를 말한다 .

② timeout=5
grub 부트화면에서의 대기시간이다 . 단위는 초이다 . 현재 설정은 5 초간 선택이 없으면 default 에 설정된
값으로 부팅된다 .

③ splashimage=(hd0,0)/grub/splash.xpm.gz
부트 화면의 배경이미지를 지정하는 부분이다 . xpm 형태의 그림이미지를 압축한 xpm.gz 파일을 사용한다 .
(hd0,0) 의 뜻은 /dev/hda1 라는 뜻이다 .
default=1
timeout=5
http://www.linux.co.kr/에서 멀티 부팅 검 splashimage=(hd0,0)/grub/splash.xpm.gz
색 Hiddenmenu
title SULinux (2.6.9-34.EL)
        root (hd0,0)
        kernel /vmlinuz-2.6.9-34.EL ro root=LABEL=/
vga=773
Boot loader(manager) for multi boot with Linux
※ 참고 . 리눅스 디바이스 와 grub 디바이스와의 관계

1. 기본관계
  /dev/fd0 : (fd0) floppy?
  /dev/hda : (hd0) 설명 : SCSI 하드디스크인 경우에 첫번째 물리적인  디스크도 이 값에 해당한다 .
  /dev/hdb : (hd1)
 
2. 사용예
  /dev/hda1 : (hd0,0)
  /dev/hda4 : (hd0,3)

④ title SULinux (2.6.9-34.EL)


        root (hd0,0)
        kernel /vmlinuz-2.6.9-34.EL ro root=LABEL=/ vga=773
        initrd /initrd-2.6.9-34.EL.img
-. title SULinux (2.6.9-34.EL) : 부트 _ 엔트리 _ 설명
-. root (hd0,0) : root ( 하드디스크 디바이스명 , 부트 파티션명 )
-. kernel /vmlinuz-2.6.9-34.EL ro root=LABEL=/ vga=773 : kernel / 커널이미지경로 ro root= 루트 디바이스명 vga= 지원하는 그래픽해상도
-. initrd /initrd-2.6.9-34.EL.img : initrd / 초기화에 필요한 이미지 경로 ( 초기화 Ram Disk Loader)

⑤ windowns 가 설치되어 있을 경우
만약 windowns 와 같이 설치된 시스템이라면 아래와 유사한 설정이 추가 되어 있을 것 이다 .

title Windowns
        rootnoverify (hd0,1)
        chainloader +1

-. title Windowns : 부트 _ 엔트리 _ 설명


-. rootnoverify (hd0,1) : rootnoverify ( 윈도우가 설치되어 있는 하드디스크 디바이스명 , 파티션명 )
-. chainloader +1 : 윈도우 운영체제는 chains-load 에 의해서 부팅되는데 이것에 관한 설정이다 .

www.linux.co.kr에서 리눅스탭을 치고 강좌 “시스템부팅에 관한 모든 것”


http://www.linux.co.kr/home/lecture/index.php?cateNo=1&secNo=27&theNo=&leccode=10916
Installation Fedora9 for multi boot with Linux
• 현재 HP 는 2GHz clock Core 2 Duo E4500, 2GB 주메모리 , 39GB HDD 는 primary master 로서 20GB
C; 드라이브에 winXP 가 깔려 있고 , 19GB E: 드라이브에는 Fedora 가 깔려 있다 . D: 드라이브는
primary slave 로서 CD drive 가 할당되어 있다 . GRUB 이 boot manager 로서 winXP 또는 Fedora Liux
를 선택하여 부팅할 수 있다 . 하나의 HDD 에 두 개의 winXP, Fedora 의 주파티션들이 있고 Fedora 주
파티션을 삭제하고 다시 Fedora 를 설치한다 .
• Fedora9 설치 CD 4 장 가운데 첫 번째 것을 CD drive 에 넣고 PC 를 켜면 CMOS setup 에서 CD drive
로 제일 먼저 부팅 되도록 설정되어 있으면 설치 CD#1 으로 부터 설치가 시작된다 .
• root password, host name, Eth0 설정 , 키보드 자판 언어 , 시간대 , 파티션에서 “모든 파티션 삭제하고
디폴트 레이아웃 / 리눅스 파티션 삭제하고 디폴트 레이아웃 / 남은 공간에 디폴트 레이아웃 / 사용자 레
이아웃 /” 에서 “사용자 레이아웃”을 선택
• “ 사용자 레이아웃” 에서 WinXP 는 sda1(C: 드라이브 ) NTFS, 기존의 Fedora 는 sda3(E: 드라이브 )
에 ext3 파일시스템으로 되어 있음을 보여 준다 . 특히 19GB 의 Fedora 주파티션은 LVM 에 의해 관리
되도록 VG0(19040MB) 로 되어 있고 이를 다시 두 개의 LV 으로 나눠서 LV0 에는 ext3 로서 17024MB,
LV1 에는 swap 으로서 1984MB 로 할당되어 있다 .
sda1 20002MB,
sda2 196MB, /boot, ext3
sda3 19061MB, LVM PV, VG0>LV0(17024MB, /, ext3), LV1(1984MB, ,swap)

“ 페도라 리눅스 9”, 김선영 저 , 가메 ,


2007
Installation Fedora9 for multi boot with Linux
• 먼저 기존의 sda2, sda3 파티션을 삭제하고 삭제된 영역에 새로이 위와 비슷하게 파티션을 할당하는데
먼저 /boot 디렉토리에 200MB 고정 사이즈 , ext3 파일시스템으로 “새로 생성” 버튼을 눌러 sda2 파
티션을 생성한다 . 나머지 영역에 대해서 “새로 생성” 버튼을 눌러 LVM PV 파일시스템으로 sda3 파티
션을 생성한다 . “LVM” 버튼을 눌러 sda3 PV 에 VG0 를 명시하고 비슷한 방법으로 LV0 를 추가해서
/(root) 디렉토리에 17000MB 고정 사이즈 , ext3 파일시스템으로 LV0 를 생성하고 나머지에 NA 디렉토
리에 나머지 용량으로 해서 swap 파일시스템으로 LV1(2016MB) 을 할당해서 포맷을 시작한다 .
또 다르게는 VG0 에 /root, swap 외에 많은 응용 S/W 를 설치할 공간인 /usr( 많은 공간 할애 , 12GB),
다중 사용자 계정들을 위한 /home( 많은 공간 할애 , 5GB), 인쇄 스풀링 기능을 위한 /var, 임시파일
/tmp 등의 디렉토리로 해서 LV 을 할당할 수 있다 . 즉 VG0>LV0(/root), LV1(swap), LV2(/usr),
LV3(/home), LV4(/var), LV5(/tmp) 로 나눠질 것이다 . 만약 LVM 을 사용하지 않는다면 sda3(/root),
sda4(swap), … , sda8(/tmp) 가 될 것이다 . /root 로 로그인 하면 시스템 파티션이 아닌 다른 파티션들을
다른 파일 시스템으로 fdisk 나 mkfs 를 사용해서 변경시킬 수 있다 .

한 개의 HDD, primary master, /dev/sda 한 개의 CDROM, primary slave, /dev/cdrom

dev/sda1(20GB)
Win XP dev/sda2(200MB), /boot, ext3

dev/sda3(18800MB)
LV0, /root, ext3
PV0 이자 VG0
LV1, , swap
Installation Fedora9 for multi boot with Linux

• 부트로더 설치에서 /dev/sda ( 즉 HDD 의 MBR, master boot record) 에서 할 건지 , first sector of boot
partition /dev/sda2 에서 할 건지를 결정해야 하는데 뭐가 좋지 ?

• 부트로더 운영 체제 목록에는 기본적으로 Fedora 라벨과 Other 라벨이 나타나는데


Fedora /dev/VolGroup00/LogVol00 : root directory

Other /dev/sda1

여기서 Fedora 를 기본부팅으로 체크박스에 체크한다 . 그러면 나중에 GRUB 에서 엔터를 않 치면


Fedora 로 부팅된다 .

만약에 부트로더를 MBR 에 엮어서 문제가 생기면 DOS 시동디스크로 부팅시켜서 dos 에서 fdisk MBR
치면 복원된다 .

• “ 사무 및 생산성 , 소프트웨어 개발 , 서버”의 세 가지 체크 박스에 체크를 한다 . 랜을 연결하고 Fedora


및 Additional Fedora Software 에 대해 repository URL 을 수정하는데 그냥 스킵한다 . Fedora 의
repository URL 은 file:// /mnt/source

“ 지금 사용자 설정”의 라디어 버튼을 체크하면 “사무 및 생산성 , 소프트웨어 개발 , 서버”의 세 가지 체


크 박스에 체크 대신에 세부적인 설치 패키지들에 대한 선택을 할 수 있다 .

데스크탑 (GNOME, KDE, 등 ), 소프트웨어 개발툴 (JAVA, C), 서버 (FTP, DNS, 뉴스 , 메일 등 ), 응용


프로그램 ( 게임 , 그래픽 , 사운드 등 , 여기서 cdrom 을 굽자면 xcdroast 패키지 반드시 설치 ), 기반시
스템 (X 윈도우 시스템 , 다중 언어 사용을 위해 in-choose 패키지는 설치 ), 언어지원 ( 한국어 지원 설
정)
Installation Fedora9 for multi boot with Linux

• 4 개의 설치 CD 를 준비하라는 지시와 함께 계속 진행할지 않 할지 물어보고 계속 진행을 선택하면 CD1


에 있는 패키지를 설치하기 시작한다 . 1166 패키지 가운데 CD1 은 1~373 설치 , CD2 은 374~923 설
치 , CD3 는 924~1149 설치

• 설치가 완료되면 부트로더 설치라는 메시지가 보이고 이것이 완료되면 CD4 를 빼고 재부팅한다 .
• 재부팅 하면 GRUB 가 뜨면서 몇 초 내에 엔터를 치면 Fedora (2.6.25-14.fc9.i686), Other 둘 중 하나를
선택해서 부팅시킬 수 있다 .

• Fedora 를 선택해서 부팅하면 설정화면이 나타나고 라이센스 보고 , 사용자 계정 등록 ( userid: fiberamp,


name: Kim Iksang, PWD), 키베로스 또는 NIS 와 같은 네트워크 인증을 받으려면 “네트워크 로그인 사
용” 버튼을 누름 .

• 시간 설정 및 네트워크 시간 프로토콜 NTP(Network Time Protocol) 활성화 체크하든지 말든지 ( 여기서


는 일단 체크 않함 ). 원격시간서버는 0.fedora.pool.ntp.org, 1.fedora.pool.ntp.org, 2.fedora.pool.ntp.org

• 마지막으로 하드웨어 프로파일을 인터넷을 통해 보낸다 . UUID : 753a0829-4632-4dbf-8762-


bc844132191d, kernel version : 2.6.25-14.fc9.i686
Understanding the Linux kernel

• 멀티유저 , 그룹 , 프로세스 , 커널 , 파일시스템 , 메모리 관리 , 입출력 장치 관리 , 장치 드라이버

• 하드웨어 세그멘테이션 , 하드웨어 페이징

• 프로세스 기술자 , 상태 , 큐 전환

• 인터럽트와 예외 상황 , 시스템 콜 및 API, 타이머

• 시그널과 프로세스간 통신

• 프로세스 스케쥴러

• 메모리 관리 , 프레임과 페이징

• 메모리 매핑 , 파일 시스템 , 파일 접근

• 가상 파일 시스템 , 파일 시스템 마운트 하기

• 스와핑 , 메모리 해제

• 실행 가능 파일 , 라이브러리

“ 리눅스 커널의 이해” , 다니엘 보베이 , 마르코 체사티 저 , 이호 , 심마로 역 , 한빛미디어 ,


2001
Overview of Operating System (1)

• 프로세스들이나 작업들 (tasks) 의 스케줄링 , 기억장치 관리

• 사용자의 편의성을 위한 SERVICE, 자원 ( 데이터 및 프로세스 ) 관리의 효율성

• 사용자나 프로그래머가 hardware 를 모르더라도 응용프로그램이 가능하도록 사용자와 컴퓨터간의 인터페이스를


제공한다 .

- 프로그램 생성

- 프로그램 실행 : 명령어와 데이터를 주기억장치에 적재 (load) 하고 , I/O 장치들과 파일들을 초기화해야 하


며 , 그 이외의 자원들도 준비

- I/O 장치에 대한 액세스

- 파일의 관리

- 시스템 사용 권한 통제

- 오류 검출 및 대응

- 컴퓨터 성능 모니터링 및 통계 처리

• 프로세스들이나 작업들 (tasks) 의 스케줄링 : 하드웨어는 수시로 실행중인 프로세서에 인터럽트를 보내어 OS 로
하여금 새로운 스케줄링 결정을 하도록 함으로써 많은 프로세스들이 프로세서 시간을 공평하게 공유할 수 있게 한
다.
실행중인 프로그램에 의하여 I/O 장치가 언제 사용될 것인지를 결정해주고 파일에 대한 액세스와 사용을 제어한
다.
프로세서 자체도 하나의 자원으로서 관리의 대상
운영체제는 특정 사용자 프로그램을 실행하는 데 프로세서 시간을 어느 정도 사용해야 할 것인지 결정해야 한다 .
다중프로세서 시스템 (multiple-program system) 의 경우에는 그러한 결정이 모든 프로세서에 대하여 이루어져야
한다 .

• 가상기억장치의 두 가지 이점 : (1) 어떤 프로그램을 위한 명령어들과 데이터들이 한꺼번에 주기억장치에 적재되


어 있지 않더라도 , 프로세스가 주기억장치에서 실행될 수 있으며 , (2) 비록 기억장치 관리가 소프트웨어로 수행되
지만 , OS 는 페이징 (paging) 과 세그먼테이션 하드웨어를 포함한 프로세서 내부 하드웨어 지원에 의존한다 .
Overview of Operating System (2)
Scheduling of Processes (1)

• scheduling of multi-task, job, process

• interactive processing ( 대화식 처리 ) / batch processing ( 일괄 처리 )

• scheduling : short term medium term long term

- 일단 작업이나 프로그램이 시스템에 들어오면 프로세스가 되어서 단기 (short-term) 스케줄러의 큐 (queue) 에 들어간
다 . 어떤 시스템에서는 새로이 생성된 프로세스가 교체되어 나가 있는 상태 (swap-out condition) 에서 시작되며 , 이
경우에 그것은 중기 스케줄러 (mid-term scheduler) 를 위한 큐에 추가된다 . 장기 스케줄러 (long-term scheduler) 를 다
중프로그래밍의 정도 (degree of multiprogramming) 에 따라 기억장치에 적재될 프로세스들의 수를 제어한다 .

- New : 프로그램이 고급 스케줄러에 의해 받아들여졌지만 , 아직 실행될 준비는 되지 않았다 . 운영체제가 그 프로세스


를 초기화한 다음에 ready 상태로 변경할 것이다 .

Ready : 프로세스가 실행될 준비가 되었고 , 프로세서에 의해 실행되기를 기다리는 중이다 .

Running : 프로세스가 프로세서에 의해 실행되고 있는 중이다 .

Waiting : 프로세스가 I/O 와 같은 시스템 자원을 기다리면서 실행을 중단하고 대기 중이다 .

Halted : 프로세스가 종료되었고 , 운영체제에 의해 제거될 것이다 .


Scheduling of Processes (2)

• PCB (Process Control Block) :

- 식별자 (Identifier) : 각 프로세스에 지정된 고유의 식별자 .

- 상태 (State) : 프로세스의 현재 상태 (new, ready 등 ).

- 우선순위 (Priority) : 단기 큐에 들어갈 상대적 우선순위 수준 .

- 프로그램 카운터 (Program Counter) : 실행될 프로그램의 다음 명령어


의 주소

- 기억장치 포인터 (Memory Pointer) : 기억장치 내에서 프로세스의 시


작 위치와 끝나는 위치 , 이것은 본 프로세스가 사용하는 메모리 영역
에 대한 정보를 가져야 다른 신규 프로세스가 놓여질 메모리 위치를
결정할 수 있고 본 프로세스의 종료 후에 메모리 영역을 다른 프로세
스들에게 할애할 수 있기 때문이다 .

- context data : 이 프로세스가 수행될 때 생긴 변수 값 , 상태 값들이


저장되는 일종의 본 프로세스에서 사용하는 스택

- IO status information : 본 프로세스가 사용한 I/O 및 파일 목록

- accounting information : 본 프로세스에게 스케쥴러에 의해 할당된 실


행 시간
• 프로세스 A 가 운영체제에게 (I/O 요구 등의 ) 서비스 호출 (service call)
을 보냈다 . 운영체제가 이 호출에 대한 처리를 완료할 때까지 A 의 실행은
연기된다 .

• 프로세스 A 가 인터럽트를 발생하였다 . 인터럽트는 프로세서로 보내지는


신호로서 하드웨어에 의하여 발생된다 . 이 신호가 감지되면 , 프로세서는
A 의 실행을 멈추고 운영체제 내에 있는 인터럽트 처리 루틴의 수행을 시작
한다 . A 와 관련된 여러 사건 (event) 들이 인터럽트를 야기시킬 수 있다 .
예를 들면 , 특권 명령 (privileged instruction) 을 실행하려고 시도하는
것과 같은 오류나 시간 종료 (time-out) 등이다 . 시간 종료는 프로세서를
어떤 한 프로세스가 독점하는 것을 막기 위한 것이다 . A 에 관련되어 있지
않은 사건들이 인터럽트를 야기시켰다 . I/O 동작의 완료가 그 예이다 .

- 큐로부터 빼 냄
- PCB 로부터 프로세스 관련 정보를 복구함

- 큐로부터 빼 내는 과정 : round robin, priority algorithm


- 큐로 집어 넣는 과정 : I/O 요청서비스 콜을 한 프로세스는 I/O 큐로 , timer 가 끝나
거나 월권 행위를 한 프로세스는 단기 큐로 집어 넣는 식으로 상황에 따라 다른 종류
의 큐로 집어 넣어 나중에 I/O 종료와 같은 인터럽트 발생시에 해당 I/O 큐로부터 프
로세스를 끄집어 내어 실행한다 .

- PCB 안에 나중에 복귀하기 위한 정보 저장


- 큐로 집어 넣음
Scheduling of Processes (3)

• 어떤 프로세스가 I/O 를 요구하였기


때문에 중단되었다면 , 그 프로세스는
해당되는 I/O 큐로 들어간다 . 만약 시
간이 종료되었거나 또는 운영체제가 반
드시 처리해야 할 일이 발생하여 중단
되었다면 , 그 프로세스는 ready 상

태로 바뀌어서 단기 큐로 들어간다 .

• I/O 동작의 완료 인터럽트가 뜨면 스케


줄러는 실행 중이었던 프로세스는
ready 상태로 바뀌어서 단기 큐로 들
여 보내고 I/O 큐에 있던 프로세스를
실행한다 .
Memory Management (1) - Partitioning

• 프로세서의 처리 속도가 빨라 대부분의 다중


프로세스는 I/O 수행 상태로서 유휴상태로
남아 프로세서의 비효율적인 시간 낭비

• 이로부터 보다 많은 수의 다중 프로세스를 지
원하도록 하는 것이 좋다

• 따라서 제한된 메모리 용량 내에서 각 프로세


스의 메모리 할당 및 관리는 중요하다

이와 같이 다중 프로세스를 최대로 활성화할 경우


동적 메모리 분할로 인해 조각이 많이 나게 되어
(fragmented) 조각난 메모리의 낭비가 심해진다 .
이로부터 각 분할된 조각들을 shift 하여 조각을 없
애준다 .(compaction)

가장 최근에 I/O 수행이 시작된 프로세스 2 는 다 그 다음에 프로세스 1 이 I/O 요청을 함으로써 디
른 프로세스에 비해 가장 나중에 수행되므로 디스 스크의 중간 큐로 swap-out 시키고 그전의 프로세
크의 중간 큐로 swap-out 시키고 process4 를 스 2 를 swap-in 한다 .
swap-in 시킨다 . 이는 가급적 많은 수의 다중 프
로세스를 활성화시켜 가급적 프로세서의 유휴상태
를 최소화 하고자 하는 것이다 .
Memory Management (2) – Paging
• 조각난 공간을 모으는 과정 (compaction) 은 프로세서의 처리 속도를 낮추기 때문에 바
람직하지 못하다 .

Jmp offset address


Jmp offset address • 조각난 공간을 모으기 위해 각 프로세스를 shift 시키게 되는데 프로세스 내부의 분기문
shift
의 경우 절대적 물리주소가 변경되므로 base 주소 및 상대 주소 (offset) 의 논리 주소
물리 주소 를 갖고 있어야 한다 .

• 이러한 partition 방법의 단점을 보완하기 위해 조각난 메모리 공간 (frame) 에 분할된


프로세스 (page) 를 할당하는 방식이다 .

• page table 에는 프로세스의 분할된 영역인 page 들이 어느 비어 있는 조각난 frame


에 들어 가 있다는 정보를 담고 있다 . 따라서 프로세스가 조각 나 있더라도 page table
조각난 공간이 모아짐 을 이용하여 접근이 가능하게 된다 .
Memory Management (3) – Paging

virtual (logical) address space physical address space


(main memory)
8K = 213
4K = 212

page 0 block 0 or frame 0


page 1 block 1
page 2 block 2
page 3 block 3

page 4
page 5
page 6
page 7
Memory Management (4) – Demand Paging & Virtual Memory

• Page demanding : 보다 더 효율적으로 메모리 공간을 이용하기 위해 프로세스의 전체 page 들을 분할된 frame 들에 할당하기 보다는 매 시점 마다 기존
의 잘 접근하지 않는 page 들 대신에 필요한 page 들로 교체 (swapping) 하는 방법이 있다 . 잘못하면 교체가 수시로 이루어져 처리 속도가 늦어지게 된다 .
(thrashing) 직접사상 cache 의 경우에 하나의 line 에 많은 수의 tag 들이 존재하기 때문에 잘 못 replace 하다가는 교체하다가 볼 일 다 본다 .

• 이와 같이 하면 아주 큰 크기의 프로세스라 할지라도 전체를 메모리에 탑재하지 않고 꼭 필요한 것들만 탑재함으로써 프로그래머가 개발하는 프로그램의 사이
즈에 연연할 필요가 없어 진다 .

• HDD 는 접근성이 느려서 정지상태의 프로그램이나 데이터를 저장하는 단순히 보조 기억장치 이다 . 그런데 demand paging 기법을 사용하면 프로세스가
전체의 페이지들을 주메모리에 탑재하지 않더라도 수행 가능하다 . 따라서 HDD 로 부터 수시로 필요한 page 를 요청하여 프로세스를 수행시킬 수 있다 . 이
것은 언뜻 보면 HDD 를 하나의 프로세스가 돌아 가는 주메모리처럼 보여 진다 . 이러한 연유로 HDD 를 가상 메모리라고 한다 .
Virtual memory (1)

• paging 기법 : 다수의 프로세스들이 제한된 용량의 주 메모리에 올라가 있게 되고 수 차례에 걸쳐 프로세스가 생성되
고 소멸되는 가운데 메모리의 가용 공간은 조각난다 . 이러한 조각난 메모리 공간을 모은다는 것은 시간이 걸리는 작업
이다 . 따라서 조각난 메모리 공간에 프로세스에 관련된 코드가 그대로 분리되어 존재하도록 하는 대신 절대적 위치 정
보를 어딘가에 기록해 놓으면 된다 . 이를 위해 조각난 메모리 가용 공간을 frame 이라 하고 이러한 frame 에 프로세스
의 분리된 단위인 page 를 대응시키면 되고 그 정보를 page table 에 기록한다 . 즉 CPU 는 어떤 프로세스의 코드를 실
행한다고 할 때 그 코드의 page 번호와 오프셋으로 구성된 논리주소를 갖고 페이지 테이블을 참조하여 물리주소로 변
환하여 접근하게 된다 .

• 요구 페이지 (demanding page) : 하나의 프로세스는 조각난 메모리의 frame 들에 할당된 page 들로 구성되어 있고
자체의 페이지 테이블을 갖고 있다 . 이러한 page 들 가운데 자주 사용되지 않는 page 들은 사실 메모리 공간을 쓸데
없이 차지하고 있는 셈이다 . 따라서 운영체제에서 사용이 매우 적은 page 들을 검색하여 그 위치에 다른 프로세스의
필요한 page 들로 교체하는 기능을 가진다면 제한된 메모리 용량에 대해 매우 효율적인 이용을 기할 수 있을 것이다 .
그러나 page 의 교체가 자주 발생하는 thrashing 과 같은 이상 동작이 발생하여 HDD 를 자주 접근하여 속도가 느려지
는 현상이 발생한다 . 그러나 이러한 역기능을 억제하기 위한 알고리즘이 개발되어 이러한 문제는 거의 없어졌다 .

• 가상메모리 : 앞서와 같이 요구 페이지라는 방법을 사용하면 작은 메모리 용량에 많은 수의 응용 프로그램들을 활성화


시킬 수 있다는 결론이고 이것은 작은 메모리 용량임에도 불구하고 매우 큰 용량의 메모리를 사용하는 식이 된다 . 이를
가상메모리라고 한다 .
Virtual memory (1)

• page table pointer in register : 하나의 프로세스들은 하나의 page table 을 가진다 . 논리주소를 물리주소로 빠르게 변
환하여 프로세스의 코드를 실행해야 하기 때문에 page table 은 가급적 CPU 내부의 레지스터에 저장되어 있어 접근성
이 좋은 것이 가장 바람직하다 . 그러나 프로세스의 코드 길이가 매우 크다면 page table 의 entry 수 (page 수와 이에
대응하는 frame 수 , 즉 page table 줄 숫자 ) 도 매우 크고 이를 CPU 내의 한정된 용량의 레지스터에 기록하는 것은
불가능하다 . 이 대신에 page table 이 주 메모리에 위치하되 시작주소 즉 포인터를 레지스터에 저장하는 방법이 있다 .

• demanding page table : 매우 큰 프로세스에서 page table 의 entry 수가 매우 클 때는 page table 자체의 크기가 매우
커서 메모리를 많이 차지하기도 한다 . 이 경우에 당장 그 프로세스가 사용하는 page 들에 대한 page table 의 entry
들만을 주 메모리에 저장하여 메모리를 절약하는 방법이 있다 .

• TLB (Translation Lookaside Buffer) : 프로세스의 처리속도를 빠르도록 논리주소를 물리주소로 빠르게 변환하기 위해
참조하는 page table 은 가급적 CPU 로부터의 접근성 ( 거리가 가까움 ) 이 좋은 것이 가장 바람직하다 . 가장 접근성이
가까운 것은 앞서 언급한 대로 CPU 내의 레지스터이고 그 다음이 캐쉬 구조이다 . 이러한 특정 프로세스의 특정 page
table entry 를 CPU 에 인접해 있는 캐쉬 메모리 (TLB) 에서 검색하고 있으면 곧 바로 page entry 의 frame 및 오프셋
으로부터 물리주소를 얻어 CPU 는 이 물리주소로 캐쉬 메모리 (TLB 가 아닌 주 메모리와 관련된 캐쉬 ) 에 접근한다 .
Linux kernel

• 리눅스 커널 버전 : 2.6.12 에서 주번호 2 는 커다란 변화 , 중간 번호 6 은 기능의 변화와 같은 작은 변


화를 나타내고 짝수인 경우에는 안정 버전 , 홀수 인 경우에는 개발 버전 , 마지막 수자 12 는 버그를 위
한 패치 버전을 말한다 .
Linux kernel

• 시스템 콜 : 사용자 응용 프로그램은 다수의 타스크 ( 또는 프로세스 ) 의 하나로서 만약 커널 함수를 원한


다면 SWI( 소프트웨어 인터럽트 ) 를 사용해서 하드웨어적인 공지를 통해 커널함수를 사용한다 . 이와
같이 하는 이유는 user mode 와 kernel mode 의 두 가지 동작 영역을 규정하고 CPU 상에서 이러한 두
가지 모드를 지원하도록 설계되어 있다 . User mode 에서는 특정 메모리 영역을 접근하지 못하도록 되
어 있고 특정 instruction 역시 사용할 수 없도록 설계되어 있어 시스템 콜이라는 과정을 통해 커널 영역
을 액세스한다 .

• 메모리 관리 : 알고리듬으로 buddy system 과 slab 할당자를 사용한다 .

• 태스크 매니지먼트 : 태스크를 관리하는 부분으로서 타스크의 생성 , 소멸 , 중단 등을 담당한다 .

• IPC(Interprocess Communication) : signal, message queue, shared memory, semaphore 등을 제공하고


있다 .

• VFS(Virtual File System) : 가상 파일 시스템은 각기 다른 파일 시스템 (EXT2, EXT3, VFAT, JFS 등 ) 이


나 디바이스 드라이버 등에 대해서 동일한 인터페이스를 제공하는 부분이다 . 즉 어떤 응용 프로그램이
특정 IO 의 디바이스 드라이버를 통해서 그 IO 를 제어하고자 할 때 그것에 대한 하나의 가상 파일 기술
자를 얻어 open, read, write, close 시스템 콜을 사용할 수 있고 이를 통해 IO 를 제어할 수 있다 .

• BSD Socket Interface API : bind, connect, accept, send, recv 등으로 대변되는 BSD socket interface
를 제공하는 부분이다 .

• File System : ext2, ext3, vfat, jfs 등의 파일 시스템을 제공하는 부분이다 .

• Network Protocol Stack : ipv4, ipv6, atm, x25 와 같은 프로토콜 스택을 가지고 있는 부분이다 .

• Device driver : 어떤 응용 프로그램이 운용체제 상에서 특정 IO 를 제어하고자 할 때 그것의 디바이스 드


Process “ 소켓 API 를 이용한 네트워크 프로그래밍” 주기호 저 , 배재대학교 누리사
업단

• ps -e (f, j, l) : UID( 사용자 ID), 프로세스 ID(PID), 부모 프로세스 ID(PPID), 세션 ID(SID), 플래그 (F),
상태 (S) 등의 정보가 보임 . 프로세스의 상태 정보에는 {D : I/O 처리중 , R : 작동 중 , S : 이벤트를 기
다리는 중 , T : 시스널에 의해 중단된 상태 , W : 페이징 작업 중 , Z : zombi process 는 작동이 끝난 상
태로서 부모 프로세스로부터의 wait( ) 커널함수에 의해 프로세스가 해제되길 기다리는 프로세스 } 가
있다 . 세션은 로그온한 각각의 사용자를 지칭하고 – e 옵션은 전체 세션에 대해 돌아가는 프로세스에
대한 정보를 보여 준다 .

• pstree : 디렉토리 구조로 프로세스를 보여 줌 .

• 프로세스의 생성 : fork( ) 커널 함수로서 먼저 부모 프로세스 , 다른 하나는 이로부터 user context,


프로그램 위치 시스템
kernel context 를 물려 받아 자식 프로세스를 생성 .
• clone2.c 는 fork( ) 를 호출해서 부모 및 자식 터미널
프로세스를 생성하고 이로부터 clone2 를 실 [root@localhost /]# cd work/socket_ code
[root@localhost socket_code]# gcc –o clone2 clone2.c
행하면 “ hello world” 라는 문구가 두 번 나타 [root@localhost socket_code]# ls
컴퓨터
남을 확인할 수 있다 . ps 명령어를 치면 두 clone2 clone2.c …
[root@localhost socket_code]# . / clone2 &
개의 clone2 라는 프로세스를 확인할 수 있
Root 폴더 [1] 3175
다. [root@localhost socket_code]# hello, world
Hello, world
#include <stdio.h>
2GB 미디어
int main(){
[root@localhost socket_code]# ps –l
fork();
F S UID PID PPID C Pri SZ TTY TIME CMD
printf("hello, world\n");
0 S 0 2542 2538 0 80 pts/0 00 bash
sleep(30);
부모 프로세스 0 S 0 3175 2542 0 80 pts/0 00 clone2
return 0;
자식 프로세스 1 S 0 3176 3175 0 80 pts/0 00 clone2
}//clone2.c
4 R 0 3177 2542 0 80 pts/0 00 ps
Generation of process : fork( )

• process2.c 의 main 함수 안에 프로세스를 생성하는 fork( ) 함수를 호출하면 두 개의 프로세스가


생성된다 . 각각의 프로세스는 부모 및 자식 프로세스로서 fork( ) 함수의 반환 값이 각각 자신의
PID 및 0 이 되어 이 반환 값을 기준으로 각기 다른 일을 수행하도록 할 수 있다 . process2.c 의 실
행 파일과 fork( ) 함수에 의해 생성되는 프로세스의 차이는 ? process2.c 의 main 함수 시작 부분
에 fork( ) 를 호출해서 프로세스를 생성하므로 process2 실행 자체가 부모 및 자식 프로세스가 된
다.
#include <stdio.h>
int main(){
• process2 를 실행하고 나면
int cpid; 먼저 자식 프로세스에 의한
if((cpid=fork())==-1){ 실행인 child process:
fprintf(stderr, "can't fork);
exit(0);
PID=%d PPID=%d\n” 가 나
} 타나고 그 다음에 부모 프로
else if(cpid!=0){ //fork( ) 가 0 이 아닌 자신의 PID 를 반환하면 부모 프로세스
세스에 의한 실행인 parent
printf("\n parent process: PID=%d PPID=%d\n", getpid(), getppid());
sleep(20); process: PID=%d
} PPID=%d\n” 가 나타나고 20
else{ //fork( ) 가 0 을 반환하면 자식 프로세스
초 지나서 끝난다 . 그리고
printf("\n child process: PID=%d PPID=%d\n", getpid(), getppid());
sleep(20); ps 명령어를 쳐 보면 이 프로
} 세스들이 보이지 않는다 . 그
exit(0); //kernel 로 하여금 프로세스 종료하고 반환값 exit status word 0 을 보내는 시스템 콜 ( 또는 커널 함
수) 이유는 exit( ) 에 의해프로세
}
스가 종료되었기 때문이다 .
//process2.c
Exit of process : wait( ), waitpid( )

• 프로세스들은 부모 - 자식 관계로 상속 연결되어 있는 사슬 구조이다 . fork( ) 에 의해 생성된 하나의


프로세스는 이전의 부모 프로세스 PID 를 이어 받고 자신의 PID 는 자식 프로세스의 부모 PID 가
된다 . 자식프로세스가 종결되면 부모 프로세스에 의해 exit status word 를 회수해서 자식 프로세스
의 모든 자원을 없애도록 한다 . 이를 위해 부모 프로세스에서 wait( ) 시스템 콜을 사용해서 좀비
자식 프로세스에 대해 완전 무장 해제시킨다 . 왜 이와 같이 할 까 ?
waitpid( 완전 무장 해제 대상 •
#include <stdio.h> PID, exit status word 를 회수
int main(){
해서 저장해 둘 위치 , 옵션 )
int cpid;
int zpid;
if((cpid=fork())==-1){ 프로그램 위치 시스템

fprintf(stderr, "can't fork");


터미널
exit(0);
[root@localhost /]# cd work/socket_ code
}
[root@localhost socket_code]# gcc –o zombie1 zombie1.c
else if(cpid!=0){
[root@localhost socket_code]# ls
printf("\n parent process: PID=%d PPID=%d\n", getpid(), getppid()); 컴퓨터
zombie1 zombie1.c …
sleep(20);
[root@localhost socket_code]# . / zombie1 &
zpid=waitpid(-1, NULL, NULL); 자식 프로세스에 대해서 완전 무장 해제
Root 폴더 parent process: PID=3371 PPID=3225
printf("zombie process %d removed\n", zpid);
[1] 3371
sleep(10);
child process: PID=3372 PPID=3371
exit(0);
2GB 미디어 [root@localhost socket_code]# ps
}
PID TTY TIME CMD
else{
3372 …
printf("\n child process: PID=%d PPID=%d\n", getpid(), getppid());
[root@localhost socket_code]# child process 3372 terminated
sleep(10);
zombie process 3372 removed
printf("child process %d terminated\n", getpid());
exit(0); // 자식 프로세스가 종료되었지만 아직 부모 프로세스에 의해 해제된 것은 아닌 좀비 프로세스
}
}//zombie1.c
Signal to process

• signal 은 커널 또는 다른 프로세스로부터 받아 signal handler 에 의해 처리한다 . 이것은 SWI(software


interrupt) 에 의한다 . 이와 같이 signal 을 두는 이유는 어떤 프로세스의 동작에 일시 개입해서 event
driven 방식의 동작을 취한다 . nesC 에서 event-driven 방식의 처리에서 하부 컴포넌트로부터의
signal 을 받는다 .

• Signal action 구조체는 signal 을 받았을 때 처리 함수 , 다른 시그널들에 대한 마스킹 , 실행 후 복귀상


태의 세
#include 가지 설정 값을 구성한다 .
<sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void sig_handler(int sig);

int main(){
struct sigaction act; //signal action 구조체
act.sa_handler=sig_handler; // 시스널 받을 때 액션을 할 함수 포인터
sigfillset(&act.sa_mask); // 다른 시그널 마스크
act.sa_flags=SA_RESETHAND; // 핸들러 실행후 기본값으로 리셋
(void) sigaction(SIGINT, &act, NULL); //Ctrl + C 인터럽트에 의한 시그널 받았을 때 앞서 정의된 action 으로 처리
while(1){
sleep(3);
printf("waiting for SIGINT...\n");
}
}

void sig_handler(int sig){ //Ctrl + C 인터럽트에 의한 시그널 받았을 때 동작


printf("I catched a signal (number= %d)\n", sig);
} // signal_intr.c
Signal to process

프로그램 위치 시스템
• Ctrl + C 를 치면 SIGINT 의 시그널이 발생되
터미널 어 그러한 시그널이 발생될 때 처리하라는
[root@localhost /]# cd work/socket_ code
[root@localhost socket_code]# gcc –o sig_intr signal_intr.c sigaction(SIGINT, &act, NULL) 함수에 의해
컴퓨터
[root@localhost socket_code]# . / sig_intr act 구조체의 sa_handler 멤버에 설정된 처
waiting for SIGINT...\
waiting for SIGINT...\
리함수 포인터 내용대로 sig_handler( ) 함수
Root 폴더 waiting for SIGINT...\ Ctrl + C 로 가서 처리하게 된다 . 이와 같이 한 후에도
"I catched a signal (number=3)
계속 main( ) 에서의 실행이 계속되는데 다시
waiting for SIGINT...\

2GB 미디어 waiting for SIGINT...\ Ctrl + C Ctrl + C 를 치면 이제 더 이상 main( ) 에서


[root@localhost socket_code]# 의 실행을 멈추게 된다 . 이와 같이 되는 이유
는 act 구조체에 설정된 sa_flags 멤버에
SA_RESETHAND 라고 설정했기 때문이다 .

• kill –l 명령어 : 여기서 시그널들의 종류를 볼


수 있다 .

• kill –SIGQUIT 13092 : 13092 PID 프로세스


에게 SIGQUIT 이라는 시그널을 보냄 . 그러
면 13092 프로세스는 앞서 예제에서와 같이
내부적으로 signal 에 대한 action 을 구성해
놓은 대로 동작할 것이다 .
Kill zombie process by signal

• 자식 프로세스가 exit( ) 했을 때 “ SIGCHLD” 시그널 즉 SWI 가 발생된다 . 이와 같이 종료된 자식 프


로세스를 완전 무장 해제 시키기 위해 “ SIGCHLD” 이 발생될 때 처리하는 핸들러에 waitpid( ) 를 구현
해 넣으면 된다 . 이전 예제에서는 부모 프로세스에서 sleep( ) 을 충분히 줘서 자식 프로세스가 종료된
이후 시점에서 waitpid( ) 를 사용하여 죽였다 .
Kill zombie process by signal
Socket

• Socket 은 (IPv4, IPv6, X25), (stream, datagram, raw IP), (TCP, UDP) 의 세 가지 인수를 가지고 파일
기술자와 같이 socket descriptor 를 반환한다 .

• bind( ) 는 프로토콜이 설정된 socket descriptor, 자신의 주소 구조체 , 주소 구조체의 길이의 세 가지


인수로 부터 자신의 통신 node 를 구성한다 . 주소 구조체는 자신의 IP 주소 , 포트 번호로 구성된다 .

Protocol family 설명
PF_INET Ipv4
PF_INET6 Ipv6

Socket type 설명 internet


SOCK_STREAM TCP 와 같이 연결지향
SOCK_DGRAM UDP 와 같이
datagram
SOCK_RAW

Socket type 설명 httpd http client


IPPROTO_TCP TCP browser
Web server
IPPROTO_UDP UDP Protocol, IP, port
Protocol, IP, port
IPPROTO_ICMP ICMP(ping)

socket( ) socket address struct


         
bind ( )
Socket

struct sockaddr{ struct sockaddr_in{

sa_family_t sin_family; sa_family_t sin_family;

unsigned char sa_data[14]; unsigned short int sin_port;


14 Byte
} 범용 (GENERIC) 주소 구조 struct in_addr sin_addr;

unsigned char sin_zero[8];
Address family 설명 인터넷 주소 구조체
}
AF_INET IPv4
AF_INET6 IPv6
AF_X25 X25 패킷넷
• 특정 프로토콜 stack 에 따라 고유하게 정의된
주소 구조체가 있다 . bind( ) 나 connect( ) 와 같
은 함수에서 특정 프로토콜 스택의 주소 구조체
sin_family AF_INET
를 인수로 사용한다면 특정 프로토콜마다 bind
sin_port htons(serv_port)

sin_addr.s_addr htonl(INADDR_AN INADDR_ANY 는 0 으로서 자신의 IP 를 커널 및 connect 기능을 갖는 함수를 구현해야 할 것


Y) 에 맡김으로써 다양한 시스템과의 호환성 ( 이
식성 ) 을 좋게 함 . 이다 . 이러한 귀찮은 작업을 없애기 위해 특정
프로토콜 스택의 주소 구조체를 범용 주소 구조
체로 형변환을 해서 사용한다면 다양한 프로토
콜에 대해서도 통합적으로 기능을 할 수 있는 하
나의 bind, connect 함수만을 구현하면 될 것이
다.
Socket
• if(bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
int bind(int sockfd, struct sockaddr *myaddr, int addrlen); 성공하면 0, 실패하면 1 을 반환

• serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- sin_addr 은 in_addr 구조체로서 8 비트씩 쪼개진 4 개의 IP(192.168.123.165) 를 나타낸다 .

- INADDR_ANY 는 0 으로서 자신의 IP 를 커널에 맡김으로써 다양한 시스템과의 호환성 ( 이식성 )


을 좋게 함 .

- htons( ) 는 little endian 또는 big endian 의 프로세서 내부 레지스터와 메모리 사이의 바이트 정열
의 차이에 따라 올바르게 정열하는 함수이다 . htons 는 host to net short integer, htonl 은 host to net
long integer 임 .

• memset( &serv_addr, 0, sizeof(serv_addr)); 이것은 sin_zero[8] 이 모두 영으로 채워져야 하므로

• if(listen(serv_sock, MAXQUE)<0)

int listen(int sockfd, int backlog) 는 해당 소켓의 대기열 사이즈 안에 버퍼링한다 . 성공하면 0, 실
패하면 1 을 반환

• if((clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &caddr_len))<0)


int accept(int sockfd, struct sockaddr *cliaddr, int *addrlen) 은 클라이언트로부터의 connect( ) 함
수가 기동되어 패킷이 수신되면 이로부터 client 의 주소구조체를 특정 위치인 cliaddr 에 저장하고
client socket 을 생성해서 이 client socket 을 통해서 수신된 데이터를 메모리의 특정 위치에 저장하
고 이를 다시 송신하는 recv, send( ) 함수가 있다 .
Socket

• printf("Echo request from %s\n", inet_ntoa(clnt_addr.sin_addr));

inet_ntoa( ) 함수는 서버에서 수신된 (accept) 된 클라이언트의 IP 주소 구조체를 인수로 해서 이를


ascii 문자열의 포인터로 반환해 주는 함수로서 IP 주소를 문자열로 보여 주기 위해 사용한다 .

char* inet_ntoa(struct in_addr addr)

• if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)

client 프로그램에서 클라이언트 자신의 socket 을 생성하고 자신의 IP 및 port 를 bind 하지 않고


곧 바로 connect( ) 함수를 사용해서 목적지 IP 및 port 번호를 가지는 주소구조체를 인수로 해서
서버에 연결하는 과정을 시작한다 .
Echo socket program
• HP 에서 echo server 를 “ . / tcpechoserv 7000” 와 같이 포트 7000
번으로 구동한다 . 먼저 소켓을 생성하고 주소 구조체에 포트를 기입
하고 소켓과 주소 구조체를 바인드 시킨다 . 이 소켓을 통해 listen 함
수를 사용해 수신되는 것이 있는지 큐에 집어 넣고 그 다음에 accept
프로그램 위치 시스템
함수를 통해 송신지 주소인 클라이언트 주소를 포함한 client socket
터미널
을 생성한다 .
[root@localhost /]# cd work/socket_ proc
[root@localhost socket_code]# ls
• 다른 터미널을 열어 client 프로그램을 구동한다 . Client 프로그램은
“ . / tcpechocli 127.0.0.1 7000” 과 같이 자신의 loop back 목적지
Clone2.c clone2 process2.c process signal_intr.c sig_intr zombie1.c zombie1
컴퓨터 tcpechoserv.c tcpechocli.c IP 및 포트 번호 7000 을 사용해서 서버에 접속 (connect 함수 ) 한다
[root@localhost socket_code]# gcc –o tcpechoserv tcpechoserv.c .

Root 폴더
[root@localhost socket_code]# gcc –o tcpechocli tcpechocli.c
• 클라이언트로부터 접속하자 마자 에코 서버 프로그램에서는 받아들
[root@localhost socket_code]# . / tcpechoserv 7000 여서 (accept 함수 ) 송신지 주소인 clnt_addr.sin_addr 를 “ Echo
Echo request from 127.0.0.1 request from ~” 과 같이 출력하고 이를 포함해서 client socket 을 구
2GB 미디어
성.

[root@localhost /]# cd work/socket_ proc


[root@localhost socket_code]# . / tcpechocli 127.0.0.1 7000
Input message : hello
Echo from the server : hello

• 클라이언트가 서버에 접속한 후 입력 문자열을 서버로 보내기 위해 자신의 소켓을 통해 send 함수를 사
용한다 .

• 서버에서는 클라이언트로부터 보내진 문자열을 client socket 을 통해 recv 함수를 사용하여 메시지 버퍼
에 저장하고 이를 다시 client socket 을 통해 클라이언트로 송신한다 .

• 클라이언트에서는 이를 recv 함수를 사용해 서버로부터 보내진 문자열을 자신의 소켓을 통해 받아 들여


출력한다 .
#include <stdio.h> memset(&serv_addr, 0, sizeof(serv_addr));
#include <stdlib.h> serv_addr.sin_family = AF_INET;
#include <string.h> serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
#include <unistd.h> serv_addr.sin_port = htons(serv_port);
#include <sys/socket.h>
#include <arpa/inet.h> if(bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
exit_error("bind() failed");
#define MAXQUE 5
#define MSGBUFSIZE 80 if(listen(serv_sock, MAXQUE)<0)
exit_error("listen() failed");
int main(int argc, char *argv[]){
int serv_sock; while(1){
int clnt_sock; caddr_len = sizeof(clnt_addr);
struct sockaddr_in serv_addr; if((clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr,
&caddr_len))<0)
struct sockaddr_in clnt_addr;
exit_error("accept() failed");
unsigned short serv_port;
printf("Echo request from %s\n", inet_ntoa(clnt_addr.sin_addr));
unsigned int caddr_len;
if((msg_size = recv(clnt_sock, msg_buf, MSGBUFSIZE, 0))<0)
exit_error("recv() failed");
char msg_buf[MSGBUFSIZE];
if(send(clnt_sock, msg_buf, msg_size, 0) != msg_size)
int msg_size;
exit_error("send() failed");
close(clnt_sock);
if(argc != 2){
}
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
}
exit(1);
}
void exit_error(char *error_message){
perror(error_message);
serv_port = atoi(argv[1]);
exit(1);
}
if((serv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
exit_error("socket() failed"); // tcpechoserv.c
#include <stdio.h>
#include <stdlib.h> memset(&serv_addr, 0, sizeof(serv_addr));

#include <string.h> serv_addr.sin_family = AF_INET;

#include <unistd.h> serv_addr.sin_addr.s_addr = inet_addr(serv_IP);

#include <sys/socket.h> serv_addr.sin_port = htons(serv_port);

#include <arpa/inet.h>
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)

#define MSGBUFSIZE 80 exit_error("connect() failed");

void exit_error(char *error_message); fputs("input message :", stdout);


fgets(msg_buf, sizeof(msg_buf), stdin);

int main(int argc, char *argv[]){


int sock; if(send(sock, msg_buf, sizeof(msg_buf), 0) != sizeof(msg_buf))

struct sockaddr_in serv_addr; exit_error("send() failed");

unsigned short serv_port; if((msg_size = recv(sock, msg_buf, MSGBUFSIZE-1, 0))<0)

char *serv_IP; exit_error("recv() failed");

char msg_buf[MSGBUFSIZE];
unsigned int msg_size; msg_buf[msg_size] = '\0';
printf("Echo from the server: %s", msg_buf);

if(argc != 3){
fprintf(stderr, "Usage: %s <server IP> <echo port>\n", argv[0]); close(sock);

exit(1); exit(0);

} }

serv_IP = argv[1]; void exit_error(char *error_message){

serv_port = atoi(argv[2]); perror(error_message);


exit(1);

if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0) }

exit_error("socket() failed");
// tcpechocli.c
Echo socket program
• HP 에서 echo server C 코드를 TB 에서 동작시키도록 하기 위해 “
arm-linux-gcc –o tcpechoserv_arm tcpechoserv.c” 와 같이 컴파일
한 후에 실행 이미지를 TB 에 다운로드한다 . TB 에서 포트 7000 번
으로 에코 서버를 구동한다 .
프로그램 위치 시스템

• HP 터미널을 열어 client 프로그램을 구동한다 . Client 프로그램은


터미널 “ . / tcpechocli 192.168.123.165 7000” 과 같이 TB 의 목적지 IP
[root@localhost /]# cd work/socket_ proc
및 포트 번호 7000 을 사용해서 TB 서버에 접속 (connect 함수 ) 한
[root@localhost socket_code]# ls
다.
Clone2.c clone2 process2.c process signal_intr.c sig_intr zombie1.c zombie1
컴퓨터 tcpechoserv.c tcpechocli.c
[root@localhost socket_code]# arm-linux-gcc –o tcpechoserv_arm
• 클라이언트로부터 접속하자 마자 에코 서버 프로그램에서는 받아들
여서 (accept 함수 ) 송신지 주소인 clnt_addr.sin_addr 를 “ Echo
tcpechoserv.c
request from 192.168.123.166” 과 같이 HP 의 IP 로 출력하고 이를
Root 폴더 [root@localhost socket_code]# gcc –o tcpechocli tcpechocli.c
포함해서 client socket 을 구성 .
[root@localhost socket_code]# cp tcpechoserv_arm /tftpboot/.
[root@localhost socket_code]# ifconfig eth0 192.168.123.166 up
2GB 미디어 [root@localhost socket_code]# service xinetd restart
[root@EMPOS /]# tftp –r tcpechoserv_arm –g 192.168.123.166

[root@EMPOS /]# ls
[root@localhost socket_code]# . / tcpechocli 192.168.123.165 7000
… tcpechoserv_arm …
Input message : hello
[root@EMPOS /]# chmod 755 tcpechoserv_arm
Echo from the server : hello
[root@EMPOS /]# . / tcpechoserv_arm 7000
[root@localhost socket_code]#
Echo request from 192.168.123.166
Echo socket program for multi users [root@localhost /]# cd work/socket_ proc
[root@localhost socket_code]# . / tcpechocli 192.168.123.166 7000 (4)
Input message : I am HP (7)
Echo from the server : I am HP (8)
프로그램 위치 시스템 [root@localhost socket_code]# (9)

터미널
[root@localhost /]# cd work/socket_ proc
[root@localhost socket_code]# ls
Clone2.c clone2 process2.c process signal_intr.c sig_intr zombie1.c zombie1
컴퓨터 tcpechoserv.c tcpechocli.c
[root@localhost socket_code]# gcc –o tcpechocli tcpechocli.c
[root@localhost socket_code]# gcc –o tcpechoserv tcpechoserv.c
Root 폴더
[root@localhost socket_code]# arm-linux-gcc –o tcpechocli_arm tcpechocli.c
[root@localhost socket_code]# cp tcpechocli_arm /tftpboot/.
[root@localhost socket_code]# ifconfig eth0 192.168.123.166 up
2GB 미디어
[root@localhost socket_code]# service xinetd restart

[root@localhost socket_code]# . / tcpechoserv 7000 (3) (1)
(5) [root@EMPOS /]# tftp –r tcpechocli_arm –g 192.168.123.166
Echo request from 192.168.123.166
[root@EMPOS /]# ls
Echo request from 192.168.123.165 (10) (2)
… tcpechocli_arm …

• HP 에서 echo server 를 “ . / tcpechocli 7000” 와 같이 포트 7000 번 [root@EMPOS /]# chmod 755 tcpechocli_arm
(6)
으로 구동한다 . TB 에 client 프로그램을 작동시키도록 먼저 “ arm- [root@EMPOS /]# . / tcpechocli_arm 192.168.123.166 7000

linux-gcc –o tcpechocli_arm tcpechocli.c” 와 같이 컴파일한 후 실행 Input message : I am TB (11)


이미지를 TB 로 다운로드 한다 . TB 에는 “ . / tcpechocli_arm Echo from the server : I am TB (12)
192.168.123.166 7000” 과 같이 클라이언트를 구동한다 . 동시에 [root@EMPOS /]# (13)
HP 에서도 “ . / tcpechocli 192.168.123.166 7000” 과 같이 클라이
언트를 구동한다 .

• 이 때 동시에 두 클라이언트로부터 동시에 접속될 수 없음을 알 수


있고 어느 한 클라이언트에서 접속이 끊어져서야 다른 클라이언트
에서 접속하는 것을 볼 수 있다 . 이를 해결하려면 다중 프로세스를
사용하는 방법이 있다 .
Echo socket program for multi users

#include <stdio.h> if(argc != 2){

#include <stdlib.h> fprintf(stderr, "Usage: %s <port>\n", argv[0]);

#include <string.h> exit(1);

#include <unistd.h> }

#include <signal.h> serv_port = atoi(argv[1]);

#include <errno.h>
#include <wait.h> if((serv_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
exit_error("socket() failed");

#include <sys/file.h>
#include <sys/socket.h> memset(&serv_addr, 0, sizeof(serv_addr));

#include <arpa/inet.h> serv_addr.sin_family = AF_INET;


serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

#define MAXQUE 5 serv_addr.sin_port = htons(serv_port);

#define MSGBUFSIZE 80
if(bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)

void exit_error(char *error_message); exit_error("bind() failed");

void do_echo(int csock);


void zombie_collector(int sig_num); if(listen(serv_sock, MAXQUE)<0)
exit_error("listen() failed");

int main(int argc, char *argv[]){


int serv_sock; sig_handler.sa_handler = zombie_collector;

int clnt_sock; sig_handler.sa_flags = SA_RESTART;

struct sockaddr_in serv_addr;


struct sockaddr_in clnt_addr; if(sigfillset(&sig_handler.sa_mask)<0)

unsigned short serv_port; exit_error("sigfillset() failed");

unsigned int caddr_len;


int cpid; if(sigaction(SIGCHLD, &sig_handler, 0)<0)

struct sigaction sig_handler; exit_error("sigaction() failed");


while(1){ void exit_error(char *error_message){
caddr_len = sizeof(clnt_addr); perror(error_message);
if((clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, exit(1);
&caddr_len))<0)
}
exit_error("accept() failed");
printf("Echo request from %s\n", inet_ntoa(clnt_addr.sin_addr)); // tcpechoserv_fork.c
if((cpid = fork())<0)
exit_error("fork() failed");
if(cpid == 0){ • 동시에 두 클라이언트로부터 동시에 접속될 수 있도록 하기 위
close(serv_sock);
해 다중 프로세스를 사용한다 .
do_echo(clnt_sock);
• 앞서의 서버 프로그램과 거의 동일하나 accept 함수 이후에 이
exit(0); 를 위해 fork( ) 함수를 기동해서 부모 및 자식 프로세스를 생성
} 한다 . 자식 프로세스에서 do_echo( ) 함수를 통해 클라이언트
close(clnt_sock); 로부터 보낸 문자열을 에코시키고 종료되면 SIGCHLD 시그널
} 링이 발생되고 sigaction( 시그널 유형 , 핸들러 포인터 , 복귀
} 방법 ) 함수에 설정된 내용대로 zombie_collector( ) 함수로 가
서 좀비가 된 자식 프로세스를 완전 무장 해제 시키고 대기한다
void zombie_collector(int_sig_num){ .
int zid;

while((zid = waitpid((pid_t)-1, NULL, WNOHANG))>0);


if(zid == -1 && errno != ECHILD)
exit_error("waitpid() failed");
}

void do_echo(int csock){


char msg_buf[MSGBUFSIZE];
int msg_size;

if((msg_size = recv(csock, msg_buf, MSGBUFSIZE, 0))<0)


exit_error("recv() failed");
if(send(csock, msg_buf, msg_size, 0) != msg_size)
exit_error("send() failed");
close(csock);
}
Echo socket program for multi users
Multi-User Linux system
• host 운영자는 사용자 계정을 개설할 수 있고 그 사용자들에 대한 접근 권한을 설정할 수 있다 . 사용자
는 운영자에 의해 정해진 사용자 ID 와 암호를 갖고 리눅스 시스템에 접속할 수 있고 이들에게 할당된
/home 아래에 파일시스템을 가지고 있다 .

• 허용된 사용자들이 네트워크를 통해 host 에 접속해서 자신의 파일시스템을 액세스하는 이면에는 host
자체가 사용자들에게 특정의 서비스를 제공할 수 있다는 의미이다 . 이것이 host 가 특정 용도 ( 웹 ,
FTP, telnet, mail, DNS 등 ) 를 가지는 서버로서의 기능을 가지고 사용자들은 이 서비스를 제공 받는
client 가 된다 . 이와 같이 server 와 client 간의 네트워크를 통해 통신을 하기 위해서 특정 프로토콜이
있고 각각은 server 및 client S/W 가 돌아가야 한다 .

user1

user2

host
처음 로그인하면 이 위치
/

/root /usr /home


user3

/user1 /user2 /user3


Multi-User Linux system
• Terminal console 은 Ctrl+Alt+F1~F7 을 통해 리눅스 시스템을 볼 수 있도록 하는 창의 역할을 한다 . 동
시에 여러 개의 콘솔 터미널을 열어 사용할 수 있으며 각 콘솔 터미널은 Ctrl+Alt+F1~F7 을 사용해 다른
콘솔 터미널로 이동할 수 있다 . X-window 는 Ctrl+Alt+F7 이다 .

• Root 계정의 슈퍼유저 ( 운영자 , admin) 는 리눅스 설치시에 암호를 정하고 그 때 사용자계정도 만들 수
있지만 리눅스 설치 후에 기동해서 리눅스 환경에서 useradd 라는 컴맨드를 사용해서 사용자들을 추가
할 수 있다 . 일반 사용자는 root 운영자와는 달리 시스템을 변경할 수 없지만 (useradd 명령을 내릴 수
없다 ), 때로는 super user 로서 시스템을 제한 적으로 변경하고자 할 때 자신이 su 라는 명령어를 사용
해서 root 권한을 가질 수 있다 . 반대로 사용자 계정을 제거하려면 userdel 명령어를 사용한다 .
Multi-User Linux system
프로그램 위치 시스템

터미널

컴퓨터 [fiberamp@localhost ~]$ mkdir work 프로그램 위치 시스템


[fiberamp@localhost ~]$ cd work
[fiberamp@localhost work]$ userdel jonny 터미널
Root 폴더
[root@localhost /]# groupadd sharegrp

[fiberamp@localhost work]$ no such command [root@localhost /]# useradd –g sharegrp jonny

[fiberamp@localhost work]$ su – root [root@localhost /]# passwd jonny


2GB 미디어 컴퓨터
[fiberamp@localhost work]$ userdel jonny 새 암호 :

.. …

^C Root 폴더 [root@localhost /]# id jonny

[fiberamp@localhost work]$ uid=501(jonny) gid=501(sharegrp) groups=501(Sharegrp)


[root@localhost /]# find –name minicom
2GB 미디어 ./usr/bin/minicom
File system
• inode 는 리눅스 상에서 파일을 접근하기 위해 관련 정보를 기록한 구조체이고 이 안에 inumber 가 있
다 . 이를 사용하여 파일에 대한 접근 ID 라고 볼 수 있다 . 이와 관련해서 링크 명령어가 있다 . “ln file1
file2” 라고 하면 기존의 file1 이 새로운 file2 로 하드링크되는데 복사 (cp) 와는 달리 둘 중의 하나의 파
일이 변경되면 링크 걸린 나머지 파일도 덩달아 변경된다 . 가령 Object link embedded 와 같이 사용자
가 문서 작업에서 어떤 그림 파일을 가져와 삽입시키고 그 그림을 수정하면 그림 파일도 수정되는 식이
다 . Symbolic link 도 있는데 이것은 윈도우에서 아이콘과 같은 기능이다 . 나중에 디바이스 드라이버의
경우 INSMOD 명령어의 경우를 살펴 볼 것이다 .

파일명은 틀리지만 같은
file1 inode 를 사용하기 때문에 같
link 은 파일이다 . 그러나 하나의
파일을 수정하면 다른 파일도
inode 같이 변하게 된다 .
file2

Symbol access “ln –s dir1 symdir” 하면 이를


symdir “ symdir” 로 가리키면 dir1 에
file1 file2 data 접근이 된다 .

dir1 data block


File system
• 모든 파일들이나 디바이스들이 inode 로 등록되며 이에 대한 파일기술자 (file descriptor) 를 생성할 수
있다 . 파일기술자는 접근 순서대로 일련의 번호로 주어지며 이를 통해 해당 파일이나 디바이스에 접근
할 수 있다 .

• LED 디바이스 드라이버에서 “ insmod ledioport.ko” 를 함으로써 리눅스에 의해 inode 번호 257 이 할


당된다 . 이 inode 를 가지고 “ mknod ledioport 257 0” 로 하면 ledioport 라는 장치명이 /dev/ledioport
와 같이 생성된다 . 응용프로그램에서 “ fd = open(ledioport, ~)” 와 같이 커널 함수 ( 시스템 콜 ) 를 사용
해서 led 의 fd(file descriptor) 를 얻고 이것을 가지고 LED 에 액세스할 수 있게 된다 .

fd 0 stdin fd 0

fd 1 stdout fd 1
Process ID 5248 Process ID 5236
fd 2 stderr fd 2

fd 3
File1, inumber 3 fd 3
fd 4
File2, inumber 10 fd 4

File3, inumber 25

ledioport, inumber 257


File system

• /proc 밑에는 PID(process ID) 의 디렉토리들을 볼 수 있으며


•「 ls –l 」하면
구분 권한 link 개수 user_id group_id 사이즈 변경 날짜 파일이

- r-xr-xr-w 1 fiberamp root 1000 2004.07.30


somefile

과 같이 나타난다 .

구분에서 d : 디렉토리 , - : 일반 파일

「 ls –l 」하면 좌측에 inumber 가 리스트 된다 .

inumber 구분 권한 link 개수 user_id group_id 사이즈 변경 날짜


파일이름

1567 - r-xr-xr-w 1 fiberamp root 1000 2004.07.30


somefile\

•「 chmod u+w g=rw o-w somefile 」하면 somefile 의 접근권한을 사용자의 경우 (u) 쓰기 권한을 추
가 , 그룹 (g) 의 경우 읽기 및 쓰기 권한 설정 , 기타 (o) 의 경우 쓰기 권한 삭제를 한다 . 결국 rwxrwxr--
이 된다 . 이보다는 u, g, o 각 3 비트씩 해서 숫자로 표시하면 「 chmod 774 somefile 」와 같이 하는
게 더 보기 좋다 .
File system

• 파이프라인과 리다이렉션 (redirection) : 파이프라인은 작은 사이즈의 명령어를 갖추고 이를 한 번에 다


양한 명령을 내릴 수 있도록 하나의 명령어로부터 출력되는 것을 다음 단의 명령어 입력으로 사용하는
식이다 . 리다이렉션은

cat names.txt | sort “cat” 에 의해서 names.txt 를 stdout 으로 출력한 것을 “ sort” 로 정렬


(pipeline)

cat names.txt ; sort

sort < names.txt name.txt 파일을 표준 입력으로 해서 redirection

ls -al | vi - 디렉토리 표시된 것을 표준입력 (-) 으로 해서 vi 에디터로 넘겨 받음 .

ls > filelist.txt

• rpm(redhat package manager) : -qa –ql 패키지 조회 , i 인스톨 , v 설치상황 보여줌 , h 해쉬


Multi-User Linux system

• IP, 포트 , 데몬 : MAC address 는 ethernet 자체의 등록 번호 , IP 는 인터넷상의 주소 , 포트는 각종


client /server 데몬에 할당된 출입구 번호 , demon 은 background 로 돌아가는 프로그램으로서 ftp, http,
icmp(internet message protocol for ping command), telnet 등

• IP 의 세 자리 번호가 같으면 gateway 없이도 연결이 가능하다 .

• Demon 은 chkconfig, netstat –au 로서 현재 구동중인지 확인해 볼 수 있다 .

• 방화벽 관련은 iptables –F, setup 에서 해제할 수 있고 Selinux 는 X-window 의 Selinux management 에
서 default setting 을 disable 로 한다 . 방화벽을 비활성화 시키고 해야
Linux Directory (1)

HDD CD-RW FLOPPY


/.
[root@localhost /]# [userid@localhost /]$
hdb1(primary partition #1) hdb1(primary partition #1)
hda1(C:) hda5(D:) /..

/bin /boot /dev /etc /home /lib /home


/lost+found /misc /mnt /opt /proc
/root /sbin /tmp /usr /var hdb6 (extended logical partition #2)

/root /userid
Documents nautilus Documents nautilus
.Xauthority .ami .bash_history .bash_logout .Xauthority .ami .bash_history .bash_logout
.dia .gconf .gnome .mozilla .swp .dia .gconf .gnome .gqview .gtkrc
.viminfo .mplayer
Linux Directory (2)
• Root 또는 사용자 로그인하는 과정 : LINUX 는 다수의 사용자들의 고유 접근 권한 및 데이터 영역을 가
지고 있고 다수 접속과 multi task 기능을 가진다 . Root 는 최고 권한을 가지는 super user 로서의 권한을
가져서 시스템을 관리 운영할 수 있어 사용자 계정을 생성해 줄 수 있고 권한도 규정할 수 있다 . 반면 일
반 사용자 계정에 등록된 사용자는 사용할 수 있는 영역이 제한되어 있어 시스템을 건드릴 수는 없지만
su 컴맨드를 사용하여 일부 super user 의 권한을 자체적으로 가질 수 있다 .
• Ctrl + Alt + F1~F6 : text 콘솔 , Ctrl + Alt + F7 : X-window 콘솔 , 콘솔에서 사용자 계정으로부터 로그아웃
하는 방법은 exit 명령어를 치거나 , Ctrl+D 키를 입력하여 로그아웃 한다 .
• 리눅스 시스템의 호스트 이름은 /etc/sysconfig/network 파일에 등록되어 있다 .
• 작업 위치는 현재 로그인 사용자 계정의 홈 경로를 의미한다 . 예를 들면 sulinuxuser 라는 계정으로 로그
인하였을 때의 홈 디렉토리 경로는 /home/sulinuxuser 가 되는데 이때 이 경로를 모두 표시하는 것이 아
니라 ~ 기호로 표시하게 된다 .
• 리눅스 시스템을 종료는 윈도우와는 달리 반드시 shutdown 컴맨드를 사용해서 안정적으로 종료해야 한
다.
[ 계정명 @ 시스템이름 현재작업위치 ] 프롬프트 기호
구분자 설    명
root 로그인한 사용자 계정명
localhost 리눅스 시스템의 호스트명
~ 현재 작업 디렉토리 위치

# 프롬프트 기호 ( # : root 계정일 경우 , $ : 일반계정일 경우 )

    명령어 대기 커서

http://www.linux.co.kr/에서 리눅수 탭을 치면 강좌 “시작과 종료하기”


http://www.linux.co.kr/home/lecture/index.php?cateNo=1&secNo=27&theNo=&leccode=10917
Linux Directory

디렉토리 명 기능 특성
bin LINUX command 유동
boot 부트 이미지 유동
dev fd(floppy disk), cdrom, mem, modem, /dev/mem, 유동
/dev/sda1, /dev/zero

etc 시스템 환경 설정 유동
home 사용자 홈 유동
lib 공유 라이브러리 및 커널 모듈 유동
lost+found 파일시스템 복구를 위한 fsck(file system check) 링크 유동
misc 기타 유동
mnt 디바이스 마운트 유동
opt Add-on 소프트웨어 패키지 고정 , 공유 가능
proc 커널과 프로세스를 위한 가상파일 시스템 유동
root 루트 사용자 홈 디렉토리 유동
sbin 시스템 명령어 고정 , 공유 가능
tmp 임시 작업 유동
usr /local /share / 고정 , 공유 가능
var 가변 자료 유동
Linux Directory
[root@ciss9 /]# ls -l
total 136
drwxr-xr-x 2 root root 4096 Aug 12 05:44 bin
drwxr-xr-x 2 root root 4096 Aug 12 05:48
boot
drwxr-xr-x 6 root root 36864 Oct 10 04:02
dev
drwxr-xr-x 37 root root 4096 Oct 11 14:28
etc
drwxr-xr-x 14 root root 4096 Oct 1 11:41
home
drwxr-xr-x 4 root root 4096 Aug 12 05:42 lib
drwxr-xr-x 4 root root 4096 Aug 12 05:36
mnt
dr-xr-xr-x 89 root root 0 Sep 6 23:49 proc
drwxr-x--- 17 root root 4096 Oct 12 07:01
  이들 디렉토리에 대해서 간단히 설명하면 다음과 같다 .
root
drwxr-xr-x 3 root root 4096 Aug 12 05:44 / : 최상의 디렉토리인 루트 디렉토리 .
sbin /bin : 중요하고 꼭 필요한 명령어가 있는 디렉토리 .
drwxrwxrwt 7 root root 4096 Oct 12 04:02 /boot : 커널 (vmlinux 등 ) 시스템 부팅에 관련된 파일을 저장하고 있는 디렉토리 .
tmp /dev : 시스템 디바이스 (device) 파일을 저장하고 있는 디렉토리 . /dev/mem, /dev/sda1, /dev/zero
drwxr-xr-x 22 root root 4096 Aug 12 05:41 /etc : 패스워드파일등 시스템의 전체 환경설정파일을 저장하고 있는 디렉토리 .
usr /home : 사용자의 홈디렉토리 , ID 와 동일한 이름으로 디렉토리를 가짐 .
drwxr-xr-x 20 root root 4096 Aug 12 05:44 /lib : 프로그램 (C, C++ 등 ) 에 필요한 각종 라이브러리를 저장 .
var m/mnt : 플로피 , CD-ROM 등 마운트를 위한 디렉토리 . 업버젼에서는 media
[root@ciss9 /] /proc : 실행중인 프로세스나 현재 시스템의 정보를 파일형태로 보여주는 가상디렉토리 .
/root : root 의 홈디렉토리 .
/sbin : 시스템 관리자용 명령어를 저장하고 있는 디렉토리 .
/tmp : 일시적인 저장을 위한 디렉토리 .( 정기적으로 삭제됨 )
/usr : 각종 어플리케이션등이 설치되어 있는 디렉토리 .
/usr/X11R6 : X 윈도우 시스템의 루트 디렉토리 .
/usr/include : C 프로그램에 필요한 헤드파일 (*.h) 디렉토리 .
/usr/lib : /lib 에 들어가지 않은 라이브러리 디렉토리 .
/usr/man : 명령어들의 도움말을 주는 매뉴얼 (manual) 페이지 디렉토리 .
/usr/sbin : /bin 에 제외된 명령어와 네트웍관련 명령어가 들어있는 디렉토리 .
/usr/src : 프로그램 소스 ( 주로 커널소스 ) 가 저장되는 디렉토리 .
/usr/local : 아파치 같은 추가 소프트웨어가 설치되는 장소 .
/var : 시스템운용중에 생성되었다가 삭제되는 데이터를 저장하는 디렉토리 .
/var/log : 각종 로그파일이 저장되는 디렉토리 .
/var/spool/mail : 메일이 일시적으로 저장되는 디렉토리 .
/var/spool/lpd : 프린트를 하기 위한 임시 디렉토리 ( 스풀링 디렉토리 ).
LINUX Command

컴맨드 명 기능
rpm, source
tar, gzip, vi, grep
arm-linux-gcc, tftp, minicom,
ifconfig
make, jmflash test led 부트 컴맨드를 사용해 TB 를 동작시켜 보는데 부트로더에 이 함수를
수정해서 컴파일하고 실행시켜 본다 .
patch, make clean
dd, mkfs, mount, gzip
tftp –g ip_number HP 에서 mmap 을 이용한 가상논리주소로 LED 접근해서 제어하는 응용 프로
그램을 arm-linux-gcc 의 크로스 컴파일러가 제공하는 라이브러리를 사용하여
개발하고 컴파일된 실행 이미지를 tftp –g ip_number 를 사용해서 TB 의 포팅
된 리눅스 환경의 현재 디렉토리로 전송한다 . ./led 를 해서 TB 의 포팅된 리눅
스 환경에서 돌아가도록 한다 .
insmod, mknod, rmnod 포팅된 리눅스 임베디드 TB 에서 LED 를 제어하기 위한 응용프로그램을 동작시
키는데 LED 드라이버 프로그램을 사용해서 접근할 수 있다 .LED 의 물리주소를
논리주소로 변환하는 함수 (open), LED 에 쓰기 함수 (write), 닫기 함수
(close), 초기화 함수 (init), 종결함수 (exit) 로 구성된다 . linux 에서 제공하는
device 를 open 하고 거기에 쓰고 , 닫는 과정의 응용프로그램을 구성할 수 있
다 . 여기서 device driver 의 함수에 연결된다 . 초기화 함수 (init), 종결함수
(exit) 는 linux 에서 insmod 드라이버명 , rmmod 드라이버명의 컴맨드에 의
해서 기동되어 디바이스 드라이버를 등록하고 소멸시킨다 .
LINUX Command

컴맨드 명 기능
useradd, userdel, su 사용자 계정 등록 / 사용자 해제 / 운영자 자격 격상
logout, exit 세션 로그아웃 / 비슷 , ctrl+d
env, export 로그인 계정의 환경변수 보기 / 환경변수 설정하기
man Manual 보기 , 빠져 나오려면 q
apropos
info 정보 보기
ls 시스템 환경 설정
find 루트에서 파일 찾아야 함 . -name minicom*.*
Chmod
rpm(Redhat package -qa 질의모드 . –ivh install,verbose, hash(#)
manager)
cat, sort 파일의 내용을 stdout 으로 출력
cat –n
/ 정렬
yum
shutdown –h now 리눅스 시스템을 종료 , power off
shutdown –r now 리눅스 시스템 재부팅
su 사용자가 root 계정의 super user 로서의 권한을 가짐
grub
Gedit, vi
vi command
유용한 vi 명령어

삽입
I: 줄의 제일 앞에서 입력
A: 줄의 제일 끝에서 입력

콤보 command
4w: 4 단어 skip 후 이동
4b: 4 단어 skip 후 이동
4j,h,k,l: 커서이동시 지정한 수만큼 건너뛰므로 이동을 좀 더 빨리 할 수 있다 .

줄의 결합 (J)
2 줄이 있고 , 2 째줄을 1 째줄 끝에 붙이고 싶다면 , 1 째줄에서 J 를 입력하면 된다 .

커서이동
0: 줄의 처음
^: 줄의 처음 ( 글자가 시작되는 처음 )
$: 줄의 끝
w: 단어단위 이동
e: w 와 같으나 단어의 끝으로 이동
b: w 의 반대방향으로 이동
H, M, L: 커서를 화면 상 , 중 , 하로 이동

검색 (/ 후 검색할 단어입력 )
n: 뒤로 검색
N: 앞으로 검색
vi command
매크로
ab aa aaaa: aa 를 입력하면 aaaa 로 자동변환

치환
s/pattern/replace: 현재줄의 첫번째 matching pattern 치환
s/pattern/replace/g: 현재줄의 모든 matching pattern 치환
%s/pattern/replace/g: 모든 줄의 치환
line,lines/pattern/replace: 해당 범위의 치환

저장
w>> file: 지정한 파일에 추가

윈도 split
vi 내에서 위아래로 윈도가 분활되면서 2 개의 파일을 동시에 open/ 편집할 수 있다 .
ex-mode(: 프롬프트상태 ) 에서 'sp 파일이름 '
윈도우가 전환은 Ctrl+ww

기타
1. d 의 경우 command 모드로 계속 남아 있으나 c 는 삭제후 insert 모드로 변환한다 .
cc, c$, cw 등은 유용하게 사용될 수 있다 .
2. . 은 마지막 명령을 되풀이한다 .

visual 모드
윈도의 텍스트 에디터와 같이 선택부분이 반전되면서 복사 , 삭제등을 할 수 있다 .
v 로 visual 모드로 집입하여 커서키를 사용해 원하는 부분을 선택한다 .
복사는 y, 삭제 / 잘라내기는 d 로 할 수 있다 .
vi command
vi 설정 (vim 설정 )
자신의 홈디렉토리에 .vimrc 를 생성하고 다음과 같이 할 수 있다 .

set ai
set ts=4
set nu

각각 auto-indent, tab stop, numbering

윈도에서 작업중 vi 에 붙여넣기시 계단현상발생 방지


:set paste

위치기억 (UltraEdit 의 ALT-F2, F2 와 동일한 기능 )


m{a-z}: 현재위치를 {a-z} 로 북마크함
`{a-z}: 기억해둔 {a-z} 로 이동 . 보통 한개만 등록했다면 그냥 `` 를 사용하면 된다 .

레코딩
설정파일의 주석추가 / 삭제시 유용하게 사용할 수 있다 .( 이미 vi 에 매크로기능이 있지만 ,
레코딩이 UltraEdit 의 매크로기능과 유사하다 .)
q{a-z}: {a-z} 로 레코딩 시작 . {a-z} 만 가능한게 아니고 실제 {0-9a-zA-Z"} 를 적기 번거로워
이렇게 표시만 한 것이다 .
q: 레코딩 종료
@{a-z}: 레코딩 내용 적용 (@@ 를 하면 바로 이전의 레코딩내용을 적용 , N@@ 은 N 으로
지정한 숫자만큼 적용 )
vi command

ctags 사용
쉘에서 ctags -R 하여 모든 소스에 대해 인덱스 생성
vi 를 실행하고 검색할 단어를 :ta tag 로 지정하든지 , 단어가 있는 곳에 커서를
둔다 .
해당함수 ( 오브젝트 ) 가 정의된 곳으로 가기 : Ctrl + ]
되돌아가기 : Ctrl + t

여러 파일 편집
vi a.c b.c c.c 와 같이 여러 파일을 지정한다 .
args: 파일목록 표시
n: 다음파일 편집 (vi 시작지 지정하지 않는 파일은 'n 파일이름 ' 이로 지정하면
된다 .)
rew: 이전 파일 편집 (vim 에선 prev 를 사용해도 된다 )
* 현재 편집중인 파일을 저장해야 다음 파일을 수정할 수 있음에 주의
( 불편한 편집이 아닐 수 없다 .)

여러줄을 주석으로 처리할때


10 줄을 주석기호 # 을 사용하여 주석처리하려면 다음과 같이 하면 된다 .
우선 , 첫째줄에 # 를 붙이고 , 두째줄로 넘어와 9. 를 입력하면 된다 .
.(period) 는 마지막에 수행한 명령어를 반복하는 명령이다 .
This article comes from dbakorea.pe.kr (Leave this line as is)
X-window
• 시스템 > 관리 > 네트워크 장치제어 에 가서 eth0 를 활성화 , 시스템 > 관리 > 방화벽에 가서 활성화 적용 ,
시스템 > 관리 > 네트워크 에 가서 eth0 의 속성에서 IP, gateway, subnet mask, DNS 등을 설정 .
• Firefox web browser 를 열어 http://moodle.pcu.ac.kr에 접속한다 .
Introduction of TCP/IP

• OSI 각 계층의 API : 하위계층 API device driver, 전달계층 (transport) 의 프로토콜 TCP/IP 를 위한 API 소켓 ,
응용계층의 API HTML

(OSI1,2)<IP,ARP(OSI3)<TCP,UDP(OSI4)<session<presentation<HTTP,FTP,telnet,SMTP(OSI7)

• 이더넷 : LAN 에서 동작하는 OSI1,2 에 해당하는 동작 규격을 의미한다 . 물리계층에서의 노드 간에 프레임을 신


뢰성 있게 전송하기 위해 오류제어 , 흐름제어 , 프레임의 동기 , 상위 계층의 프로토콜 형태 , 패킷 데이터로 구성
된 프레임 구조를 갖는다 . 흐름제어는 LAN 카드의 고유 식별 번호라고 볼 수 있는 48 비트의 MAC 물리주소에
따라 이루어진다 . CSMA/CD(Carrier Sense Mulitple Access/Collision detection) 의 프로토콜로 동작하는데 이로 인
해 속도 향상에 제동이 걸리지만 최근에는 100Mbps 까지 속도가 향상되었다 .

• 연결형 ( 연결설정과 경로에 따른 전송 , 연결해제의 절차에 따른 통신망의 운용 ) 과 비연결형

- 연결형 : TCP, virtual circuit, 회선교환

- 비연결형 : MAC, IP, UDP, tftp, datagram

계층 내용 API(Application Program Interface)


MAC(Medium Access Control), FTP 사의 Packet
프레임 단위의 데이터 송수신을 다루는 프로그래밍 , 디바이스
링크 - 물리 계층 Driver, MS 사의 NDIS(Network Driver Interface
드라이버
Specification), 노벨사의 ODI(Open Data Interface)
전달 계층 TCP/IP 게층의 데이토 송수신 흐름 및 오류제어 소켓 (winsock, BSD
응용 계층 SMTP, HTTP, FTP, tftp

컴퓨터 네트워크 프로그래밍 김화종저 p3-12


IP (1)

• IP 는 인터넷 계층으로서 (network layer) 비연결성의 특성을 갖고 32 비트의 송수신 IP 주소를 가지고 송신단에
서 여러 라우터를 거쳐서 수신단에 이르게 된다 .

IP 패킷 구성요소 기능
Version IPv6, IPv4
Internet Header Length 헤더의 길이
Service Type
Total Length 전체 길이
Identification 조각난 패킷의 순서 번호
DF : DeFragment 즉 어떤 노드에서 수용할 수 있는 패킷 길이를 초과할 경우 패킷을 조각낼 필요가 있는데 이 때 이 비트
Flags 가 1 로 되어 있으면 조각내지 않음 . 따라서 조각낼 필요가 있을 때는 그 노드에서 에러가 발생한다 . 패킷을 조각내지 않
도록 , More : 1 이면 패킷이 더 있다는 뜻임
Fragment Offset
Time to Live 수명이 정해져 있어서 많은 수의 노드를 거칠 경우 중간 노드 ( 라우터 ) 에서 패킷이 제거됨
Protocol 상위 계층의 프로토콜이 무엇인지 TCP, UDP 인지를 구분
Header Checksum
Source IP Address 10000001 00001010 00000110 00000111 129.10.6.7
Destination IP Address
TCP 또는 UDP data

컴퓨터 네트워크 프로그래밍 김화종저 p13-18


IP (1)

class A : 0|7bit netid|24bit hostid, subnet mask 255.0.0.0, 0.0.0.0~127.255.255.255

class B : 10|14bit netid|16bit host id, subnet mask 255.255.0.0, 128.0.0.0~191.255.255.255

class C : 110|21bit netid|8bit host id, subnet mask 255.255.255.0 192.0.0.0~223.255.255.255

Class identifier Network 안의 호스트 이 가능한 IP


Network 를 구분

• IP 주소는 네 가지 클래스의 netid 와 hostid 로 구성되고 subnet mask 에 의해 서브넷이 결정된다 .

• Class 를 두는 이유는 여러 호스트들을 묶어서 하나의 네트워크 그룹으로 만드는데 A class 가 가장 많은 호스트들
을 하나의 네트워크 안에 가질 수 있지만 네트워크 개수는 가장 작다 .

• 사설 IP 와 공인 IP : 각 class 마다 내부 네트워크에서만 사용되는 IP 들이 할당되어 있다 . 가령 C class 에서는


192.168.0.0~192.168.255.255

• Broadcast ip : 같은 네트워크 안의 모든 host 들에게 브로드캐스트할 경우 IP 의 마지막 자리수가 255


IP (2)

• IP 패킷의 필드에서 fragment 에 대한 설정이 있는데 그 이유는 두 연결 노드 사이에 여러 개의 서브넷 노드들이 존재하
고 이들이 수용할 수 있는 최대 패킷 크기 (MTU, Maximum Transmission Unit) 가 있기 때문에 이에 맞춰서 보내고자 하
는 데이터 크기를 조각낼 (fragmentation) 필요가 있다 . 특히 최 하위 계층인 이더넷의 프레임이 수용할 수 있는 데이터
필드의 최대 크기가 1500 바이트임을 감안하면 더욱이 그렇다 . 즉 각 계층에서 처리할 수 있는 데이터 크기와 통과 노
드들에서 전달 가능한 최대 패킷 크기 가운데 가장 작은 크기 (path MTU) 에 맞춰서 데이터 사이즈를 조정할 필요가 있
다.

• telnet cc.kangwon.ac.kr 과 같이 PC 에서 telnet 응용 서비스를 호출한다 > domain name list 로부터 수신지의 IP 주소
를 얻는다 > TCP 단계를 거쳐 > IP 계층에서는 수신지 IP 주소의 netid 와 자신의 IP 주소의 netid 가 같은지 아닌지
확인하고 같으면 ARP(Address Resolution Protocol) 를 구동하여 ARP 에 의해 같은 LAN 내의 호스트들에게 IP 주소를
캐스트 하여 해당 수신지로부터 MAC 주소를 가져온다 > 이제 이더넷을 통해 송수신 MAC 주소 , 상위로부터의 패킷 ,
에러정정부호 , 동기부호를 붙여 프레임을 구성하고 수신지로 보낸다

• ARP 의 역과정 , 즉 MAC 주소로부터 IP 주소를 알아내기 위한 프로토콜을 RARP(Reverse ARP)


TCP/UDP

• TCP 는 많은 양의 데이터를 끊김 없이 순서대로 패킷의 송수신을 가능하게 하는 트랜스포트 계층에서의 연결형 프로토
콜이다 . 즉 트랜스포트 계층에서 종점간의 연결 개설 , 패킷 전달 순서 확인 , 오류 발생시 패킷 재전송 , 중복패킷 제
거 , 흐름제어 , 네트워크 오동작 시 보고하는 등의 기능을 갖고 있다 . 즉 송수신단의 연결설정과 연속적 패킷의 스트림
을 보장하는 프로토콜이다 .

- 따라서 신뢰성의 확보 및 패킷 스트림의 순서가 매우 중요한 서비스에 사용된다 .

- 상위 응용계층에서 telnet, http, ftp, smtp 와 같이 파일 또는 메일과 같이 신뢰성과 순차적 스트림 전송에 대한 응용 서비
스를 지원한다 ,

• UDP 는 위와 같이 연결 설정이 없고 패킷의 분실 확인이나 패킷의 순서 보장도 없는 트랜스포트 계층에서의 비연결형


프로토콜이다 .

- 신뢰성은 많이 떨어지나 헤더의 길이가 짧고 연결 설정에 대한 지연이 없기 때문에 간단한 패킷을 실시간에 주고 받는
경우 , 패킷을 broadcast 하거나 multicast 하는 경우 , UDP 기능만을 지원하는 서버의 경우에는 UDP 프로토콜을 사용
한다 .

- TCP 는 통신을 하는 두 노드 사이의 연결 설정을 위한 오버헤드가 크다 . 반면에 UDP 의 경우는 패킷의 구조가 간단한
비연결형 데이터그램이기 때문에 헤더의 크기가 적어 짧은 길이의 데이터 통신과 빠른 실시간 서비스에 있어서는 최적
이다 . 특히 LAN 내에서의 UDP 사용은 LAN 내부에서의 전송 오류가 거의 없고 데이터의 순차도 지켜지기 때문에
TCP 보다 오버헤드가 적은 UDP 가 유리하다 . 따라서 domain name 서비스나 LAN 내에서의 데이터 전송 서비스인
NFS(Network File System) 서비스에 적용할 수 있다 .

• MAC 주소 ( 이더넷 ) < IP 주소 (IP 계층 ) < Port 번호 (TCP UDP 계층 ) 컴퓨터 네트워크 프로그래밍 김화종저 p3-12
TCP field structure (1)
• TCP 에서의 연결 절차 : (1) port A 에서 port B 로 연결 설정하기 위해 SYN 비트를 1 로 하고 Sequence Number 필드
에 보내는 데이터가 몇 번째 바이트인가를 나타내는 X 를 만들어 하위 계층으로 보낸다 (2) port A 의 IP > 이더넷 (3)
port B 의 이더넷 < IP (4) port B 의 TCP 계층에서 port A 로부터 받은 X 번째 바이트의 데이터에 대해 확실히 수신했
다는 메시지를 보내기 위해 ACK number 필드에 (X+1) 을 채우고 ACK 비트를 1 로 설정해서 응답한다 . 또한 port A
로 port B 자신도 연결 설정을 하겠다는 의미로 SYN 비트를 1 로 설정하고 보내는 데이터가 몇 번째 바이트인지를
Sequence Number 필드에 Y 로 해서 전체 패킷을 구성하여 하위 계층으로 보낸다 . (5) port B 의 IP > 이더넷 (6) port
A 의 이더넷 < IP (7) port A 의 TCP 계층에서 port B 로부터 받은 Y 번째 바이트의 데이터에 대해 확실히 수신했다는
메시지를 보내기 위해 ACK number 필드에 (Y+1) 을 채우고 ACK 비트를 1 로 설정해서 응답한다 .

• [port A 연결 설정 port B 응답 및 연결 요청 port A 의 응답 ] 과 같이 3 way handshake 과정을 통해 연결하는 이유


는 하위 계층인 IP 에서 datagram 의 비연결식 동작을 취하기 때문에 TCP 계층에서 보내는 패킷의 순차흐름에 대한
신뢰성 확보 차원에서 이루어지는 연결 과정이다 .

• TCP 의 패킷 구성 필드에서 흐름제어와 관련된 window 필드에는 자신이 수용할 수 있는 데이터 사이즈의 크기를 설정
함으로써 흐름제어를 원활히 한다 . 두 통신 노드 간에 조각낼 필요 없이 원활하게 소통할 수 있는 데이터의 최대 크기를
path MTU 라고 하는데 대체로 이더넷의 1500 바이트 내로 하는 것이 보편적이다 . 따라서 window 필드에도 이 정도의
1460 바이트로 설정하는 것이 일반적이다 .

컴퓨터 네트워크 프로그래밍 김화종저 p21-24


TCP field structure (2)

TCP 패킷 구성요
기능

Source Port
Destination Port
Sequence Number 전체 데이터 중 현재 보내는 송신 데이터가 몇 번 째 바이트인지를 나타내는 순서 번호
Ack number 상대방으로부터 수신한 데이터가 몇 번째 바이트까지 들어 왓는지를 나타냄
Header length
URG : 긴급 데이터임을 표시하는 비트
ACK : 수신했음을 알리는 비트
Code bits
SYN : 최초 데이터를 보내기 위해 연결 설정함을 표시하는 비트
FIN : 연결 해제를 나타내는 비트 , RST : 연결을 리셋
Window 흐름제어용 윈도우 크기

컴퓨터 네트워크 프로그래밍 김화종저 p21-24


Server and client

• 서버

- 연결형 서버 : TCP 와 같이 접속하는 client 마다 소켓을 사용해야 하므로 서버에 다소 부담은 되지만 연결성이
좋다 . / 비연결형 서버 : UDP 와 같이 접속하는 client 마다 소켓을 사용할 필요가 없어 broadcast 의 서비스에 사
용할 수 있다 . 그러나 연결성이 떨어진다 .

- 반복형 (iterative) : 서버에서 하나의 프로세스가 다수의 client 들에게 순차적으로 서비스 해 주는 경우로서 서비
스 시간이 짧고 간단할 경우에 적용된다 . 그만큼 서버에서 돌아가는 서비스 프로그램은 간단한다 . / 동시처리형
(concurrent) : 다수의 client 들이 접속하여 서비스를 요청할 경우 서버는 각각에 대해 개별적인 프로세스 (session)
를 할당하여 동시에 처리해 주는 형태이다 . 이 경우에는 서비스의 시간이 불규칙하고 다소 복잡할 경우에 해당되
며 당연히 서버의 서비스 프로그램은 복잡해 지고 부담이 된다 .

컴퓨터 네트워크 프로그래밍 김화종저 p28-32


Apache, PHP, MySQL 성공적인 웹프로그래밍 PHP 와 MySQL, Luke Welling, 류정욱 외 1 인 공역 , 정보문화사 , p971-
979

• ISP 에게 요청하여 IP 를 확보하고 그 IP 에 대응하는 도메인 이름을 설정할 필요가 있다 . 도메인 이름이 URL 이
되어 사용자가 접속하는 웹서버의 문자 이름이 된다 .

• 아파치 서버 : 아파치를 윈도우에 설치하기 위해 패키치를 다운받는다 . 이 패키치를 설치하기 위해 상기의 정보


및 포트번호 80 을 설정할 필요가 있을 것이다 . 아파치는 TCP/IP 다른 응용프로그램과 포트를 공유해서는 않 된
다 . 웹브라우져의 local host URL 에 아파치 설정 웹페이지가 보인다 .

• 아파치 서버가 설치되면 디렉토리 C:\Program Files\Apache Group\Apache\conf\httpd.cond 의 내용을 수정하여


PHP 와 연동하기 위한 형상을 설정한다 . 또한 main( 시작 ) web page 인 index.htm 이 놓여질 위치는 아파치 웹
서버의 루트인 C:\ Program Files\Apache Group\Apache\htdocs 아래가 된다 .

• PHP 를 설치하기 위해 zip 파일을 C:\PHP 에 압축을 풀고 .dll 파일들은 C:\windows\system32 아래에 넣고 ,
php.ini 파일은 C:\windows 아래에 넣는다 . 이제 php.ini 파일을 열어 확장모듈 DLL 파일의 위치 , 웹서버의 루
트 디렉토리 “ doc_root = “C:\ Program Files\Apache Group\Apache\htdocs” 와 같이 설정한다 .

• MySQL(Structured Query) 을 C:\mysql 아래에 설치한다 . C:\windows\my.ini 초기화 파일의 내용을 다음과 같이
수정한다 . ( 기본 폴더에 설치하면 할 필요가 없다 )

[mysqld] basedir = C:\mysql\bin\ datadir = C:\mysql\data\

PATH, 익명사용자 삭제 , 패스워드 설정 작업이 필요한데 이를 위해 DOS 실행창에서 다음과 같이 한다 .

C:\mysql\bin\mysqladmin –u root password 루트패스워드

서비스를 시작 또는 중지하도록 DOS 실행창에서 하거나 제어판 > 관리도구 > 서비스도구를 사용하여 할 수 있다 .

• 시작메뉴에 아파치 웹서버 서비스를 시작하라는 아이콘을 클릭하면 아파치 서버가 동작하기 시작한다 .
MySQL 성공적인 웹프로그래밍 PHP 와 MySQL, Luke Welling, 류정욱 외 1 인 공역 , 정보문화사 , p971-
979

• MySQL(Structured Query Language) : 관계형 DB 관리 시스템 (RDBMS), 데이터베이스 > 테이블 > 행 / 열 , 키 ,
스키마

• 도스창 (mysql monitor 창 ) 에서 다음과 같이 입력하여 로그인한다 . mysql -h hostname -u username -p

자신의 컴퓨터가 아닌 외부의 MySQL 서비스를 제공하는 웹호스팅을 받을 경우 호스트명을 입력하고 웹호스팅
당사에서 부여 받은 사용자 이름을 입력한다 .

• 패스워드를 치고 나면 mysql> 이라는 프롬프트가 나타나 이제부터 MySQL 을 사용하여 데이터베이스를 구축할
준비가 된다 .

• 데이터베이스 이름을 짓기 위해 다음과 같이 DOS 창에서 입력한다 .

mysql> create database DB_name ;

• 만들어진 데이터베이스는 MySQL 서버에 존재하고 다수의 사용자들이 접속하여 사용하거나 웹에서 쿼리를 요청
할 수 있다 . 접근 및 사용 권한 설정을 다음과 같이 할 수 있다 .

mysql> grant all ( 엔터 ) ->on *( 엔터 ) -> to fred identified by ‘mnb123’( 엔터 ) -> with grant option;

권한을 허용 모든 DB 에 대해 비밀번호를 가진 사용자에게 사용자가 다른 사용자에게 줄 수 있는 권한 옵션

1 2 3

브라우져 웹서버 PHP 엔 MySQL 서버


6 5 진 4
MySQL 성공적인 웹프로그래밍 PHP 와 MySQL, Luke Welling, 류정욱 외 1 인 공역 , 정보문화사 , p971-
979

bookorama.sql
• 데이터베이스 이름은 create database
create database books; books ;

create table customers • 서점의 매출관련 DB 를 구축하기 위해 고


(customerid int unsigned not null auto_increment primary key,
객 , 발주 , 발주된 책으로 테이블을 만든다 .
name char(50) not null,
address char(100) not null,
city char(30) not null • not null 은 반드시 값이 입력되어야 함을 의
); 미 , auto_increment 는 테이블 내역이 추가
create table orders
될 때마다 id 수자가 자동으로 증가
(orderid int unsigned not null auto_increment primary key,
customerid int unsigned not null,
amount float(6,2), use books
date date not null
); insert into customers values
create table books (3, "Julie Smith", "25 Oak Street", "Airport West"),
(5, "Michell Arthur", "357 N. Rd.", "Yarraville");
(isbn char(13) not null primary key,
author char(50), insert into orders values
title char(100), (NULL, 5, 60, "2004-04-02"),
price float(4,2) (NULL, 3, 150, "2004-04-15"),
); (NULL, 5, 24.99, "2004-04-19");
create table order_items insert into books values
(orderid int usigned not null, ("0-672-11", "Kim Iksang", "What is Java", 30),
isbn char(13) not null, ("0-672-08", "Kim Yongwoo", "What is SQL", 50),
quantity tinyint unsigned, (NULL, 5, 24.99, "2004-04-19");
primary key (orderid, isbn)
nsert into order_items values
); (1, "0-672-11", 2),
(2, "0-672-08", 3);
MySQL 성공적인 웹프로그래밍 PHP 와 MySQL, Luke Welling, 류정욱 외 1 인 공역 , 정보문화사 , p971-
979

• 서점의 매출관련 DB 를 구축하기 위해 고객 , 발주 , 발주된 책으로 테이블을 만든다 .

• not null 은 반드시 값이 입력되어야 함을 의미 , auto_increment 는 테이블 내역이 추가될 때마다 id 수자가 자동으
로 증가
Gateway linux server

• 다수의 컴퓨터들이 인터넷 서비스를 받으려면 각각 고정 IP 를 받는다고 할 때 IP 고갈 문제로 인해 그


림과 같이 리눅스 서버 하나만이 고정 IP 를 ISP 로부터 할당 받고 이를 통해 연결된 내부 넷의 클라이
언트들은 인터넷을 공유할 수 있도록 한다 . 또한 내부 net 을 외부로부터 보호하기 위한 방화벽을 구현
할 수 있는데 Linux gateway 서버에서 외부 인터넷 망으로부터 들어 온 패킷을 보고 출입을 허용할지 않
할지를 결정할 수 있고 이와 같은 패킷 필터링을 통해 방화벽을 구현할 수 있다 .

인터넷 ISP 로부터 부여 받은 고정 IP 로 설


정된 primary ethernet

PC 방 Linux 192.168.0.1 사설 IP 로 설정
gateway 된 secondary ethernet

192.168.0.2 사설 IP 로 설 client client client



192.168.0.4 사설 IP 로 설

Fedora 리눅스 네트워크 & 웹 서버 무작정 따라하기 , 신재훈 , 길벗 , 2007, p476~
Gateway linux server

• 사설 IP 로 설정된 내부 net 의 client 가 외부 인터넷 망에 접속해서 서비스 받으려고 할 때 Linux


gateway server 의 secondary ethernet 을 통해 서버로 송신하는 패킷의 헤더를 ISP 공인 IP 헤더로 바
꾸어 줌으로써 외부 인터넷망에 접근할 수 있다 . 앞서 방화벽을 위한 패킷 필터링을 위해서는 수신된 패
킷들의 IP, port 들을 검토할 필요가 있고 iptables 를 사용해 보호 기준을 설정할 수 있다 . 따라서
iptables 의 NAT(Network Address Translation) 기능을 사용하면 앞서의 사설 IP 의 client 가 인터넷망
을 접근할 수 있다 . 이러한 기능을 가능케하는 것이 masquerade 유틸이다 .
Proxy server

• Proxy 는 대리인의 뜻으로 수신된 패킷의 헤더 정보 ( 소스 , 목적지 IP 및 port, 프로토콜 , 도메인 ) 를


보고 수신 제한을 하는 것으로 보안과 더불어 보안으로 인한 속도 저하를 억제함으로써 속도 개선 차원
의 의미를 가진다 . 반면 방화벽으로서의 패킷 필터링은 제한된 iptables 뿐만 아니라 다른 포트나 주소
로 포워딩시키는 라우팅 기능이 있다 .

• Proxy 기능은 패킷 필터링 보다 상위 S/W stack 에 놓여 있어 외부로부터 들어온 패킷은 먼저 패킷 필터


링을 거치고 이 후에 proxy 를 거치게 되어 있다 .

Portal site
인터넷 server

PCU Linux proxy


server

client client client

Fedora 리눅스 네트워크 & 웹 서버 무작정 따라하기 , 신재훈 , 길벗 , 2007, p538~


Proxy server

• 가령 client 가 요청한 웹문서를 Proxy server 가 인터넷망을 통해 portal site server 로 요청 패킷을 보내
면 portal site server 는 proxy server 에게 그 웹문서를 보내고 proxy server 는 수신한 웹문서를 메모리
또는 디스크 ( 캐쉬 ) 에 저장해 놓고 해당 client 에게 보낸다 . 따라서 이 후에 자주 사용하는 웹문서에
대한 client 로부터의 요청에 대해 갱신되지 않았으면 캐쉬에 있는 웹문서를 빠르게 서비스해줌으로써
통신 속도를 개선할 수 있다 .

• Squid 프로젝트 (www.squid-cache.org) 에서 제공되는 유틸을 사용하여 구현할 수 있다 .


DHCP server

• Port : IP 가 어떤 집의 주소라고 한다면 포트는 거기에 거주하는 개인으로 비유할 수 있고 64K 포트가
있다 . 80 번 포트는 http, 23 번 telnet 을 서비스한다 .

Fedora 리눅스 네트워크 & 웹 서버 무작정 따라하기 , 신재훈 , 길벗 , 2007, p538~


Basic structure of processor
4800_0000
memory controller
4900_0000
USB Host Controller
4A00_0000
Interrupt Controller
4B00_0000
DMA
4C00_0000
Clock & Power Management
4D00_0000
LCD Controller
4E00_0000
NAND Flash
5000_0000
UART
5100_0000
PWM Timer
5200_0000
USB Device
5300_0000
Watchdog Timer
5400_0000

5500_0000
IIC
special function
5600_0000
IIS
registers
I/O port
5700_0000
RTC
5800_0000
A/D converter
5900_0000
SPI
5A00_0000
SD interface

R0

R1
register
...... file
R13 R13_exc stack pointer

R14 R14_exc link register to save PC

R15

CPSR SPSR_exc register to save CPSR

exc : abt, FIQ, IRQ, svc, und


XM-Bulverde
XM-Bulverde base board (1)
XM-Bulverde base board (2)
CPLD EPM520C
ETH0, ETH1 의
- PXA275 로부터 신 ethernet
호를 받아 연결되는 LAN91C111
주변 장치들의 제어
신호를 공급
NAND, Strata
UCB1400 flash ROM
audio codec
PXA272 processor
CF

Bluetooth, GPS

VGA 가속기
SDRAM
FF UART

PCMCIA
Flash ROM 을 퓨징
하기 위한 JTAG USB Host, USB2.0 Host
client TDI242LP
sub UART controller
IrDA

MMC,SD
SPI 를 통한 인터페이스
XM-Bulverde base board (3)
PXA27X 로부터 Multimedia
accellorator 2700G 를 통해 고 XM-Bulverde hardware user’s guide p44~
속으로 영상을 전달하도록 한다 .
XM-Bulverde FPGA board
AC codec
주변장치로부터 인터럽트가 PXA27X 의
GPIO(General Purpose IO) 에 연결
Touch screen

데이터 버스 PXA272
graphic
TFT LCD accellorator 2700G GPIO interrupts

PXA IO
주소 (CS0~5, Ax),
부품 제어 인터페이스 상태 인터페이스
데이터 , 제어 버
reset CPLD 스 PXA 내부의 IO
interface 와 연결되어
Bus led, status CPLD CPLD Boot Flash ROM(64MB) /2nd 8 SDRAM(256MB)
led Flash ROM(64MB)
주변장치를 제어

Matrix keypad CPLD JTAG


& direct key
주변장치들
Boot Flasg CPLD(CS0) (UART, USB,
ROM Ethernet: ~cs4
Flash memory CPLD(CS1) PCMCIA, CF,
제어 SD/MMC, AC97
SDRAM PXA IO codec, TFT-LCD)
Ehternet CPLD(CS4) CPLD 상태
USB PXA IO

USB2.0 & OTG CPLD(CS2)

UART PXA IO CPLD( 인터럽트 상태 ) XM-Bulverde base board


AC codec(UCB PXA IO(GPIO)
1400)
PXA27X 로부터 칩 선택신호 (CSx) 및 세부 주소
MMIC/SD PXA IO
Ax 로부터 특정 주변장치의 제어 및 상태 레지스터
PCMCIA/CF CPLD CPLD( 탈착 상태 ) 를 액세스할 수 있도록 내부 로직이 프로그램 되어
CIS CPLD, PXA IO(GPIO) 있다 .
TFTLCD CPLD(CS3), 데이터 버스
Address map of XM Bulverde

0x07FFFFFF 

Flash ROM 

(64MB)  CS1


0x04000000 


0x03FFFFFF

Flash ROM 

(64MB) 

User 53MB 





0x01400000


64MB  CS0
Ramdisk 16MB


0x00400000

0x00300000


Kernel 
2MB 
0x00100000 

0x00080000 

Boot loader 512KB 
0x00000000
0x00000000
Address map of XM Bulverde

0x0880_5000 은 어떤
LED ?

0x1060_0000 은 어떤 LED ?
XM-Bulverde linux user’s
guide, p32, bootloader 에서
test led 0x11
Address map of XM Bulverde
4000_0000
Address map of XM Bulverde

9FFF_FFFF





 PXA272 내부 레지스터 파
 일



Address map of XM Bulverde
Interrupts and IO interface by using GPIO
CPU core 는 RISC pipeline 구조를 가지고 있고 바로
측근에 IR(Instruction Cache) 및 DC(Data cache) 가
분리되어 존재한다 . CPU core 는 memory controller
를 통해 외부 메모리의 프로그램 코드를 측근의 IR 주변장치로부터 인터럽트를 수합하여 인터럽트 컨트롤
cache 로 가져와 거기에 있는 프로그램 코드를 수행한 러 내부의 제어 레지스터에 설정된 우선순위에 근거하
다. 여 가장 우선순위가 높은 인터럽트신호를 CPU core
로 보내면 CPU core 는 인터럽트 사이클로 접어들면
PXA27X 서 고유의 순차대로 동작한다 . 인터럽트 사이클의 동
작 순차는 CPU core 내부의 상태 및 데이터 레지스터
IC 의 값을 stack 에 보관하고 메모리의 해당 인터럽트의
CPU AMBA ISR 이 놓여 있는 위치로 점프해서 수행하고 ISR 의
core intf RET 인스트럭션을 만나 인터럽트 사이클 돌입 이전의
DC 프로그램 위치로 복귀해서 수행한다 .
AHB
Memory CSx, Ax, Dx, R/W
Interrupt controller
controller
외부의 시스템 버스에 칩선택 신호 , 주소 / 데이터 / 제
어 버스 신호들을 인터페이스 한다 . 시스템 버스에 연
결되는 메모리 또는 IO 인터페이스 칩의 특성에 따라
신호들의 시간 지연을 설정하거나 데이터 폭 등의 내용
DMA/bridge 을 제어레지스터에 설정할 수 있다 .

interrupts
상태
GPIO 주변장치들 CPLD
timer
제어
APB

AMBA bus 는 프로세서 내부의 각종 모듈 (memory


controller, interrupt controller, GPIO, timer, UART, 프로세서의 GPIO 제어 레지스터에 해당 포트를 인터
USB 등 ) 을 core 와 연결시키는 시스템 버스이다 . 중 럽트 입력으로 사용할지 또는 일반적인 입출력 포트로
요한 시스템 제어 모듈은 AHB 버스로 주변장치 모듈 사용할지를 설정해서 외부의 주변장치들의 신호선과
은 APB 버스로 구분하고 이들 사이에는 birdge 회로 연결되어 인터럽트 신호 또는 단순히 입출력 인터페이
가 있다 스 신호로 사용되는 범용 IO 포트이다 .
XM-Bulverde FPGA board (1)
Quartus II 를 사용하여 FPGA 에 프로그

Configuration PROM

XM-Bulverde hardware user’s guide CH4~5


p63~

CIS 로부터 들어온 영상 데이터를 FPGA 내부의 제한


된 메모리에 저장하지 않고 외부 SRAM 에 저장하도록
한다 . PXA27X 는 이 SRAM 을 액세스해서 영상을 가
져와서 처리할 수 있다 .
Status LED Status LED
1M pixel
SRAM
CIS

Configuration
Cyclone II PROM EPC4
FPGA

JTAG

CMOS
Image
Sensor 7-segment
buzzer

Text
LCD

Motor LED
Matrix Dot
driver
keypad matrix
LED

0x0880_5000
Key
Bus pad
LED Dip sw
Reset &
power
XM-Bulverde (5)
System program Device driver program
Bootloader Source (Monitor Program) 및 Image AC’97 Audio Codec Driver Source
Linux kernel (2.6.12) (PXA27x& XM-Bulverde) Source UCB1400 Touch-Screen Driver source
및 Image PCMCIA/CF Device Driver Source
Root File System RAMDisk (BusyBox) Source 및 IrDA Device Driver Source
Image MMC/SD Device Driver Source
Ethernet Device (LAN91C111) Driver Source
Application program USB Host Device Driver
Network Application Source - USB2.0 OTG, Host 지원
- Chat server and client - USB Keyboard, Mouse Application Source
- Talk server and client
Qt/Embedded Source 및 Image Text Web Browser & Remote Control Source
- Address Book, Media Player, Terminal
- Image Viewer, Calendar, Graphic games
- Clock, Spreadsheet, Text Editor
- Control Panel, Virtual Keyboard, Handwriting etc.
Qt Camera Application Source
Graphic and Text Display Control, Application Source

I/O control
I/O Interface Application Source
- 8bit Button Switch, LEDs, 7-Segment Control Source
UART Application Source (Bootloader)
Web Service
- Goahead Embedded Web Server porting
-CGI/HTML (I/O Device Control Source)
Installation Development Tools

• HP 를 켜면 Grub 에서 Fedora9 으로 진입한다 . Root 계정에서 암호를 치면 X-window (GNOME 또는


KDE) 가 나타나고 바탕하면에 “컴퓨터 , root 폴더 , 윈도우가 있는 HDD 폴더” 아이콘을 보여 준다 . 리
눅스에서는 ./media/disk 로 윈도우 파티션이 나타난다 . 바탕화면 상위의 작업 줄의 “프로그램 > 시스템
도구 > 터미널” 을 열면 가상 리눅스 텍스트 콘솔 창이 나타난다 . 또는 ctrl+alt, F1~F7 을 치면 다수의 콘
솔 창에서 텍스트모드로 여러 사용자들이 자신의 “ ./home/ 사용자 계정”으로 로그인할 수 있다 . 자신의
계정에서 나가려면 콘솔 창에서 “ logout” 또는 “ exit” 을 친다 . 마지막에 HP 를 완전히 끄려면 root 계
정에서 “ shutdown –h now” 를 쳐서 끄도록 한다 .

• 되도록이면 root 가 아닌 일반 사용자 계정으로 로그인해서 시스템을 함부로 고치지 않고 다양한 리눅스
개발환경 및 응용 프로그램들을 사용하도록 한다 .

• HP 에서 “ # rpm –qa minicom” 을 치면 minicom 패키지의 정확한 이름인 “ minicom-2.3-2.fc9.i386” 을 보


여 준다 . “# find . -name minicom” 은 minicom 이름의 실행파일을 찾는다 . 엔터 치면
/usr/bin/minicom 에 있다는 메시지를 보여준다 . “# find . -name minicom.* ” 은 minicom.* 임의 확장명
의 파일을 찾는다 . 엔터 치면 /usr/share/man/man1/minicom.1.gz 등이 있다는 메시지를 보여준다 . 그리
고 “ find : ./home/fiberamp/ .gvfs : 허가 거부” 은 root 에서 fiberamp 사용자 계정에서 사용되었다는 것
을 뜻함 .
Installation Development Tools

• Serial cable 을 HP 와 TB 의 Fast UART 에 연결하고 HP 에서 앞에서와 같이 minicom 실행파일이 있음


을 확인하고 minicom -s 을 실행해서 통신모드 설정 (dev/ttyS0, 8N1, 115200 보레이트 ) 한 다음 exit 해서
minicom 환경으로 들어 간다 . TB 를 켜거나 리셋 버튼을 누르면 TB 의 0 번지 Flash boot ROM 으로부
터 실행이 시작되어 TB 의 하드웨어를 초기화하고 flash boot ROM 의 Kernel 및 Ramdisk 이미지를
SDRAM 으로 복사하고 HP 로부터의 키 대기 상태에 들어 간다 . 몇 초 이내에 키가 들어 오면 SDRAM
의 booter 영역으로 이동해서 실행을 하고 그렇지 않으면 SDRAM 의 kernel 에 복사된 리눅스 커널로 실
행이 옮겨 가고 TFT LCD 에 리눅스 바탕화면이 나타난다 . SDRAM 의 Booter 에서는 Fast UART port 를
통해 들어 오는 키 값 ( 부트 컴맨드 ) 에 대해 실행하는 프로그램을 수행한다 . 부트 컴맨드에는 “ boot,
flash, tftp, setip, read, write, test, 등”의 컴맨드를 제공한다 . 가령 , “XM Bulverde : test led 0x12” 라고
minicom 에서 치면 TB 의 Led( 물리주소 0x1060_0000) 에 접근해서 0x12 의 8 비트를 led 에 켠다 . 그
런데 확인이 않됨 .

• Bootloader 를 구성하는 source 파일들인 xm_boot.tar.gz 를 HP 의 CD drive 에 해당하는


“ /media/cdrecorder/source/ xm_boot.tar.gz” 을 가져 와서 “ /working” 을 새로 만들고 거기에 copy 해 놓
고 압축을 푼다 . 풀면 디렉토리가 생성되고 거기에 있는 “ commands.c 의 DoTest 함수”를 gedit 또는
vi 로 수정해서 arm gcc 컴파일하고 그 이미지를 tftp 를 사용하여 전송하고 TB 의 tftp zimage booter 를
미니콤에서 실행하여 LAN 을 통해 들어오는 boot loader 를 SDRAM booter 영역으로 복사해서 “ test
led 0x12” 를 실행시켜 본다 . 여기서 현재 SDRAM 영역의 booter 에서 tftp zimage booter 를 실행해서
새로이 컴파일된 booter 를 HP 로부터 TB 의 동일한 SDRAM booter 영역으로 복사된다면 실행되는 코
드 영역 위에 다운로드 되는 코드가 겹쳐 문제가 발생할 텐데… ?
Installation tftp
• HP 에서 “ # rpm –qa tftp” 을 치면 나타나지 않아서 설치해야 하는데 한백 CD 에서 rpm 을 설치하도록
한다 . X-window 바탕화면에서 컴퓨터 폴더 아이콘을 클릭해서 열고 /usr/bin 을 훑어 보면 tftp 가 없음을
확인해 볼 수도 있다 .

• HP 에 한백 CD 를 넣으면 /media/NEW 로 나타난다 . 여기로 디렉토리를 옮기고 여기서 rpm 명령어를


사용하여 tftp 패키지를 설치하도록 한다 . 여기서 xinetd 가 필요하다는 메시지가 나타나는데 tftp 패키
지를 설치하려면 먼저 xinetd 가 먼저 설치되어 있어야 한다는 의미이다 . 그런데 find 를 써서 확인해 보
니 없고 오직 /etc/xinetd.d 디렉토리만 존재할 뿐 . 리눅스 깔 때 설치가 않되었나 ? “rpmfind.net” 에서 검
색 다운 받음
프로그램 위치 시스템

터미널

컴퓨터 [root@localhost /]# cd media/NEWr/tools/tftpserver


[root@localhost tftp-server]# rpm –ivh tftp-server-0.29-3.i386.rpm
에러 : failed dependencies : xinedt is needed~
Root 폴더
[root@localhost /]# cd media/NEWr/tools/tftpserver
[root@localhost tftp-server]# rpm –ivh tftp-server-0.29-3.i386.rpm
2GB 미디어
에러 : failed dependencies : xinetd is needed~
Installation tftp
• HP 의 X-window 에서 시스템 > 관리 > 네트워크 에서 eth0 를 더블 클릭해서 나타난 설정창에서 IP,
subnet mask, gateway, DNS 를 설정하고 direct cable 을 건물의 LAN 포트에 연결한다 . 활성화 시키면
네트워크가 연결되어 Firefox web browser 를 열고 인터넷을 볼 수 있다 .

• SE(Securit Enhancement)LINUX 는 기존의 리눅스의 보안성을 지나치게 강하게 또는 지나치게 약하게


하지 않도록 편리하게 보안 설정하도록 한다 . /etc/sysconfig/selinux 를 vi 로 열고 여기서 그림과 같이 보
안을 최대로 하지 않고 어느 정도 보안을 약화시키도록 해야 (permitted) 인터넷을 통해 통신이 불편 없
이 가능하다 . 이 설정 파일은 부팅되면서 설정이 되므로 재부팅해야 적용된다 . 아래 표에 네트워크 관
련 설정 파일들이 있고 이를 수정하여 설정할 수도 있다 .


프로그램 위치 시스템

관리
네트워크 제어 스크립트 ( 명령어 ) 인
/etc/inet.d/network start ( 또는 stop,
네트웤
restart, reload, status) 라고 치면 네트워
컴퓨터 크를 활성 ( 또는 중지 , 중지 및 활성 , 설
정 변경 , 상태 ) 를 할 수 있다 .
Root 폴더 eth0 IP, gateway, subnetmask, DNS 설정

2GB 미디어
SELINUX=enforcing permitted

SELINUXTYPE=targeted
Setting network in Fedora

• ifconfig eth0 ( 또는 secondary ethernet eth1, loop-back lo) 192.168.0.10 를 치면 IP 가 설정된다 .


Ifconfig eth0 up ( 또는 down) 하면 eth0 를 활성화 ( 또는 비활성화 ) 시킨다 .

• Iptables –F 를 쳐서 방화벽 관련 iptable 의 규칙을 삭제해야 LAN 포트를 통해 HP server 에 접근이 가


능하다 .

네트워크 설정 파일 설정 내용
/etc/hosts 호스트 대비 IP 매핑
/etc/resolv.conf DNS 서버 주소 설정
/etc/sysconfig/network 호스트이름 , gateway <ex> HOSTNAME=localhost.localdomain …
/etc/sysconfig/network-scripts/ifcfg-0, ifcfg-1, NIC(ethernet0,1 등 ) 에 따른 고정 / 유동 (DHCP, Dynamic Host Configuration
ifcfg-lo Protocol), mac address, IP, gateaway, subnet mask, DNS
<ex> DEVICE=eth0 BOOTPROTO=static HWADDR=00:0c:29:cb:fa:7b …
/etc/sysconfig/selinux 보안 설정 <ex> SELINUX=permitted …
YUM(Yellowdog Updater Modified)

• yum 은 설치하고자 하는 패키지를 네트워크를 통해 검색하고 버전 관리를 통해 업데이트하고 의존성 있


는 패키지까지도 함께 설치해 준다 .

• /etc/yum.conf 설정 파일에 cache 안에 패키지를 저장할 건지 , /var/cache/yum, /var/log/yum.log 같이


캐쉬 , 로그파일 디렉토리를 설정한다 .

• /etc/yum.repos.d/*.repo 에는 패키지 관련된 저장소 (repository) 정보 설정 파일들이 있음 . 거기서 검색


대상 웹 사이트 등록 및 인증 설정을 한다 .

• “yum list xinetd” 또는 “ yum search xinetd | vi -” 을 통해 xinetd 및 그것과 의존성 있는 모든 설치 패키


지 (rpm) 들을 조사해 보고 확인된 rpm 을 “ yum install xinetd” 을 해서 웹사이트로부터 해당 rpm 을 다
운 받아 /var/cache/yum/packages 밑에 저장한다 .

명령어 설정 내용
yum install “package”
yum update “package”
yum remove “package”
yum list “package”
yum search “package”
yum provides “package”
yum clean packages(headers) /var/cache/yum/package, /header 밑의 모든 파일을 지운다 .
Installation xinetd & tftp

Service tftp
[root@localhost yum.repos.d]# yum install yum
프로그램 위치 시스템 {
[root@localhost yum.repos.d]# yum search xinetd
socket_type = dgram
telnet-server.i386
터미널 protoco = udp
xinetd.i386
wait = yes
proftpd.i386
user = root
tftp-server.i386
컴퓨터 server = /usr/sbin/in.tftpd
[root@localhost yum.repos.d]# yum list xinetd
server_args = -s /tftpboot
xinetd.i386 : 2.4.14-18.fc9 fedora
disable = no
[root@localhost yum.repos.d]# yum install xinetd
Root 폴더 per_source = 11
Downloading packages : xinetd-2.3.14-18.fc9.i386.rpm
cps = 100 2
….
}
2GB 미디어 [root@localhost yum.repos.d]# cd /etc
[root@localhost etc]# find -name xinetd
. / rc.d / init.d / xinetd . / sysconfig / xinetd
:wq
[root@localhost etc]# cd /work/tools/tftp-server Minicom version ….
[root@localhost tftp-server]# rpm –ivh tftp-server-0.29-3.i386.rpm XM Bulverde Linux Kernel
[root@localhost tftp-server]# ls /etc/xinetd.d ….
tftp ….. [root@EMPOS ~]#cd ..
[root@localhost tftp-server]# cd /etc/xinetd.d [root@EMPOS /]# tftp –r hello –g 192.168.123.166
[root@localhost xinetd.d]# vi tftp Time out
[root@localhost xinetd.d]# cd /
[root@localhost /]# mkdir tftpboot
[root@localhost xinetd.d]# cp work/hello tftpboot/.
[root@localhost xinetd.d]# ifconfig eth0 192.168.123.166 up
[root@localhost xinetd.d]# iptables –F
[root@localhost xinetd.d]# service xinetd restart
xinetd 정지
xinetd 시작
[root@localhost xinetd.d]#
Installation xinetd & tftp

HP 의 work 밑에 hello 실행 파일을 tftpboot 에 복사해 놓고 xinetd 데몬 구동해 놓고 TB 에서 tftp


를 치면 전달되어야 하는데 다음의 문제에 봉착 !!!!

avc: denied

  이 메시지는 현재 실행된 SELinux 정책이 그 응용프로그램의 동작을 허락하지 않기 때문이다 . 이러


한 일에는 여러 가지 사유가 존재한다 .
첫째 , 응용프로그램이 접근하려는 파일중 하나가 잘못 명명되어있을 수 있다 . 만일 AVC 메시지가
특정 파일을 참조한다면 , ls -alZ /path/to/file 을 수행하여 현재 참조하는 파일명 (current label) 을 조사
해 보라 . 만일 그것이 잘못되어 보이면 , restorecon -v /path/to/file 을 시도해보라 . 만일 파일과 관련
된 매우 많 은 거부 (denials) 상황이 존재하면 , fixfiles relabel 을 수행하거나 , 반복적으로 디렉토리
경로를 재명명하기 위해서 -R 옵션과 함께 restorecon 을 수행하고 싶을 수 있다 .
다른 때에는 , 거부 (denials) 현상은 정책에 의해 거부되도록 프로그램에 설정을 바꿔서 발생될 수 있
다 . 예를 들면 , 만일 Apache 를 8800 포트로 바꾸면 , 보안 정책 , apache.te, 도 관련하여 바꿔야 할
필요가 생긴다 . 정책 작성에 관한 상세한 정보가 필요하면 , 외부연결 리스트 (External Link List) 를 보
라.

http://www.linux.co.kr/home2/board/bbs/board.php?bo_table=lecture&wr_id=1448

Selinux trouble shooting browser 에서 default_t 레이블 파일 접근 불허 , 이를 해결하려면 chcon, 또


는 touch ,/autorelabel ; reboot
telnet service on xinetd

defaults{
최대 초당 50 회 무차별 접속 후 10
log_type = SYSLOG demon info
초 지연 대기
cps = 50 10
v6only = no
…..
• xinetd 는 telnet, vsftpd, tftp, ftp 등
을 통합 관리하는 internet super
} /etc/xinetd.conf
demon 으로서 /etc/xinetd.conf 에서
무차별 서비스 접속 (Denial of
service telnet{ Service) 에 대한 접속시도를 제한하
flags = REUSE 거나 /var/log 에 기록 내용 등을 설
socket_type = stream 정한다 . /etc/xinetd.d 아래의 각종
wait = no 서비스에 대한 설정

user = root • 관련 디렉토리 및 파일


server = /usr/sbin/in.telnetd /etc/rc.d/init.d/xinetd(xinetd 실행파

log_on_failure += USERID 일 ), /etc/xinetd.conf,


/etc/xinetd.d/tftp(tftp 설정파일 ),
disable = no
/etc/xinetd.d/telnet telnet (telnet 설정 파일 ),
}
/usr/sbin/in.telnetd(telnet 실행파
일 ), in.tftpd
Services on xinetd
telnet service on xinetd
Services on xinetd
Services on xinetd
Installation of arm compiler
• GNU gcc, ld 가 HP 리눅스 자체의 c-compiler 가 있지만 TB 의 arm 계열 프로세서에 맞는 arm-linux-
gcc 를 사용하여 컴파일해야 한다 .

• tar(tape archive) 는 파일을 묶음으로 저장하기 위한 util 로서

c (create): 파일들을 묶음 , x (extract) : 묶여진 파일을 풀음 , v (verbose) : 상황을 보여줌 , f (file): 리다


이렉션을 사용 않 할 때 파일명 , j : bzip2 와 연계될 경우 , t (test) : 묶여진 파일 목록 보기

<ex> tar –xvjf arm-linux-gcc-3.3.2.tar.bz2 ; arm-linux-gcc-3.3.2.tar.bz2 파일을 루트 상위에서 풀면


/usr/local/ 밑에 arm/3.3.2/ 디렉토리를 만들어 거기에 풀음 .

tar –tj < arm-linux-gcc-3.3.2.tar.bz2 ; ./usr/local/arm/3.3.2/~ 등의 파일 목록을 볼 수 있음 .

<tip> 어떤 명령어가 실행되어 헛 도는 상태를 빠져 나가려면 ctrl + d

find 같은 명령어는 상위 루트에서 실행해야 파일을 찾을 수 있음 .

CD 드라이브에 있는 파일을 현재 디렉토리에 복사하기 위해 끝에 . 을 찍음 [root@localhost


work]#cp /media/NEW/some_file

• 다음과 같이 한백 CD 로부터 arm cross compiler 를 루트 상위에 복사해 놓고 거기서 압축을 푼다 , 그


러면 /usr/local 밑에 arm/3.3.2 디렉토리가 생기면서 파일들이 풀어 진다 .
LINUX shell

• 리눅스 내부 명령어는 셀 (shell) 에 내장되어 있는 명령어로 셀이 명령어를 이해한다 . 리눅스 외부 명령어


는 /bin 안에 파일의 형태로 존재

• 차이점 : 내부 명령어의 실행 시 별도의 프로세서를 시작시키지 않지만 , 외부 명령어의 실행 시 새로운


서브 프로세스를 fork 하고 실행 .

• 경로 지정 : 리눅스에서 명령어는 셸이 특정 검색 경로를 찾아 실행하게 되어 있다 .


검색경로가 지정되어 있는 파일 : .bash_profile

PATH = _______: _______:

path 에 지정된 경로에 자주 사용하는 명령어의 결로를 앞쪽에 두는 것이 좋다 . path 에 설정된 경로를 찾
을 때까지 앞에서 뒤쪽으로 차례대로 검색 .

/etc/default/useradd : 사용자의 기본적인 셀 환경을 설정할 수 있음 . /etc/profile/ 에는 ~

• 각 사용자 계정의 .bash_profile 은 <ex> /root/.bash_profile, /home/fiberamp/.bash_profile,


/home/jonny/.bash_profile 에 있다 .
처음 로그인하면 이 위치
/

/root /usr /home

/fiberamp /jonny /user3


LINUX shell

• 시스템에 로그인된 사용자 계정을 조회 / 사용자 계정에 대한 정보를 확인


cat –n /etc/passwd
root : x : o : o : root : /root : /bin/bash
1 2 3 4 5 6 7
1 : 사용자명
2 : 패스워드 (/etc/shadow 파일에 암호화되어 있음 )
3 : 사용자 계정 uid
4 : 사용자 계정 gid
5 : 사용자 계정 이름 정보
6 : 사용자 계정 홈 디렉토리
7 : 사용자 계정 로그인 셀
<ex> fiberamp : x : 500 : 500 : Kim Iksang : /home/fiberamp : /bin/bash
jonny : x : 501 : 501 : : /home/jonny : bin/bash

• 다음과 같이 arm compiler 의 모든 경로에서 사용할 수 있도록 하기 위해 vi ~/.bash_profile 을 실행해서


다음과 같이 수정한다 .
/root 를 의미함
Installation of arm compiler

vi 는 시작이 일반모드에 있다가 i 를 치면 삽입모드로 되서 편집할


# .bash_profile
수 있고 esc 치면 다시 일반모드로 돌아가고 명령어 모드로 가기
# Get the aliases and functions 위해 “ :” 을 치면 아래 쪽에 “ :” 이 나타나 여기에 명령어를
“ :wq” 를 치면 저장하고 빠지게 된다 .
if [ -f -/.bashrc ]; then
. -/.bashrc
Blabla
fi 일반모드 bkablka
a,i,o, A, I, O : wq
# User specific environment and startup program
esc esc
PATH=$PATH:$HOME/bin
명령모드
export PATH=/usr/local/arm/3.3.2/bin:$PATH 삽입모드
: wq

unset USERNAME

• 지금까지 사용되는 대부분의 내부 명령어들은 /bin 밑에 있고 외부명령어들은 /usr/bin 밑에 주로 있다 .


그런데 source 는 /lib 밑에 있다 .

• fiberamp 계정으로 로그인해서 arm-linux-gcc 를 사용하지 못하는 이유는 무엇일까 ? root 계정에서 해야
하나 ? /home/fiberamp/.bash_profile 을 열어 동일하게 path 를 걸어 줘야 한다 . 또는 /root/bash_profile
에서 “ unset USERNAME” 을 “ set USERNAME” 으로 ?
Installation of arm compiler

• 다음과 같이 vi 에디터로 hello.c 를 쓰고 이를 arm cross compiler 로 컴파일한 후 실행 파일 ./hello 를


HP 에서 실행하면 실행이 않됨 . 그 이유는 arm 계열의 프로세서가 이해할 수 있는 코드로 컴파일 되어
있기 때문에 다른 CPU 를 장착하고 있는 HP 는 이를 이해할 수 없다 .

#Include <stdio.h>
Int main(void){
int I;
프로그램 위치 시스템 for(i=0;i<3;i++)
printf(“%d hello embedded world\n”, i);
터미널
}

컴퓨터 Insert mode


[fiberamp@localhost ~]$ mkdir work
[fiberamp@localhost ~]$ cd work
[fiberamp@localhost work]$ vi hello.c
Root 폴더 #Include <stdio.h>
Int main(void){
int I;
2GB 미디어 [fiberamp@localhost ~]$ mkdir work for(i=0;i<3;i++)
[fiberamp@localhost ~]$ cd work printf(“%d hello embedded world\n”, i);
[fiberamp@localhost work]$ vi hello.c }
[fiberamp@localhost work]$ arm-linux-gcc –o hello hello.c
fiberamp@localhost work]$ ./hello
에러 :wq
fiberamp@localhost work]$
Installation of arm compiler
• 다시 한 번 터미널을 열어 minicom 을 실행한다 . 그러면 HP 에 시리얼로 연결되어 있는 TB 로부터 부
팅된 리눅스 상태를 볼 수 있다 . 여기서 ctrl+a, z 를 눌러 minicom 도움말을 열고 거기서 send file S 를
누르면 보낼 실행 파일 hello 를 찾아 HP 에서 TB 로 시리얼 포트를 통해 TB 리눅스 커널의 현재 디렏
토리인 work 로 송되며 거기서 “ ./hello” 를 치면 실행이 잘 됨을 볼 수 있다 .
[fiberamp@localhost work]$ minicom

(2)

프로그램 위치 시스템
Minicom version ….
터미널 XM Bulverde Linux Kernel
[fiberamp@localhost ~]$ mkdir work
….
(1) [fiberamp@localhost ~]$ cd work HP 에서 minicom 을 통해 TB 의
[root@EMPOS ~]#cd ..
[fiberamp@localhost work]$ vi hello.c linux 커널이 부팅된 상태를 볼 수
컴퓨터 [root@EMPOS /]#ls 있다 .
[fiberamp@localhost work]$ arm-linux-gcc –o hello hello.c
[root@EMPOS /]# root usr etc var mnt dev
[fiberamp@localhost work]$
Minicom version ….ls [root@EMPOS /]#mkdir work
Root 폴더 [fiberamp@localhost
XM Bulverdework]$
Linuxhello
Kernelhello.c [root@EMPOS /]#cd work
[fiberamp@localhost
…. work]$
[root@EMPOS work]#
[root@EMPOS ~]#cd ..
2GB 미디어 [root@EMPOS /]#ls (3) Ctrl+a, z
…..
[root@EMPOS /]# root usr etc var mnt dev
Send file S S
[root@EMPOS /]#mkdir work
Port setup P
[root@EMPOS /]#cd work
TB 의 리눅스에서 실행파일을 실행 ….
[root@EMPOS work]#ls (4) …..
시켜 보면 제대로 돌아 감을 볼 수
[root@EMPOS work]#hello Zmodem
있다 .
…..
[root@EMPOS work]#./hello ….
[work] hello
0 hello embedded world
Space bar 한 번 누르면 디렉토리 이동 , 두 ….
1 hello embedded world
2 hello embedded world 번 누르면 선택해서 시리얼 포트를 통해 HP
에 있는 실행 파일 hello 를 TB 로 전송
Transmission thru LAN by NFS

• 앞서의 hello 실행 파일을 시리얼 포트를 통해 TB 로 전송했지만 큰 용량의 파일을 느린 시리얼 포트를
통해 TB 로 보내면 많은 시간이 걸리기 때문에 ethernet 을 통해 전달하면 100Mbps 의 빠른 속도로 보
낼 수 있다 . 이를 위해 앞서 xinetd 데몬의 tftp 를 사용하거나 지금 말할 nfs(network file system) 을 사
용한다 .

• HP 와 TB XM Bulverde 의 eth0 간에 cross LAN cable 을 연결한다 . HP 와 TB 간의 ethernet 통신이


되도록 하기 위해 TB 에서는 부팅하면서 192.168.123.165 의 사설 IP 로 설정되고 HP 에서는 IP 를 위
세 자리는 같고 마지막 자리수를 다르게 192.168.123.166 으로 하면 된다 . 이를 위해 HP 에서
“ ifconfig eth0 192.168.123.166 up” 과 같이 한다 . 혹 HP 에 방화벽이 걸려 있으면 해제 하는데 iptable
의 모든 규칙을 삭제하기 위해 “ iptables –F” 를 친다 . “iptables –L” 을 치면 routing table 사슬 (input,
forwarding, output) 의 상태 및 규칙을 확인할 수 있다 . 이제 통신이 제대로 되는지 확인하기 위해 TB
또는 HP 에서 상대방 IP 로 전송을 시켜서 제대로 되는지 가령 HP 에서 TB 의 IP 로 ping 을 하면
“ ping –c 5 192.168.123.165” 를 쳐서 5 개의 패킷을 TB 로 전송이 성공적으로 되는지 볼 수 있다 . Ping
은 ICMP(Internet Control Message Protocol) 에 의해 제어된다 .

• HP 에서 nfs demon 이 깔려 있는지 “ rpm –qa | grep nfs” 또는 “ find –name nfs” 를 쳐서 확인한다 .

• HP 에서 /etc/exports 설정 파일에서 nfs 서버의 특정 디렉토리 nfs_resource 에 대한 client 의 접근 권


한을 설정하기 위해 “ /nfs_resource *(rw,no_root_squash)” 를 쓴다 .

• HP 에서 TB 의 /mnt/nfs 로 마운트할 디렉토리인 nfs_resource 안에 앞서 컴파일된 hello 실행 파일을


넣 둔다 .
Transmission thru LAN by NFS

• 이제 HP 가 nfs 서버로 활성화 시켜 TB 로 하여금 HP 의 nfs_resource 을 마운트 하도록 하기 위해


HP 에서 “ service nfs restart” 를 친다 .

• TB 에서는 HP 의 nfs_resource 를 마운트 하기 위해 “ mount –t nfs 192.168.123.166:nfs_resource


/mnt/nfs” 를 쳐서 HP IP 인 192.168.123.166 을 eth0 를 통해 HP 로 부터 nfs_resource 디렉토리를 다
운 받아 TB 의 /mnt/nfs 디렉토리에 올린다 .

• 이제 TB 의 /mnt/nfs 에 들어 있는 hello 실행 파일을 실행시켜 확인해 본다 .


NFS (Network File System)

• NFS(Network File System) 는 파일시스템을 컴퓨터끼리 공유할 수 있게 해주는 서비스이다 . 즉 , 여러


대의 컴퓨터 (NFS 클라이언트 ) 가 큰 용량의 하드디스크를 가진 컴퓨터 (NFS 서버 ) 로부터 서버의 하
드웨어나 운영체제에 관계없이 파일시스템을 가져다 마치 자신의 파일 시스템인 것처럼 사용할 수 있
게 해주는 것이 NFS 의 기본 개념이다 .

• 서버에는 NFS demon 이 설치되어 있어야 하는데 /etc/rc.d/inetd.d/nfs 실행 파일이 있음을 find 명령
어를 사용하여 확인해 볼 수 있다 .

• NFS 서버에 /etc/exports 파일에 어느 디렉토리 ( 또는 파일 시스템 ) 를 어떤 제약을 두어 공유할 것인


가 하는 내용을 담는다 . 아무에게나 자신의 파일 시스템을 마구 사용할 수 있게 하는 것은 마치 대문을
활짝 열어두고 사는 것과 같은 일이기 때문이다 . exports 파일의 형식은 공유하는 디렉토리를 왼쪽에
적고 그 디렉토리와 관련된 옵션이나 속성을 오른쪽에 적어 준다 .

/lily/users daisy(rw,no_root_squash) rose(ro)


/usr/share/man freesia(ro) clover(ro) daisy(ro)

이 export 파일은 /lily/users 디렉토리를 daisy 라는 호스트가 읽고 쓸 수 있고 루트의 권한으로 접근


하는 것도 허가한 것이며 , rose 라는 호스트는 읽기 전용으로 마운트할 수 있게 설정한 것이다 . 그리고
/usr/share/man 디렉토리에 대해서는 freesia, clover, disy 가 읽기 전용으로 마운트할 수 있게끔 설정
한 것이다 .
프로그램 위치 시스템
Minicom version ….
XM Bulverde Linux Kernel
터미널 (1)
….
[root@EMPOS ~]#cd .. (3)
(1) [root@localhost /]# ifconfig –a
eth0 …. [root@EMPOS /]#mount –t nfs 192.168.123.166:/nfs_resource /mnt/nfs
컴퓨터
[root@localhost /]# ifconfig eth0 192.168.123.166 up [root@EMPOS /]#cd mnt/nfs

[root@localhost /]# iptables –L [root@EMPOS /]#./hello

.... 0 hello embedded world


Root 폴더
[root@localhost /]# iptables –F 1 hello embedded world

[root@localhost /]# ping 192.168.123.165 2 hello embedded world

2GB 미디어 …. [root@EMPOS /]#

[root@localhost /]# find –name nfs


….
[root@localhost /]# vi etc/exports
[root@localhost /]# mkdir nfs_resource
[root@localhost /]# cp work/hello nfs_resource/.
/nfs_resource *(rw,no_root_squash)
[root@localhost /]# service nfs restart
….
[root@localhost /]#

(2)

:wq
mount

• “mount /dev/sda1 /mnt/win” 와 같이 해서 scsi( 또는 sata) HDD 디바이스의 첫 번째 파티션에 있는


윈도우 시스템을 하나의 파일 시스템으로 취급해서 /mnt/win 으로 올려 거기서 윈도우 OS 의 file
system 인 NTFS 형태로 되어 있는 파일들을 접근할 수 있다 . 또는 가령 컴퓨터의 CD 드라이브 ( 또
는 플로피 드라이브 ) 에 있는 파일을 복사해 올 경우 , “mount /dev/cdrom(fd0) /mnt/cd(fd)” 로 해서
/mnt/cd(fd) 으로 올려 거기서 파일을 접근할 수 있다 .

• HP 에서 ( 현재 HP 는 리눅스 설치 당시에 ext3 로 파티션 포맷되어 파일시스템이 ext3 이다 .) 특정 용


량의 ext2( 또는 ext3) 의 파일시스템을 만들고 (dd … mkfs …) 여기에 새로운 파일을 넣기 위해
/mnt/ram 으로 마운트 시켜 거기서 hello 실행파일을 저장해 본다 . 이를 다시 umount 해서 변경된 파
일시스템을 만들고 이를 nfs 를 사용하여 TB 의 특정 위치에 올려 본다 . 여기서 TB 가 ext2 파일 시
스템이라면 그렇게 만들어서 올릴 필요가 있지 않을까 ? 현재 minicom 에서 디렉토리를 만들면 ext2
의 파일시스템을 마운트하는 것과 같은 것이 아니냐는 반문이 있겠지만 이것은 SDRAM 영역의 디렉토
리들이라서 전원이 나가면 마운트된 파일시스템은 사라진다 . 따라서 궁극적으로 부트 컴맨드 “ flash
ramdisk” 를 사용해서 램디스크를 flash ROM 에 저장할 필요가 있다 .

• mount –t [file system type] -o [option

mount -t ext2 /dev/sda2 /media/FEDORA


File system
• inode 는 리눅스 상에서 파일을 접근하기 위해 관련 정보를 기록한 구조체이고 이 안에 inumber 가 있
다 . 이를 사용하여 파일에 대한 접근 ID 라고 볼 수 있다 . 이와 관련해서 링크 명령어가 있다 . “ln file1
file2” 라고 하면 기존의 file1 이 새로운 file2 로 하드링크되는데 복사 (cp) 와는 달리 둘 중의 하나의 파
일이 변경되면 링크 걸린 나머지 파일도 덩달아 변경된다 . 가령 Object link embedded 와 같이 사용자
가 문서 작업에서 어떤 그림 파일을 가져와 삽입시키고 그 그림을 수정하면 그림 파일도 수정되는 식이
다 . Symbolic link 도 있는데 이것은 윈도우에서 아이콘과 같은 기능이다 . 나중에 디바이스 드라이버의
경우 INSMOD 명령어의 경우를 살펴 볼 것이다 .

파일명은 틀리지만 같은
file1 inode 를 사용하기 때문에 같
link 은 파일이다 . 그러나 하나의
파일을 수정하면 다른 파일도
inode 같이 변하게 된다 .
file2

Symbol access “ln –s dir1 symdir” 하면 이를


symdir “ symdir” 로 가리키면 dir1 에
file1 file2 data 접근이 된다 .

dir1 data block


File system
• 모든 파일들이나 디바이스들이 inode 로 등록되며 이에 대한 파일기술자 (file descriptor) 를 생성할 수
있다 . 파일기술자는 접근 순서대로 일련의 번호로 주어지며 이를 통해 해당 파일이나 디바이스에 접근
할 수 있다 .

• LED 디바이스 드라이버에서 “ insmod ledioport.ko” 를 함으로써 리눅스에 의해 inode 번호 257 이 할


당된다 . 이 inode 를 가지고 “ mknod ledioport 257 0” 로 하면 ledioport 라는 장치명이 /dev/ledioport
와 같이 생성된다 . 응용프로그램에서 “ fd = open(ledioport, ~)” 와 같이 커널 함수 ( 시스템 콜 ) 를 사용
해서 led 의 fd(file descriptor) 를 얻고 이것을 가지고 LED 에 액세스할 수 있게 된다 .

fd 0 stdin fd 0

fd 1 stdout fd 1
Process ID 5248 Process ID 5236
fd 2 stderr fd 2

fd 3
File1, inumber 3 fd 3
fd 4
File2, inumber 10 fd 4

File3, inumber 25

ledioport, inumber 257


프로그램 위치 시스템
[root@localhost /]# minicom

터미널 (1)
Minicom version ….
(1) [root@localhost /]# cd work/source ….
[root@localhost source]# ls XM-Bulverde# tftp ramdisk48_332.gz ramdisk
컴퓨터
… ramdisk48_332.gz … …. 16M tftpdone.
[root@localhost source]# gzip –d ramdisk48_332.gz XM-Bulverde# boot
[root@localhost source]# ls ….
Root 폴더
… ramdisk48_332 …
[root@localhost source]# mkdir /mnt/ramdisk [root@EMPOS ~]#cd ..
2GB 미디어 [root@localhost source]# mount –t ext2 –o loop ramdisk48_332 [root@EMPOS /]#ls
/mnt/ramdisk
Applications bin dev usr … work
[root@localhost source]# ls /mnt/ramdisk
[root@EMPOS /]#cd work
bin dev usr …
[root@EMPOS work]# . /led
[root@localhost source]# mkdir /mnt/ramdisk/work
l : left
[root@localhost source]# cp /tftpboot/led /mnt/ramdisk/work/.
r : right
[root@localhost source]# cp /tftpboot/ledioport.ko
/mnt/ramdisk/work/. q ; quit

[root@localhost source]# cp /tftpboot/test /mnt/ramdisk/work/.


[root@localhost source]# umount /mnt/ramdisk
[root@localhost source]# ls /mnt/ramdisk
[root@localhost source]# ls –l
-rwxr_xr_x ramdisk48_332 40M

[root@localhost source]# gzip ramdisk48_332
[root@localhost source]# ls –l
-rwxr_xr_x ramdisk48_332.gz 16M

[root@localhost source]# cp ramdisk48_332.gz /tftpboot/.
[root@localhost source]# ifconfig eth0 192.168.123.166 up
[root@localhost source]# service xinetd restart
[root@localhost source]#
ramdisk

• TB 의 부트 프롬프트 상황에서 “ tftp ~” 명


Flash (1) booter 2
(4)
령을 사용해 HP 로부터 램디스크 압축파일
ROM
ramdisk ramdisk 을 다운 받아 SDRAM 의 ramdisk 영역에
(3)
kernel (5)
(2) 3 쓰게 된다 . 부트 프롬프트 까지 와 있는 상
ramdisk
황에서 이미 SDRAM 에는 flash ROM 에
kernel SDRAM
있는 모든 이미지를 복사해 놓은 상황이고
bootloader
(0)
1 여기에 새로이 HP 로부터의 램디스크를 덮
n 실행 포인터
어쓰기 한 결과가 된다 . 다시 TB 의 부트
프롬프트 상황에서 “ boot” 명령을 치면
(0) 리셋되면서 0 번지에서 부트로더가 실행되면서 SDRAM 커널로 실행 포인터를 옮겨 리눅
(2) ROM 의 부트이미지를 RAM 에 복사
스가 부팅된다 . 이제 리눅스 프롬프트에서
(3) ROM 의 커널이미지를 RAM 에 복사
“ ls” 를 치면 HP 에서 만든 파일시스템이
(4) ROM 의 램디스크 이미지를 RAM 에 복사하고 나면
(5) 부트 프롬프트 (XM-Bulverde#) 에서 키입력 대기 상태에서 “ tftp ~” 명령을 그대로 나타난다 .
치면 HP 로부터 램디스크 압축파일인 ramdisk48_322.gz 이 RAM 의 ramdisk
영역으로 기존에 복사된 램디스크 위에 겹쳐 쓰게 된다 .
(6) 부트 프롬프트 (XM-Bulverde#) 에서 키입력 대기 상태에서 “ boot” 명령을
• 다시 TB 를 리셋 시키면 TB 의 flash ROM
치면 RAM 의 복사된 커널 영역으로 실행 포인터가 넘어가 linux 가 TB 에서 실
에 있던 램디스크 이미지가 SDRAM 의
행하게 된다 . ramdisk 영역에 깔리고 방금 전에 HP 로부
터의 램디스크 이미지는 사라진다 . 리눅스
가 부팅된 다음에 “ ls” 를 치면 HP 에서 만
든 파일시스템이 아님을 볼 수 있다 .
jffs(journalling flash file system)

• ramdisk 의 경우 TB 에 깔려 있는 기본적인 리눅스 디렉토


리 구조를 가진 ramdisk48_332.gz 에 HP 에서 개발된 응
Flash booter
ROM 용 프로그램을 추가해서 TB 의 tftp 부트 컴맨드를 사용해
ramdisk
usr kernel
서 다운로드 한 후 TB 의 boot 부트 컴맨드를 사용해서
ramdisk kernel 부팅하면 SDRAM 에 올려진 새로운 ramdisk 로 갱
kernel SDRAM 신됨을 볼 수 있고 여기서 개발된 응용 프로그램들을 수행
bootloader 한 후 성능이 확인되면 TB 를 다시 리셋 시키고 부트 모드
TB 에서 “ tftp ramdisk48_332.gz ramdisk” , “flash ramdisk” 를
사용하여 flash ROM 에 굽는다 .

• 이것과는 다르게 TB 에 깔려 있는 기본적인 리눅스 디렉토


리 구조를 가진 ramdisk48_332.gz 에 추가하지 않고 곧 바
로 flash ROM 에 구워지는 파일시스템인 jffs2 를 사용한
다 . 즉 TB 에 추가하고자 하는 디렉토리를 “ mkfs.jffs2 –p
–o usr.jffs -e 0x40000 –r work_xm_bulverde” 와 같이 해서
Jffs2 이미지
jffs2 이미지인 usr.jffs 를 TB 의 tftp 부트컴맨드를 사용하

“mkfs.jffs2 –p –o usr.jffs -e 0x40000 –r work_xm_bulverde”

디렉토리
padding 지우는 영역 256KB
jffs(journalling flash file system)

프로그램 위치 시스템
[root@localhost /]# minicom

터미널 (1)
Minicom version ….
(1) [root@localhost /]# cd work/tools/jffs ….
[root@localhost jffs]# ls XM-Bulverde# tftp usr.jffs usr
컴퓨터
… mkfs.jffs2 … …. 16M tftpdone.
[root@localhost jffs]# cp mkfs.jffs2 /usr/local/bin/. XM-Bulverde# boot
[root@localhost jffs]# vi ~/.bash_profile ….
Root 폴더
… path 등록 Kernel Panic
[root@localhost jffs]# source ~/.bash_profile

2GB 미디어 [root@localhost jffs] cd /work


[root@localhost work]# ls
bin dev usr … work_xm_bulverde
[root@localhost work]# mkfs.jffs2 –p –o usr.jffs –e 0x40000 –r work_xm_bulverde
[root@localhost work]# ls
bin dev usr … work_xm_bulverde usr.jffs
[root@localhost work]# cp usr.jffs /tftpboot/.
[root@localhost work]# ifconfig eth0 192.168.123.166 up
[root@localhost work]# service xinetd restart
..
[root@localhost work]#
fdisk, mkfs

• /etc/fstab, mtab 설정 파일

255heads * 63sector/track = 16065


[root@localhost /]# fdisk -l
16065 * 512byts = 8225280bytes
Disk /dev/sda: 41.1GB
8225280bytes * 5005cylinders = 41,167,526,400~41.1GB
255 heads, 63 sectors/track, 5005 cylinders
device boot start end blocks id system
/dev/sda1 * 1 2550 20482843(20GB) 7 NTFS
/dev/sda2 2551 2575 200812(200MB) 83 Linux boot
/dev/sda3 2576 5005 19518975(19GB) 8e Linux
LVM(swap)
……
[root@localhost /]#
Application program

• 응용 프로그램의 main.c 에서는 거기서 참조하는 함수 원형 , 심볼 , 자료형 등을 등록하고 있는 헤더


파일들을 포함시킨다 . 컴파일할 때 그 헤더파일들에 관련된 소스파일들을 main 소스파일과 더불어
각자 컴파일하고 이들의 상호 관계를 링크시킨 후 하나의 실행 이미지를 생성한다 .

• 응용 프로그램의 main.c 가 참조하는 라


이브러리 정체 : API, OS 를 구성하는
cstexint.a96
exint.c
libmodule.obj system call 및 라이브러리 함수 , 디바이
/80C196.h
스 드라이버

MCS- 96
Macro Assembler
C Compiler
IC96.EXE
Librarian
LIB.EXE
• 명령어와 shell script, 설정 파일의 script
ASM96.EXE
cstexint.obj exint.obj enable.obj
/cstexint.lst /exint.lst in c96.lib
API

MCS- 96 System call


Relocator & Linker
RL96.EXE
exint.abs Virtual file
/exint.m96
system
Intel Hexa Converter
OH.EXE
character,
exint.hex
block, network
device driver
Application program
source
stdio.h prog1.c prog2.c prog3.c
file

Librarian C compiler(MFC visual C++, mc.exe)


(lib.exe) mc prog1.c, mc prog2.c, mc prog3.c

object
lib.obj prog1.obj prog2.obj prog3.obj
file

Relocater/Linker(link.exe)
link prog1.obj, prog2.obj, prog3.obj

executable
prog1.exe
file

• arm-linux-gcc(C compiler) -c(compile), –o(object), -I(Include), -g(debug), -E(preprocessor), -Wall


(Warning all), -O2(Optimization level2)

• arm-linux-ar(archive manager)
Application program

• main.c 에서 사용하는 것은 ref1.h 에 정의된 함수이고 ref1.c 에 구현된 함수는 ref2.h 를 포함시켜
ref2.c 에서 구현한 함수를 사용한다 . 이 경우에 main.c 에서는 ref2.h 를 포함시켜야 할까 ?

//tst1-main.c
#include <stdio.h>
main.c #include "tst1_ref1.h"

#include “ref1.h” int main(){


int a, b, c;
a=1;
ref1.h ref2.h b=2;
ref1.c ref2.c c=cal(a,b);
printf(“1st operand %d, 2nd operand%d result %d\n", a, b, c);
return 0;
}

//tst1-ref1.c //tst1-ref2.c
#include "tst1_ref1.h" #include "tst1_ref2.h"
#include "tst1_ref2.h"
int sqr(int x){
int cal(int x, int y){ return x*x;
int z; }
z=sqr(x)+sqr(y);
return z; //tst1-ref2.h
}
int sqr(int x);
//tst1-ref1.h
int cal(int x, int y);
make and makefile

• make 의 필요성
make 유틸리티의 목적은 프로그램 그룹 중에서 어느 부분이 새롭게 컴파일되어야 하는지를 자동적으
로 판단해서 필요한 커맨드 (gcc 따위 ) 를 이용해서 그들을 재컴파일 한다 . 우선은 make 의 사용을
프로그램 개발과 유지 쪽으로 국한시키기로 한다 . 보통 라인 수가 많아지면 여러 개의 파일로 나누어
( 모듈로 나누어 ) 개발을 하게 된다 . 이들은 알게 모르게 서로 관계를 가지고 있는데 , 어느 하나를
필요에 의해 바꾸게 되었을 때 그 파일에 있는 함수를 이용하는 다른 파일도 새롭게 컴파일되어야 한
다 . 하지만 파일 수가 많은 경우 이를 일일이 컴파일을 하게 될 때 , 그 불편함과 함께 컴파일하지 않
아도 될 것도 컴파일을 하게 될 수도 있고 , 컴파일해야 할 것도 미처 못하게 되는 경우가 있다 ( 링크
에러의 원인이 되기도 하는데 에러의 원인을 제대로 찾기가 힘이 든다 ).

• GNU make 는 보통 GNUmakefile, Makefile, makefile 중에서 하나가 있으면 그 파일을 읽게 된다 . 하


지만 일반적으로 Makefile 을 추천하게 되는데 , 그 이유는 우선 GNUmakefile 은 기존의 make 에서
인식을 못한다는 단점이 있고 , makefile 은 보통 소스 파일에 묻혀서 잘 안보이게 되기 때문이다 .

• Makefile 은 make 가 이해할 수 있도록 일종의 쉘 스크립트 언어같이 되어 있다 . 이 파일에는 결과 파


일을 생성시키기 위한 파일들간의 관계 , 명령어 등을 기술한다 .
Makefile 은 기본적으로 아래와 같이 목표 (target), 의존 관계 (dependency), 명령 (command)
의 세개로 이루어진 기분적인 규칙 (rule) 들이 계속적으로 나열되어 있다고 봐도 무방하다 .
make 가 지능적으로 파일을 갱신하는 것도 모두 이 간단한 규칙에 의하기 때문이다 .
--------------------------------------------------------------------------------

target ... : dependency ...


command
...
...

--------------------------------------------------------------------------------

여기서 목표 (target) 부분은 명령 (command) 이 수행이 되어서 나온 결과 파일을 지정한다 . 당


연히 목적 파일 (object file) 이나 실행 파일이 될 것이다 .

명 령 (command) 부분에 정의된 명령들은 의존 관계 (depenency) 부분에 정의된 파일의 내용이


바뀌었거나 , 목표 부분에 해당하는 파일이 없을 때 이곳에 정의된 것들이 차례대로 실행이 된
다 . 일반적으로 쉘에서 쓸 수 있는 모든 명령어들을 사용할 수가 있으며 bash 에 기반한 쉘 스
크립트도 지원한다 .

=> 참고 : 참고로 목표 부분에는 결과 파일만 올 수 있는 것이 아니고 , 보통 make clean 에서


와 같이 간단한 레이블 (label) 기능을 제공하기도 한다 .

=> 명령 부분은 꼭 TAB 글자로 시작해야 한다 . 그냥 빈칸 등을 사용하면 make 실행 중에 에


러가 난다 . 명심하세요 . make 가 명령어인지 아닌지를 TAB 가지고 구별하기 때문이죠 .
우리가 만들려고 하는 프로그램은 main.c read.c write.c 로 구성되어 있고 모두 io.h 라는 헤더 파일을 사용한다고 가정한
다 . 이들을 각각 컴파일해서 test 라는 실행 파일을 생성시킨다 .

% gcc -c main.c
% gcc -c read.c
% gcc -c write.c
% gcc -o test main.o read.o write.o

위의 방식은 make 를 쓰지 않고 그냥 명령어를 주는 방식이다 . 파일의 수가 작아서 오히려 더 간단하게 보일 수 있으나 ,


파일이 100 개정도 된다고 가정하면 ... 아찔 ...

그리고 , 아래는 위와 똑같은 일을 수행하는 Makefile 의 내용이다 .

Makefile 예제 1

--------------------------------------------------------------------------------

test : main.o read.o write.o


gcc -o test main.o read.o write.o

main.o : io.h main.c


gcc -c main.c
read.o : io.h read.c
gcc -c read.c
write.o: io.h write.c
gcc -c write.c
www.linux.co.kr에서 “ makefile” 로 검색
--------------------------------------------------------------------------------
make 이용법 .hwp 참조

가 령 main.c 를 고쳤다고 생각한다면 main.o 가 컴파일되어 다시 생기고 , test 도 다시 링크되어 갱신된다 . 만약 io.h 가
바뀌었다고 가정하면 모든 파일들이 컴파일되어서 목적 파일이 생기고 , 그것들이 링크가 되어 test 가 생긴다 .
[root@localhost work]# vi tst1-main.c • “make label” 은 그 디렉토리에 있는 Makefile 내부의
[root@localhost work]# vi tst1-ref1.c
label 부분을 실행한다 . 가령 “ make clean” 을 실행
[root@localhost work]# vi tst1-ref2.c
[root@localhost work]# vi tst1-ref1.h 하면 Makefile 내부의 clean 부분을 실행해서 컴파일
[root@localhost work]# vi tst1-ref2.h
된 파일을 지운다 .
[root@localhost work]# gcc –c tst1-main.c
[root@localhost work]# gcc –c tst1-ref1.c
[root@localhost work]# gcc –c tst1-ref2.c • “make –option” 의 option 에는 디렉토리를 바꿔 거기
[root@localhost work]# gcc –o tst1 tst1-main.o tst1-ref2.o tst1-ref2.o 에 있는 Makefile 을 참조할 경우 “ -C” 를 사용한다 .
[root@localhost work]# ./tst1
기타 ‘ -t’ option
1st operand 1 2nd operand 2 result 5
[root@localhost work]#
• Macro : CC, CFLAG 등의 이름에 마크로 기능사용

• $@ : 현재 목적파일 , $* : 확장자가 없는 현재 목적파


일 , $> : 가장 최근에 갱신된 목적파일

[root@localhost work]# vi Makefile


tst1: tst1-main.o tst1-ref1.o tst1-ref2.o
[root@localhost work]# make
gcc -o tst1 tst1-main.o tst1-ref1.o tst-ref2.o
gcc -o tst1 tst1-main.o tst1-ref1.o tst-ref2.o
tst1-main.o: tst1-main.c tst1-ref1.h # 왜 <stdio.h> 는 않 포함시키지
[root@localhost work]# ls
gcc -c tst1-main.c
Makefile tst1 tst1-main.c tst1-main.o tst1-ref1.c tst1-ref1.o tst1-
ref2.c tst1-ref1.o: tst1-ref1.c tst1-ref1.h tst1-ref2.h

tst1-ref2.o tst1-ref1.h tst1-ref2.h gcc -c tst1-ref1.c

[root@localhost work]# make clean tst1-ref2.o: tst1-ref2.c tst1-ref2.h

rm tst1-main.o tst1-ref1.o tst-ref2.o gcc -c tst1-ref2.c

[root@localhost work]# ls clean:

Makefile tst1 tst1-main.c tst1-ref1.c tst1-ref2.c tst1-ref1.h tst1-ref2.h rm tst1-main.o tst1-ref1.o tst-ref2.o

[root@localhost work]#

:wq
Bootloader porting to Target Board

• 이전에 /work/ 밑에 한백 CD 의 source 디렉토리를 X-


window 에서 복사한 적이 있다 . /work/source/kernel/linux-
2.6.12.tar.gz 를 압축 해제하면 linux-2.6.12 디렉토리가 생
기고 그 밑에 linux 커널 소스 파일들이 있다 .

• 이 소스파일들에 대해 TB 의 CPU 인 PXA272 chip 에 맞게


패치해 줄 필요가 있다 . 이를 위해
/work/source/kernel/patch/diff-linux-2.6.12-
xm_buverde_p1.gz 패치 파일을 zcat(gzip 파일에 대한
cat) 를 patch 명령어로 리다이렉트시켜 포팅할 소스파일들
에 대한 패치작업을 한다 .

• patch 디렉토리에 있는 readme.txt 파일을 gedit 로 열어서


그 안에 서술된 내용대로 driver 파일들을 복사해

• make empos_xm_defconfig 를 사용하여 XM 장비에 맞는


요소들을 선택한다 .

• Make zImage 를 통해 최종적인커널 image 인 zImage 를


생성한다 . 이상한 것은 Makefile 안에
empos_xm_defconfig, zImage 의 레이블이 없네요 .

• make clean 해서 모든 목적 코드를 삭제한다 .


LINUX porting to Target Board

[root@localhost work]# cd source/kernel • 이전에 /work/ 밑에 한백 CD 의 source 디렉토리를 X-


[root@localhost kernel]# tar –xvzf linux-2.6.12.tar.gz window 에서 복사한 적이 있다 . /work/source/kernel/linux-
[root@localhost kernel]# cd linux-2.6.12
[root@localhost linux-2.6.12]# ls
2.6.12.tar.gz 를 압축 해제하면 linux-2.6.12 디렉토리가 생
Makefile arch drivers include sound net init scripts mm lib kernel 기고 그 밑에 linux 커널 소스 파일들이 있다 .
usr security fs crypto …
[root@localhost linux-2.6.12]# cp /work/source/kernel/patch/diff-linux-
2.6.12-xm_bulverde_p1.gz .
[root@localhost linux-2.6.12]# zcat diff-linux-2.6.12-
• 이 소스파일들에 대해 TB 의 CPU 인 PXA272 chip 에 맞게
xm_bulverde_p1.gz | patch –p1 패치해 줄 필요가 있다 . 이를 위해
Patching file Makefile /work/source/kernel/patch/diff-linux-2.6.12-
Patching file arch/..
Patching file drivers/.. xm_buverde_p1.gz 패치 파일을 zcat(gzip 파일에 대한
…. cat) 를 patch 명령어로 리다이렉트시켜 포팅할 소스파일들
[root@localhost linux-2.6.12]# cp ../patch/driver_obj/qcif/ 여러파일들
driver/i2c/. 에 대한 패치작업을 한다 .
….
[root@localhost linux-2.6.12]# make empos_xm_defconfig

• patch 디렉토리에 있는 readme.txt 파일을 gedit 로 열어서
[root@localhost linux-2.6.12]# make zImage
그 안에 서술된 내용대로 driver 파일들을 복사해


…..
[root@localhost linux-2.6.12]# find –name zImage make empos_xm_defconfig 를 사용하여 XM 장비에 맞는
. /arch/arm/boot/zImage 요소들을 선택한다 .
[root@localhost linux-2.6.12]# make clean

• Make zImage 를 통해 최종적인커널 image 인 zImage 를


생성한다 . 이상한 것은 Makefile 안에
empos_xm_defconfig, zImage 의 레이블이 없네요 .

• make clean 해서 모든 목적 코드를 삭제한다 .


Linux source files
• arch/ directory : architecture-dependent 코드가 arch/ 디렉토리 안에 존재하며 이 디렉토리 아래에 , 리눅스 각각의 존재하는
하위 디렉토리가 있다 (kernel/, lib/, 그리고 mm/). kernel/ 하위 디렉토리는 signal handling, clock handling 등과 같
은 일반적인 커널 특징의 architecture-dependent 구현을 포함한다 . lib/ 하위 디렉토리는 architecture-dependent 소스
코드로부터 컴파일된다면 더 빠르게 실행할 수  있는 라이브러리 함수의 지역적 구현을 포함한다 . mm/ 하위 디렉토리는 지역적
memory handling 구현을 포함한다 .

• drivers/ directory : 모든 디바이스 드라이버들의 소스 코드가 drivers/ 디렉토리에 존재한다 . 리눅스 2.4 에 의해 지원되는 장치의
다양함 때문에 , 여기에 많은 소스 코드가 있다 . 실제로 모든 커널 소스의 50 퍼센트 이상이 drivers/ 디렉토리안에 존재한다 .

• fs/ drirectory : 모든 지원되는 파일 시스템을 위한 장소이다 . IBM 의 JFS 나 Hans Reiser's reiserfs 같은 새로운 파일 시스템이
필요하면 그 파일 시스템에 소스 코드를 포함하는 이 디렉토리에 패치해야 한다 .

• include/ directory : 새로운 커널이 실제로 컴파일되기 전에 설정되어져야 하며 , 이 설정에서 어느 드라이버 , 특징들 , 모듈들이 커
널안으로 컴파일될 것인지를 make 유틸리티에게 알려주는 것을 의미한다 . 기본적으로 , 대부분의 표준 배포판은 단일 프로세서 커널
로 나온다 . 커널의 표준 SMP(Symetric Multiple Processor) 특징을 구현하기 위해서는 , SMP 를 포함한 설정이 요구된다 .

• ipc/ directory ; 프로세스간 통신을 다루는 데 필요한 모든 코드가 ipc/ 안에 있다 . 모든 중요한 세마포어 (Semaphore) 핸들링 C
코드가 여기에 있다 (sem.c).

• init/ directory : fork() 를 구현하는 코드 , 자주 실행되는 코드인 cpu_idle() loop 같은 매우 중요한 코드를 포함하는 Main.c 는
init/ 디렉토리 안에 존재한다 . 시스템 부팅 과정에서 읽는 bogomips 를 계산하는 코드는 스피드의 표시를 위해 그것을 참조하는
사람들을 위해 여기에 있다 . BogoMips reading 은 가끔 컴퓨터의 성능을 표시하는 기준이 된다 . 그러나 프로세서가 시스템 성능을
모두 표시하는 것은 아니며 noop(no operation) 을 수행하는데 걸리는 시간을 측정하는 것이다 .

• lib/ directory : lib/ 디렉토리는 종종 커널의 다른 부분에 의해 필요로 하는 코드를 가지고 있다 . 이를테면 , inflate.c 가 여기에
속한다 . 이 코드는 시스템이 부팅할 때 커널을 압축 해제하고 그것을 메모리에 로드한다 . 그것은 또한 표준 PKZIP 8-bit 압축 알
고리즘을 압축 해제하는 프로그램을 갖고 있다 .

• kernel/ directory : 대부분 보통 커널 함수라 불리는 일부가 kernel/ 디렉토리에 존재한다 . 스케줄러 , fork(), 그리고 timer.c
를 여기에 속한다 . 또한 printk.c 를 이 디렉토리에서 발견할 수 있으며 커널 소스 코드 전체에 걸쳐서 printk() 는 printf()
대신에 사용된다 . printf() 함수는 커널 안으로부터 호출될 때 SMP-capable 하지 않다 .

• mm/ directory : mm/ 디렉토리는 리눅스 커널에서 가상 메모리 매니저를 구현하는 소스 코드를 포함한다 .

• net/ directory : 네트워킹 지원을 위한 모든 소스 코드는 net/ 디렉토리 안에 있다 . TCP/IP, Netware, 그리고 Appletalk 가 모
두 여기에 있다 .
LINUX porting to Target Board

• HP 에서 linux-2.6.12 및 PXA 칩 및 XM 장비 특성에 부합하기 위해 patch 를 적용한 다음 그


소스 파일들을 컴파일해서 이미지를 생성한 다음 TB 의 SDRAM 으로 커널 포팅을 위해 HP 에서
는 xinetd 데몬을 구동하고 tftpboot 디렉토리에 커널이미지를 올려 놓고 TB 에서는 tftp 부트컴
맨드를 사용해서 다운 받는다 . 이후 TB 에서 boot 라는 컴맨드를 사용하여 SDRAM 의 커널 영
역으로 실행 포인터를 넘겨줘서 linux 가 부팅되도록 한 후 성능 검증한다 . 성능 검증에 이상이 없
으면 TB 를 리셋해서 부트컴맨드에서 SDRAM 에 있던 커널을 flash 부트 컴맨드를 사용하여
flash ROM 에 fusing 한다 . 이때 주의할 것은 리셋되면서 부트로더가 flash ROM 에 있던 원래의
kernel 을 SDRAM 으로 복사해서 포팅하려던 커널이미지를 덮어쓰기 전에 부트컴맨드 상태로 진
입해야 하는데…

• 한백 CD 에 있는 linux-2.6.12.tar.gz 를 복사해서 HP 의 /work/source/kernel 밑에 두고 「 tar


xvfz linux-2.6.12.tar.gz 」로써 압축 해제하면 /work/source/kernel/linux-2.6.12 디렉토리가 생성
되고 그 밑에 패치가 않된 2.6.12 버전의 리눅스 소스파일들이 있게 된다 . 먼저 패치를 수행한 후
patch 디렉토리에 있는 readme.txt 파일을 gedit 로 열어서 그 안에 서술된 내용대로 driver 파일
들을 복사해 넣는다 . 「 make empos_xm_defconfig 」를 쳐서 설치 옵션을 설정하고 「 make
zImage 」를 쳐서 컴파일을 실행하고 zImage 라는 최종 이미지를 생성한다 . zImage 생성 위치는
/work/source/kernel/linux-2.6.12/arch/arm/boot/ 에 있음 .
led program

• TB 에 연결된 시리얼 포트를 통해 키 입력을 받아 ‘ r’ 이면 0x0880500 물리주소에 위치한 led 를 오


른쪽으로 쉬프트 하고 ‘ l’ 을 치면 왼쪽으로 쉬프트 하고 ‘ q’ 를 치면 끝내는 응용 프로그램을 TB 에서
동작시켜 본다 .
• 프로그램 코드 : termios 를 이용해
시리얼 키를 인식하는데 먼저 키보드
초기화 함수인 init_keyboard( ), 키보
드 입력이 들어오는지를 알려주는 함
수 kbhit( ) 사용이 끝나면 닫아주는
close_keyboard( ) 함수로 구성된다 .
open( ) 함수를 이용해서 /dev/mem
의 파일기술자를 얻고 이 파일 기술자
와 물리 주소값을 바탕으로 mmap 을
이용해서 0x0880500 물리주소를 논
리주소로 변환시킨 후에 이 위치에 값
을 써 넣음으로써 led 출력 점등을 제
어 한다 . led 제어가 종료되면
munmap( ) 함수로 mmap( ) 함수를
U13 74LCX374
종료하고 close( ) 로 파일기술자를 닫
는다 .
led program using mmap
프로그램 위치 시스템
Minicom version ….
XM Bulverde Linux Kernel
터미널 (1)
[root@localhost /]# cp media/FEDORA/led.c work/. ….

(1) [root@localhost /]# cd work [root@EMPOS ~]# Ctrl+a, z


[root@localhost work]# arm-linux-gcc -o led led.c [root@EMPOS ~]#ls
컴퓨터 …..
[root@localhost work]# ls led
[root@EMPOS ~]#./led Send file S
Hello hello.c led led.c
(3) Port setup P
Root 폴더 [root@localhost work]# (2)
….
S
…..

2GB 미디어 Zmodem


…..
….
[work] led
….

이를 위해 먼저 usb 메모리에 있는
led.c 를 HP 의 work 디렉토리 밑에 복
사해 넣고 이것을 컴파일해서 최종 실행
파일을 TB 의 work 디렉토리로 tftp,
nfs, 또는 z-modem 을 사용해 전송한
다 . 전송한 후 TB 의 work 디렉토리에
있는 led 실행파일을 “ ./led” 로 해서 실
행시켜 본다 . 이때 TB 의 LED 가 제대
로 점멸되는지를 확인해 본다 .
/*led.c HP 와 TB 가 시리얼 포트로 연결되어 minicom 을 통해
TB 의 리눅스에서 “ ./led” 를 실행하면 ‘ l’, ‘r’, ‘q’ 키 값에 대해 왼
쪽 , 오른쪽으로 led 를 쉬프트 , 끝내기를 할 수 있다 . int kbhit(){
char ch;
#include <stdio.h> int nread;
#include <stdlib.h>
#include <unistd.h> • 이 응용 프로그램에서 key board 관련 통신에 대한 함
if(peek_character != -1) return 1;
수 및 읽기 함수를 구현했는데 거기서 사용한 tcgetattr(
#include <sys/types.h>
#include <sys/mman.h> ), tcsetattr( ), read( ), open( ), close( ), mmap( ),
new_settings.c_cc[VMIN] = 0;
#include <sys/stat.h> munmap( ), usleep( ) 함수들 각각은 어떤 헤더 파일에 tcsetattr(0,TCSANOW,&new_settings);
#include <fcntl.h> 서 정의되나 ? 그 헤더파일들은 어느 디렉토리에 존재 nread = read(0,&ch,1);
#include <sys/ioctl.h> 하는가 ? Arm compiler 의 library 인 new_settings.c_cc[VMIN] = 1;
#include <termios.h> /usr/local/arm/3.3.2/include 밑에 있나 . tcsetattr(0,TCSANOW,&new_settings);

#define ADDRESSOFLED 0x08805000 if(nread == 1) {


peek_character = ch;
static struct termios initial_settings, new_settings; return 1;
static int peek_character = -1; }
return 0;
void init_keyboard(){ }
tcgetattr(0,&initial_settings);
new_settings = initial_settings; int readch(){
new_settings.c_lflag &= ~ICANON; char ch;
new_settings.c_lflag &= ~ECHO;
new_settings.c_lflag &= ~ISIG; if(peek_character != -1) {
new_settings.c_cc[VMIN] = 1; ch = peek_character;
new_settings.c_cc[VTIME] = 0; peek_character = -1;
tcsetattr(0,TCSANOW,&new_settings); return ch;
} }
read(0,&ch,1);
void close_keyboard(){ return ch;
tcsetattr(0,TCSANOW,&initial_settings); }
}
int main(void){ while(dir != 'q'){
int fd;
unsigned char *addr_led; if(dir == 'l') {
unsigned char dir; val2 = (~(val >> 7)) & 0x1;
unsigned char val, val2; val = (val << 1) | val2;
unsigned char ch = 'l'; }
else if( dir == 'r') {
if ((fd=open("/dev/mem",O_RDWR|O_SYNC)) < 0){ val2 = (~(val << 7)) & 0x80;
perror("mem open fail\n"); val = (val >> 1) | val2;
exit(1); }
}
*addr_led = val;
addr_led=mmap(NULL,1,PROT_WRITE,MAP_SHARED,fd,ADDRESSOFLED);
if(kbhit()){
if(((int)addr_led < 0) ){
ch = readch();
addr_led=NULL;
switch(ch){
close(fd);
case 'r': dir = 'r'; break;
printf("mmap error\n");
case 'l': dir = 'l'; break;
return -1;
case 'q': dir = 'q'; break;
}
}
}
init_keyboard();
usleep(100000);
printf("\n8bit LED IO Interface Procedure\n");
}
printf("--------------------------------------\n");
printf(" l for left shift\n");
*addr_led = 0x00;
printf(" r for right shift\n");
close_keyboard();
printf(" q for exit\n");
munmap(addr_led, 1);
printf("--------------------------------------\n");
close(fd);
return 0;
*addr_led = 0;
}
val = 0;
val2 = 0;
ioremap 함수를 사용하여 LED 의 물리주소
LED driver (0x08805000) 및 길이 (1 byte) 를 주고 이로부터 논
리주소를 얻어 ledioport_ioremap 포인터 변수에 저
장한다 .

//fimename : ledioport.c 는 main( ) 함수가 없는 파일 조작 함수들로만


구성된 led 드라이버이다 .
int ledioport_open(struct inode *minode, struct file *mfile) {

if(ledioport_usage != 0) return -EBUSY;


#include <linux/init.h>
#include <asm/uaccess.h> ledioport_ioremap= ioremap(LEDIOPORT_ADDRESS,LEDIOPORT_ADDRESS_RANGE);
if(!check_region(ledioport_ioremap,LEDIOPORT_ADDRESS_RANGE))
#include <linux/module.h>
request_region(ledioport_ioremap,LEDIOPORT_ADDRESS_RANGE,LEDIOPORT_NAME);
#include <linux/fs.h> else printk(KERN_WARNING"Can't get IO Region 0x%x\n",ledioport_ioremap);
#include <asm/io.h>
ledioport_usage = 1; 얻은 논리주소 및 길이로부터 check_region( ) 을 사
#include <linux/init.h> return 0; 용하여 영역이 있나 검토하고 있으면
} request_region( ) 을 사용하여 영역 요구를 하고 영역
#include <linux/kernel.h>
이 할당되었다는 flag ledioport_usage 를 ‘ 1’ 로 셋한
#include <linux/ioport.h> 다.
int ledioport_release(struct inode *minode, struct file *mfile) {

#define DRIVER_AUTHOR "hanback" iounmap(ledioport_ioremap);


#define DRIVER_DESC "led test program" release_region(ledioport_ioremap,LEDIOPORT_ADDRESS_RANGE);
ledioport_usage = 0;
#define LEDIOPORT_MAJOR 0 return 0;
} inode 와 파일 포인터를 받아 iounmap( ) 및
#define LEDIOPORT_NAME "LED IO PORT"
release_region( ) 을 사용하여 ledioport_ioremap 에
#define LEDIOPORT_MODULE_VERSION "LED IO PORT V0.1" 해당하는 할당된 논리주소 영역을 릴리즈하고 더 이
상 영역이 할당되지 않았음을 표시하는 flag
#define LEDIOPORT_ADDRESS 0x08805000 ledioport_usage 를 ‘ 0’ 으로 리셋한다 .
Ioremap, check_resion,
#define LEDIOPORT_ADDRESS_RANGE 1
request_region, printk,iounmap,
static struct file_operations led_fops = {
release_region, get_user,
write : ledioport_write_byte,
register_chrdev,
//Global variable open : ledioport_open, OS 에서 지원하는 시스템콜 함수 포
unregister_chrdev 함수들이 참
release : ledioport_release, 인터 open, write, close 로 구성된 파
static int ledioport_usage = 0; 조하는 헤더 파일들은 ? 헤더파
}; 일조작 구조체에서 led 드라이버 함수
일들은 어디에 ? 아마도 TB 에
static int ledioport_major = 0; 포인터를 대응시켜 드라이버가 OS
깔려 있는 리눅스 OS 의 라이브
커널에 삽입된 이후에 프로그래머가
static unsigned char *ledioport_ioremap; 러리 , /work/linux-
2.4.12xm_buverde/include 밑에 OS 시스템콜 함수를 사용해도 드라이
헤더파일들이 존재함 . 버의 연계된 함수가 호출되도록 한다 .
LED driver
ssize_t ledioport_write_byte(struct file *inode, const char *gdata, size_t length, loff_t *off_what) {
unsigned char *addr;
unsigned char c; inode 와 쓰여질 데이터 포인터 , 길이 등을 인수로
해서 led 의 논리주소인 ledioport_ioremap 의 위치
get_user(c,gdata); 에 데이터를 씀 module_init(led_init);
module_exit(led_exit);
addr = (unsigned char *)(ledioport_ioremap);
*addr = c;
return length;
MODULE_AUTHOR(DRIVER_AUTHOR);
}
MODULE_DESCRIPTION(DRIVER_DESC);
int led_init(void) { MODULE_LICENSE("Dual BSD/GPL");

int result; 매크로를 사용하여 insmod, mknod 의


result = register_chrdev(LEDIOPORT_MAJOR,LEDIOPORT_NAME,&led_fops); 명령어에 대해 led_init 함수가 호출되도
록 하고 rmnod 의 명령어에 대해서는
if(result < 0) { led_exit 함수를 호출되도록 한다 .
printk(KERN_WARNING"Can't get any major\n");
return result;
}
열기 , 쓰기 , 닫기 드라이버 함수와 이에 상응하는 OS 시스템 콜함수를 대
응시킨 파일 조작 구조체 &led_fops 를 인수로 해서 OS 에서 지원하는 문자
ledioport_major = result;
디바이스 등록하는 함수 register_chrdev( ) 를 사용하여 주번호를 할당 받아
전역 변수인 ledioport_major 에 저장해서 나중에 드라이버 해제할 때 사용한
printk("init module, ledioport major number : %d\n",result);
다 . 성공적으로 드라이버 등록이 되면 주번호를 디스플레이 한다 .
return 0;
}

void led_exit(void) {
if(unregister_chrdev(ledioport_major,LEDIOPORT_NAME))
printk(KERN_WARNING"%s DRIVER CLEANUP FALLED\n",LEDIOPORT_NAME);

else printk("driver: %s DRIVER EXIT\n", LEDIOPORT_NAME); ledioport_major 에 저장된 주번호로부터 문자 디바이스 등록을 해
} 제하고 성공 여부에 대한 메시지를 출력한다 .
LED driver
//test.c 는 TB 의 리눅스 터미널에서 “ ./test 0x23” 과 같이 치면 led
에 출력하는 응용 프로그램이다 .

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv)


{
int dev;
char buff;

if(argc <= 1) {
printf("please input the parameter! ex)./test 0xa1\n");
return -1;
}
드라이버의 int ledioport_open(struct inode *minode, struct file *mfile) {}
이 open( ) 함수에 대응됨 . “/dev/ledioport” 는 insmod 및 mknod 명령
dev = open("/dev/ledioport", O_WRONLY);
어에 의해 등록된 led 의 파일 형태이다 .
if (dev != -1)
{
if(argv[1][0] == '0' && (argv[1][1] == 'x' || argv[1][1] == 'X'))
buff = (unsigned char)strtol(&argv[1][2],NULL,16);
else
buff = atoi(argv[1]); 드라이버의 ssize_t ledioport_write_byte(struct file *inode, const char *gdata, size_t length, loff_t
write(dev,&buff,1); *off_what) { } 이 write( ) 함수에 대응되고
close(dev); write( ) 의 첫 번째 인수인 dev 와 *inode 는 일치하지 않는데 ?
}
else 드라이버의 int ledioport_release(struct inode *minode, struct file *mfile) { } 이
{ close( ) 함수에 대응되고
printf( "Device Open ERROR!\n"); close( ) 의 첫 번째 인수인 dev 와 *inode 는 일치하지 않는데 ?
exit(-1);
}

return(0);
}
LED driver

• HP 에서 한백 CD 를 삽입하고 /media/NEW 에서 /spource 를 /work 밑에 폴더 복사해 놓고


“ /work/source/CYC2C8_src/Device_Driver/bus-led_driver/ledioport.ko 및 test 파일을 z-
modem(tftp) 을 사용해 TB 로 다운받는다 . nfs 를 사용하여 다운 받는 것이 아니라 HP nfs server 의
파일을 공유한다는 차원이기 때문에 다소 문제가 있다 . 공유의 의미가 무얼까 ?

실제로는 HP 에서 /work/led_driver 디렉토리를 만들고 거기에 ledioport.c 및 test.c 를 복사해 놓고


거기서 Makefile 에 정의된 대로 make 해서 led 드라이버 오브젝트인 ledioport.ko 및 응용 실행파
일인 test 를 생성해서 TB 로 다운로드 해서 거기서 실행시킨다 .

• TB 에서 다운 받은 ledioport.ko 를 가지고 insmod 및 mknod 명령어를 사용하여 /dev/ledioport 드


라이버를 등록한다 .

• TB 에서 “ ./test 0x11” 를 실행하면 led 에 0x11 로 점등함을 확인할 수 있다 .

• < 이상한 점 > (1) HP 에서 linux-2.6.12 및 PXA 칩 및 XM 장비 특성에 부합하기 위해 patch 를 적


용한 다음 그 소스 파일들을 컴파일해서 이미지를 생성한 다음 TB 의 SDRAM 으로 커널 포팅을 위해
HP 에서는 xinetd 데몬을 구동하고 tftpboot 디렉토리에 커널이미지를 올려 놓고 TB 에서는 tftp 부
트컴맨드를 사용해서 다운 받는다 . 이후 TB 에서 boot 라는 컴맨드를 사용하여 SDRAM 의 커널 영
역으로 실행 포인터를 넘겨줘서 linux 가 부팅되도록 한 후 성능 검증한다 . 성능 검증에 이상이 없으
면 TB 에서 flash 부트 컴맨드를 사용하여 SDRAM 에 있는 이전에 포팅된 커널을 flash ROM 에
fusing 한다 . Led device driver 가 참조하는 시스템 함수들은 패치된 리눅스 소스파일들이 되어야 하
지 않을까 ? (2) asm 이 아니라 asm.arm (3) Makefile 에서 include 디렉토리가 패치된 리눅스 소스
파일들이 있는 include 위치까지 해 줘야 ..
부트컴맨드 setip 를 사용해서 HP 및 TB 의 IP 를 먼저 설정한다 .
프로그램 위치 방화벽
시스템 관련은 iptables –F, setup 에서 해제할 수 있고 Selinux 는 X-
Minicom version ….
window 의 Selinux management 에서 default setting 을 disable 로 한
다 . 방화벽을 비활성화 시키고 해야 TB 와 HP 간에 이더넷 통신이 가 [XM_bulverde] setip 192.168.123.166 192.168.123.165
터미널 (1)
능하다 .
[root@localhost /]# cd work/led_driver XM Bulverde Linux Kernel

(1) [root@localhost led_driver]# ls ….

Makefile, ledioport.c, test.c [root@EMPOS ~]# cd ..


컴퓨터
[root@localhost led_driver]# make [root@EMPOS /]# tftp –r ledioport.ko -g 192.168.123.166

[root@localhost led_drivrer]# ls [root@EMPOS /]# tftp –r test -g 192.168.123.166

Makefile, ledioport.c ledioport.mod.o ledioport.ko ledioport.o test.c [root@EMPOS /]# insmod ledioport.ko
Root 폴더
test.o init module, ledioport major number : 252
[root@localhost led_driver]# cp ledioport.ko test tftpboot/. [root@EMPOS /]# mknod /dev/ledioport c 252 0
[root@localhost led_driver]# service xinetd restart /dev/ledioport
2GB 미디어
… [root@EMPOS /]# . /test
[root@localhost led_driver]# [root@EMPOS /]# rmmod ledioport

Insmod 명령어가 어떤 시스템 함수를 호출하고 ledioport.ko 를 참조해


서 led_init(void) 을 호출하고 그 안에서 register_chrdev( ) 시스템 함수
를 호출해서 inode 구조체의 inumber 253 를 얻는다 .

mknod 명령어를 사용하여 이 inumber 를 /dev/ledioport 라는 장치명 파


일로 등록해서 test 에서 접근할 수 있도록 한다 .

inode 는 리눅스 상에서 파일을 접근하기 위해 관련 정보를 기록한 구조체이고 이 안에 inumber 가 있다 .


이를 사용하여 파일에 대한 접근 ID 라고 볼 수 있다 . 이와 관련해서 링크 명령어가 있다 .
ln file1 file2 라고 하면 기존의 file1 이 새로운 file2 로 하드링크되는데 복사 (cp) 와는 달리 둘 중의 하나
의 파일이 변경되면 링크 걸린 나머지 파일도 덩달아 변경된다 . 가령 Object link embedded 와 같이 사
용자가 문서 작업에서 어떤 그림 파일을 가져와 삽입시키고 그 그림을 수정하면 그림 파일도 수정되는 식
이다 . Symbolic link 도 있는데 이것은 윈도우에서 아이콘과 같은 기능이다 .
LED driver
Ioremap, check_resion, request_region, printk,iounmap,
# led Device Driver Makefile release_region, get_user, register_chrdev, unregister_chrdev 함수들이 참
조하는 헤더 파일들은 ? 헤더파일들은 어디에 ? 아마도 TB 에 깔려 있는 리
눅스 OS 의 라이브러리
CC = arm-linux-gcc linux-2.6.12-xm_bulverde 는 이미 패치된 리눅스 소스 디랙토리로서 이 디
렉토리 밑에서 컴파일 한 후에 ledioport.c 가 참조하는 arm 디렉토리가 생
obj-m := ledioport.o 성되서 제대로 컴파일이 된다#. led Device Driver Makefile

KDIR := /work/linux-2.6.12-xm_bulverde
CC = arm-linux-gcc
PWD := $(shell pwd) warning Optimizatiom level 2 KDIR = /work/linux-2.6.12-xm_bulverde
C compiler optins CFLAGS = -D__KERNEL__ -DMODULE -Wall -O2 -I$(KDIR)
DRIVER_SRCS = ledioport.c
CFLAGS = -D__KERNEL__ -DMODULE -Wall -O2 -I$(KDIR)
DRIVER_OBJS = ledioport.o
TEST_TARGET = test
TEST_TARGET = test
TEST_OBJS = test.o
TEST_OBJS = test.o TB 에 깔려 있는 리눅스 OS 의
TEST_SRCS = test.c
TEST_SRCS = test.c 라이브러리를 – I option 을 써서
include 시킴
ledioport.o: ledioport.c
CC -c CFLAGS ledioport.c
default:$(TEST_TARGET)
test: test.o
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
CC -o test.o
$(CC) $(KDIR) -c $(TEST_SRCS)
test.o: test.c
$(CC) $(TEST_OBJS) -o $@
디렉토리 이동해서 CC -c test.c
거기서 make
clean:
rm -f *.ko
rm -f *.o
rm -f *.mod.*
rm -f .*.cmd
rm -f $(TEST_TARGET)
rm -f default
LED driver

• 한백 CD 에 있는 linux-2.6.12-xm_bulverde.tar.gz 를 복사해서 HP 의 /work 밑에 「 tar xvfz linux-


2.6.12-xm_bulverde.tar.gz 」로써 압축 해제하면 linux-2.6.12-xm_bulverde 디렉토리가 생성되고 그
밑에 패치된 2.6.12 버전의 리눅스 소스파일들이 있게 된다 . /work/linux-2.6.12-xm_bulverde 디렉토
리에서 Makefile 에 정의된 대로 「 make empos_xm_defconfig 」를 쳐서 설치 옵션을 설정하고 「
make zImage 」를 쳐서 컴파일을 실행하고 zImage 라는 최종 이미지를 생성한다 . 이와 같이 한 후
에 비로소 ledioport.c 역시 제대로 컴파일이 된다 .

• 앞서의 「 (2) asm 이 아니라 asm.arm 」 이라는 구절에서 컴파일 한 후에 ledioport.c 에서 참조하
는 arm 디렉토리가 생성되어 제대로 참조할 수 있음을 확인할 수 있다 .
Web server

• HP 에서 한백 CD 의 source/webserver 의 파일들을 크로스 컴파일해서 실행파일인 webs 를 TB 의


bin 아래에 두고 , web 아래에 html 파일을 둔다 .

• 소켓 프로그래밍

• C509 호의 내 연구실에는 IP 가 203.250.143.233 으로 잘 사용해 왔는데 어느 날 NIC 의 IP 를


C302 의 남는 IP 인 203.250.122.222 로 하면 않되는 까닭은 무얼까 ? 이 IP 들은 C 클래스 체계로
위 세 자리 당 하나의 네크워크를 구성하고 하나의 gateway 가 있다 . 그렇다면 각 층마다 다른
gateway switch 로 연결되어 있나 ?

• 내방 C509 에서 TB 에 direct UTP cable 을 연결하고 IP 를 “ ifconfig eth0 203.250.143.133 up” 으


로 해서 연결하면 C302 에서 203.250.133.xxx 컴퓨터의 웹브라우져에서
http://203.250.143.133/index.html 웹페이지를 보면 않 된다 . ping 을 사용해서 해보면 network 간에
통신이 이루어지지 않음을 알 수 있었다 . 왜 그렇지 ? TB 의 리눅스 상에서 gateway 를 설정하는 설
정 파일 /etc/sysconfig/ifc-eth0 가 없어서 거기서도 설정이 않 되고 다른 방법을 사용해서 설정할 필요
가 있다 . 만약 C302 층에 있는 같은 넷에 소속된 203.250.133.xxx IP 의 컴퓨터와 TB 를 거기서 남
는 203.250.133.xxx IP 로 설정하고 direct LAN port 에 연결하면 gateway 설정 없이도 정상적으로
보여질 것이다 .
Web server - Makefile

all: compile CFLAGS = -DWEBS -DUEMF -DOS="LINUX" -DLINUX


$(UMSW) $(DASW) $(SSLSW) $(IFMODSW)
CC = arm-linux-gcc OTHERS = -DB_STATS -DB_FILL -DDEBUG
AR = arm-linux-ar DEBUG = -g -Wall
ARCH = libwebs.a IFLAGS = -I..
NAME = webs LDFLAGS = $(SSLLIB) $(IFMODLIB)

# User Management switch compile: $(NAME)


UMSW = -DUSER_MANAGEMENT_SUPPORT
# Build archive of objects
# Digest Access switch
DASW = -DDIGEST_ACCESS_SUPPORT $(ARCH): $(DEPEND_FILES)
$(AR) $(ARFLAGS) $(ARCH) $?
# SSL switches (enable all to activate)
# SSLINC = /RSASSL/library/include # Primary link
# SSLLIB = /RSASSL/library/lib/libsslc.a
# SSLSW = -DWEBS_SSL_SUPPORT -I$(SSLINC) $(NAME): Makefile $(ARCH)
# SSLPATCHFILE = ../websSSL.o $(CC) -o $(NAME) $(DEBUG) (CFLAGS)
$(IFLAGS) \
# If-Modified-Support switches (requires math library, libm.a) main.o $(ARCH) $(LDFLAGS)
# IFMODSW = -DWEBS_IF_MODIFIED_SUPPORT
# IFMODLIB = /usr/lib/libm.a clean:
rm -f $(NAME) $(ARCH)
# Dependencies
DEPEND_FILES = ../asp.o ../balloc.o ../base64.o ../cgi.o
../default.o \
../ejlex.o ../ejparse.o ../form.o \
../h.o ../handler.o ../mime.o ../misc.o ../page.o \
../ringq.o ../rom.o \
../sock.o ../sockGen.o $(SSLPATCHFILE) \
../security.o ../sym.o ../uemf.o ../url.o ../value.o \
../md5c.o ../um.o ../umui.o ../websda.o ../emfdb.o \
../webrom.o ../webs.o ../websuemf.o main.o
Web server - Makefile
# Dependencies ../rom.o: ../rom.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h

../asp.o: ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h ../security.o: ../security.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h

../balloc.o: ../balloc.c ../uemf.h ../sock.o: ../sock.c ../uemf.h

../base64.o: ../base64.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h ../sockGen.o: ../sockGen.c ../uemf.h

../cgi.o: ../webs.h ../wsIntrn.h ../uemf.h ../sym.o: ../sym.c ../uemf.h

../default.o: ../default.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h ../uemf.o: ../uemf.c ../uemf.h

../ejlex.o: ../ejlex.c ../ej.h ../ejIntrn.h ../uemf.h ../um.o: ../webs.h ../wsIntrn.h ../um.h ../uemf.h

../ejparse.o: ../ejparse.c ../ej.h ../ejIntrn.h ../uemf.h ../umui.o: ../webs.h ../wsIntrn.h ../um.h ../uemf.h

../emfdb.o: ../emfdb.h ../wsIntrn.h ../uemf.h ../url.o: ../url.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h

../form.o: ../form.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h ../value.o: ../value.c ../uemf.h

../h.o: ../h.c ../uemf.h ../webrom.o: ../webrom.c ../webs.h ../wsIntrn.h ../uemf.h

../handler.o: ../handler.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h ../webs.o: ../webs.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h

../md5c.o: ../md5.h ../wsIntrn.h ../uemf.h ../websda.o: ../webs.h ../wsIntrn.h ../websda.h ../uemf.h

../mime.o: ../mime.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h ../websuemf.o: ../websuemf.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h

../misc.o: ../misc.c ../uemf.h ../websSSL.o: ../websSSL.c ../websSSL.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h

../page.o: ../page.c ../webs.h ../wsIntrn.h ../ej.h ../ejIntrn.h ../uemf.h main.o: main.c ../wsIntrn.h ../webs.h ../ej.h ../ejIntrn.h ../uemf.h

../ringq.o: ../ringq.c ../uemf.h


# Transition rules (add -o to put object in right directory)

.c.o:
$(CC) -c -o $@ $(DEBUG) $(CFLAGS) $(IFLAGS) $<
Web server – server program

#include "../uemf.h"
#include "../wsIntrn.h"
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#ifdef WEBS_SSL_SUPPORT
#include "../websSSL.h"
#endif

#ifdef USER_MANAGEMENT_SUPPORT
#include "../um.h"
void formDefineUserMgmt(void);
#endif

static char_t *rootWeb = T("web"); /* Root web directory */


static char_t *password = T(""); /* Security password */
static int port = 80; /* Server port */
static int retries = 5; /* Server port retries */
static int finished; /* Finished flag */

static int initWebs();


static int aspTest(int eid, webs_t wp, int argc, char_t **argv);
static void formTest(webs_t wp, char_t *path, char_t *query);
static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
int arg, char_t *url, char_t *path, char_t *query);
extern void defaultErrorHandler(int etype, char_t *msg);
extern void defaultTraceHandler(int level, char_t *buf);
#ifdef B_STATS
static void printMemStats(int handle, char_t *fmt, ...);
static void memLeaks();
#endif
Window XP IIS
• XP professional 는 IIS(Internet Information Service) 기능이 있는데 웹서버 , 메일서버 ( 송신
SMTP, 수신 POP 는 아님 ), FTP 서버를 구성할 수 있다 . 제어판 > 프로그램 추가 > window 구성
요소에서 IIS(http, smtp, ftp) 를 설치를 XP professional CD 로부터 설치한다 . 설치가 되면 관리
도구에서 실행 아이콘을 발견할 수 있다 . 여기서 마우스 오른쪽 빠른 메뉴에서 속성 ( 웹서버 , 메일 ,
ftp) 을 클릭해서 설정한다 .

• 웹서버설정 내용 : IP 와 포트 (http 의 경우 80, ftp 의 경우 21, telnet 23 번 ), 웹페이지가 있는 홈


디렉토리 C:\inetpub\wwwroot, 접근 보안 ( 호스트에 설정된 사용자들에 한 해서 사용자 이름 , 암
호를 통해 접근하게 할 수도 있음 ), 가상 디렉토리

• 컴퓨터 이름 , admin 계정 및 사용자 계정 , 작업그룹 , 도메인의 의미


• 홈페이지 작성은 저작도구를 사용해 frontpage, namoweb editor 등 , dynmic HTML(style
sheet), CGI, javascript

• 사설 IP 와 공인 IP : class A 10.0.0.0~10.255.255.255, class B 172.16.0.0~172.31.255.255,


class C 192.168.0.0~192.168.255.255 는 여러 기관에서 중복 사용가능하고 인터넷에 직접연결
이 않 되고 인터넷 공유기를 통해 접속 . 127.0.0.1 은 자신의 루프백 IP 이다 .

• 전용선과 인터넷회선 : 일반 가정에서는 통신사로부터 VDSL modem, cable modem 을 사용해 유


동 IP 로 인터넷에 접속하나 큰 회사는 ISP 로 부터 공급 받은 전용선을 통해 고정 IP 로 인터넷에 접
속한다 .

• ISP POP(point of presence) T1(1.544Mbps) 또는 E1(2.048Mbps) 로부터 기관의 종단 장치


(CSU 또는 DSU) 를 통해 신호를 재생시키고 router 를 통해 gateway switch
Windows 로서
XP 홈랜 네트워크
네트워크 간연
, 크라운 출판사ㅡ 이주경 지음
Window XP ICS (Internet Connection Sharing)
• 가정에서 XP professional 이 깔려 있는 호스트 컴퓨터에 한 NIC(network interface card) 는 인터
넷에 연결되고 다른 secondary NIC 에는 hub 를 통해서 여러 대의 client 컴퓨터들이 연결되어 있
다.

• XP 에서 “네트워크 연결”에서 primary ethernet 은 로컬영역연결 , secondary ethernet 은 로컬영


역연결 2 로 나타나고 로컬영역연결 2 를 클릭하여 고급 탭에서 “인터넷연결공유”에 체크한다 . 이
와 같이 하면 gateway 컴퓨터에 연결된 컴퓨터들이 인터넷에 접속하여 사용할 수 있다 .
XP 에서 ICS(internet connection
shareing) 기능이 설정된 컴퓨터 인터넷 ISP 로부터 부여 받은 고정 IP 로 설
정된 primary ethernet
또는 인터넷공유 S/W(Sygate,
wingate) 가 깔려 있는 host
computer
집 router)
또는 인터넷 공유기 (wireless Gateway 192.168.0.1 사설 IP 로 설정
server 된 secondary ethernet

192.168.0.2 사설 IP 로 설 client client client



192.168.0.4 사설 IP 로 설

Windows XP 홈랜 네트워크 , 크라운 출판사ㅡ 이주경 지음


Window XP ICS (Internet Connection Sharing)

로컬영역연결 2

인터넷 연결공유
Window XP shared folders in local network
• 교내 망에서 각 컴퓨터는 컴퓨터 이름 , 사용자 계정 , 그룹 및 그에 대한 권한이 설정되어 있다 . 각
로컬넷은 그림과 같이 C class 에서 위 세 자리가 하나의 로컬넷으로 구성되고 각 로컬넷은 라우터에
연결되어 인터넷 ISP 에 접속된다 . 로컬넷에 소속된 컴퓨터들은 “작업 그룹”을 조성해 가입할 수 있
다.

203.250.133.1
인터넷
gateway
203.250.133. 220 고정 IP

203.250.133. 222 고정
IP

client client client ISP

Gateway
switch(router) 203.250.143.1 gateway

LOCAL
NETWORK
C CLASS 255
COMPUTERS PER
LOCAL NET
203.250.143.231 고정 IP
client client client

203.250.143.233 고정
IP

Windows XP 홈랜 네트워크 , 크라운 출판사ㅡ 이주경 지음


Window XP shared folders in local network

• 내 컴퓨터에서 컴퓨터 이름 , 및 자신의 로컬넷의 작업 그


룹을 지정한다 .
Window XP shared folders in local network

• 사용자 계정을 만들고 Guest 계정을 허용한다 .


Window XP shared folders in local network

• “ 내 컴퓨터”의 오른쪽 마우스 빠른 메뉴에서 “관리”를


클릭하거나 제어판의 “관리도구”를 치면 사용자 및 그
룹에 대해 설정할 수 있다 .

• Administrators 그룹에 디폴트로 Administrator 와


User 계정이 등록되어 있다 . 마찬가지로 Guests 그
룹에도 Guest 계정이 등록되어 있다 . XP 에서 디폴트
로 되어 있는 사용자 권한이 이미 거기에 맞게 설정되어
있어서 사용자가 특별히 재설정할 필요는 없다 .
Window XP shared folders in local network
• “ 전체네트워크 >microsoft Windows Network“ 에서 자신이 소속된 로컬넷의 작업 그룹들을 볼 수
있고 자신이 소속된 작업 그룹에 들어가면 자신의 컴퓨터이름을 확인해 볼 수 있다 . 내 컴퓨터 이름
에 들어가서 공유 자료들을 볼 수 있다 .
Window XP shared folders in local network
• 또는 “네트워크 환경”에 들어 가면 연결된 컴퓨터 공유 폴더들이 나타난다 . 여기서 공유 폴더의 접근
은 로컬넷에 소속된 컴퓨터들에 한하는데 다른 로컬넷에 소속된 컴퓨터의 공유폴더를 액세스하려면 “
실행 >\\ 액세스하고자 하는 컴퓨터 ( 공유폴더 ) 이름”을 치면 접근할 수 있다 .
Window XP shared folders in local network

• 내 컴퓨터의 공유폴더에 대해 접근할 수 있는 사용자 이름들에 대해 설정할 수 있는데 그 사용자들도


자신의 컴퓨터에서 그 사용자 이름으로 로그온 되어 있어야 한다 . 패스워드는 양쪽의 경우 다 다를
수 있다 . 따라서 모든 사람들이 접근하도록 하려면 Guset 계정을 허용해 놓고 있어야 한다 .

• 로컬넷 간에 접근을 위해서 WINS 에 설정할 필요가 있음 .

인터넷

황윤희 정일정 김명희 ISP

작업그룹 CTL
Gateway wins
switch(router)
로컬넷 마다 거기에 소속
LOCAL
된 작업그룹들과 컴퓨터 NETWORK

이름들 . 각 컴퓨터에 설 작업그룹 MSHOME


컴퓨터이름
정된 사용자 계정들 iskim 하월수 문명숙
사용자 계정 : 사용자 계정 :
김익상 하월수
작업그룹
하월수 workgroup
Window XP shared folders in local network

• 모든 사람들에게 공유를 허용하려면 (1) Guest 계정을 허용하고 (2) wins 를 설정 (3) 폴더옵
션에서 “모든 사용자에게 동일한 폴더 공유 권한을 지정”에 언체크 하고 (4) 공유할 폴더의 사용
권한을 “ everyone” 사용자 그룹으로 설정

You might also like