반응형
반응형

lsof -i :8080

 

kill {PID}

반응형

'연구개발 > Etc..' 카테고리의 다른 글

[Docker] 생성 및 실행  (0) 2018.07.04
운영체제 개론  (0) 2017.05.29
지표 관련 용어  (0) 2016.08.22
unity key  (0) 2016.05.07
RAID 1+0 과 0+1의 차이점  (0) 2011.07.11
반응형


도커 명령어 익히기 ( + 우분투 설치 )


도커 명령어

옵션설명
-ddetached mode (백그라운드 모드)
-pHost와 컨테이너의 Port를 연결 (fowarding)
-vHost와 컨테이너의 Directory 연결 (마운트)
-e컨테이너 내에서 사용할 환경변수 설정
-it-i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션
--rm프로세스 종료시 컨테이너 자동 제거
--link컨테이너 연결[컨테이너명:별칭]
--name컨테이너 이름 설정



도커 실행중인지 확인 docker version

C:\Users\bactoria>docker version
Client:
 Version:       18.03.0-ce
 API version:   1.37
 Go version:    go1.9.4
 Git commit:    0520e24
 Built: Wed Mar 21 23:06:28 2018
 OS/Arch:       windows/amd64
 Experimental:  false
 Orchestrator:  swarm

Server:
 Engine:
  Version:      18.03.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   0520e24
  Built:        Wed Mar 21 23:14:32 2018
  OS/Arch:      linux/amd64
  Experimental: false

C:\Users\bactoria>



우분투 이미지 다운로드 docker pull ubuntu:16.04

C:\Users\bactoria>docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
22dc81ace0ea: Pull complete
1a8b3c87dba3: Pull complete
91390a1c435a: Pull complete
07844b14977e: Pull complete
b78396653dae: Pull complete
Digest: sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6
Status: Downloaded newer image for ubuntu:16.04

C:\Users\bactoria>



이미지 확인하기 docker images

C:\Users\bactoria>docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               f975c5035748        2 weeks ago         112MB

C:\Users\bactoria>



우분투 컨테이너 실행하기 docker run -it --name myUbuntu ubuntu:16.04 /bin/bash

C:\Users\bactoria>docker run -it --name myUbuntu ubuntu:16.04 /bin/bash
root@27db33196683:/#



리눅스 접속 확인하기 ls

root@27db33196683:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@27db33196683:/#



우분투 컨테이너 종료하기 exit

root@27db33196683:/# exit
exit

C:\Users\bactoria>



실행중인 컨테이너 확인하기 docker ps

C:\Users\bactoria>docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

C:\Users\bactoria>



모든 컨테이너 확인하기 docker ps -a

C:\Users\bactoria>docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
be76370e89aa        ubuntu:16.04        "/bin/bash"         45 seconds ago      Exited (0) 15 seconds ago                       myUbuntu

C:\Users\bactoria>



종료된 우분투 컨테이너 실행하기 docker start myUbuntu

C:\Users\bactoria>docker start myUbuntu
myUbuntu

C:\Users\bactoria>



우분투 컨테이너 접속하기 docker attach myUbuntu + Enter X2

C:\Users\bactoria>docker attach myUbuntu
root@be76370e89aa:/#
root@be76370e89aa:/#



우분투 컨테이너 빠져나가기 Ctrl+p + Ctrl+q
(컨테이너 종료하지 않음)

root@be76370e89aa:/#
root@be76370e89aa:/# read escape sequence

C:\Users\bactoria>



실행중인 모든 컨테이너 확인하기 docker ps

C:\Users\bactoria>docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
be76370e89aa        ubuntu:16.04        "/bin/bash"         5 minutes ago       Up 3 minutes                            myUbuntu

C:\Users\bactoria>



우분투 컨테이너 종료하기 docker stop myUbuntu

C:\Users\bactoria>docker stop myUbuntu
myUbuntu

C:\Users\bactoria>



이미지 제거하기 docker rmi ubuntu:16.04
(삭제안됨)

C:\Users\bactoria>docker rmi ubuntu:16.04
Error response from daemon: conflict: unable to remove repository reference "ubuntu:16.04" (must force) - container be76370e89aa is using its referenced image f975c5035748

C:\Users\bactoria>



컨테이너 제거하기 docker rm myUbuntu
(이미지 제거하려면 컨테이너 먼저 제거해야 함)

C:\Users\bactoria>docker rm myUbuntu
myUbuntu

C:\Users\bactoria>



컨테이너 제거 확인 docker ps -a
(삭제되어서 없어졌을거임)

C:\Users\bactoria>docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

C:\Users\bactoria>



이미지 보기 docker images

C:\Users\bactoria>docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               f975c5035748        2 weeks ago         112MB

C:\Users\bactoria>



이미지 삭제하기 docker rmi ubuntu:16.04

C:\Users\bactoria>docker rmi ubuntu:16.04
Untagged: ubuntu:16.04
Untagged: ubuntu@sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6
Deleted: sha256:f975c50357489439eb9145dbfa16bb7cd06c02c31aa4df45c77de4d2baa4e232
Deleted: sha256:0bd983fc698ee9453dd7d21f8572ea1016ec9255346ceabb0f9e173b4348644f
Deleted: sha256:08fe90e1a1644431accc00cc80f519f4628dbf06a653c76800b116d3333d2b6d
Deleted: sha256:5dc5eef2b94edd185b4d39586e7beb385a54b6bac05d165c9d47494492448235
Deleted: sha256:14a40a140881d18382e13b37588b3aa70097bb4f3fb44085bc95663bdc68fe20
Deleted: sha256:a94e0d5a7c404d0e6fa15d8cd4010e69663bd8813b5117fbad71365a73656df9

C:\Users\bactoria>



무에서 유를 창조하고

다시 무로 돌아갔다.

안보고 우분투 컨테이너 생성까지 가즈아~



Issues

  • 컨테이너 attach 안될때
    컨테이너 restart 하고나서 다시 attach 붙이자.
    ( attach 명령 후 엔터 한번 더눌러 줘야함. )


  • 도커이미지 갑자기 날라갈때
    이건 hyper에 vm이랑 관련된거같은데.. 자세히 몰겠음. 한번씩 맛탱이가 가던데


  • docker version에서 Server가 안뜰 때
    hyper-V 관리자를 열어 가상머신이 실행중인지 확인


반응형

'연구개발 > Etc..' 카테고리의 다른 글

mac port kill  (0) 2024.01.31
운영체제 개론  (0) 2017.05.29
지표 관련 용어  (0) 2016.08.22
unity key  (0) 2016.05.07
RAID 1+0 과 0+1의 차이점  (0) 2011.07.11
반응형

제1장 OS의 개요

1.1 OS의 개념 및 종류

1.1.1 운영체제의 개념

     (1) 정의 - 제한된 컴퓨터의 각종 자원을 효율적으로 관리, 운영함으로써 사용자에게 최대의 편리

                성을 제공하고자 하는 인간과 컴퓨터 사이의 인터페이스를 위한 시스템 소프트웨어

     (2) 역할 - 사용자와 컴퓨터 시스템간의 인터페이스 정의

              - 사용자들간의 하드웨어의 공동사용         - 여러 사용자간의 자원 공유    

              - 자원의 효과적인 운영을 위한 스케쥴링     - 입출력에 대한 보조 역할      

              - 에러에 대한 처리                         - 사용자들간의 간섭 방지

              - 자원의 사용량 계산                       - 병렬 수행을 위한 편의 제공

              - 데이터에 대한 보안과 신속한 사용         - 통신 네트워크 관리

     (3) 목적

        1) 사용의 편리성 - 사용자로 하여금 컴퓨터의 하드웨어와 각종 정보를 효율적으로 관리하여 

                           컴퓨터를 보다 편리하게 사용할 수 있도록 제공

        2) 시스템 성능의 향상 - 성능의 최대 발휘를 목적으로 하며 다음의 기준으로 판단

           ① 처리능력(throughput) - 일정 단위 시간 동안 컴퓨터가 처리하는 작업의 양

           ② 응답시간(turn around time) - 한 작업을 처리할 때 입력으로부터 결과가 출력될 때까지

                                           의 경과 시간

           ③ 사용의 용이성(availability) - 사용자가 필요로하는 컴퓨터를 적절한 때에 얼마나 빨리 

                                          사용할 수 있도록 할 것인가

           ④ 신뢰도(reliability) - 컴퓨터가 올바로 작동되는가

     (4) 구성

        1) 제어 프로그램(control program)

           ① 감시 프로그램(supervisor program)

           ② 데이터 관리 프로그램(data management program)

           ③ 작업 제어 프로그램(job control program)

        2) 처리 프로그램(processing program)

           ① 언어 번역 프로그램(language translator program)

           ② 서비스 프로그램(service program)

           ③ 문제 프로그램(problem program)

     (5) 운영체제의 구조

        - 커널 : 인터럽트처리기, 디스패쳐, 프로세서 동기를 위한 기능 지원, H/W와 밀접하게 관련

        - 기억장치 관리기       - 입출력 시스템        - 파일 관리기

        - 단기 스케줄러 : 시스템 내 활성 큐 관리, CPU 관리, H/W와 무관

        - 자원관리기 : CPU를 제외한 다른 자원들을 관리

        - 장기 스케줄러 : 프로세서의 생성, 소멸, 제어를 담당

        - 명령어 해석기 : 사용자와 직접 대화, Shell 이라 부름


1.1.2 OS의 종류

     (1) 운영체제의 등장

         1) 1950년대 초 general motors사에서 IBM 701을 위한 최초의 운영체제를 개발하였으며 그 전에는 

            운영체제의 할 일이 사람에 의해서 직접 처리되었다.

         2) 특징(1950년대) - 일괄처리 시스템의 시작

                          - 작업제어 언어의 등장

     (2) 초기 운영체제 시스템

         - 한번에 하나의 작업만 수행하며 준비시간이 많이 걸린다

         - 장치 구동기 사용

     (3) 일괄처리 시스템(batch processing system)

         1) 1950년대 초기의 컴퓨터 처리방법 중 하나로 처리할 데이터를 일정량을 모아 한꺼번에 처리 

         2) 상주모니터(resident monitor) - 사용자가 한번에 한 작업씩 수행하던 것을 한 개의 batch로 묶어 

                                          자동 처리되게 한 OS

             * 상주모니터 구성요소

                - 인터럽트와 트랩 벡터, 장치 구동기, 작업의 순서화(대기 작업들), 제어카드 해석기

         3) 장점 - 시스템의 사용계획을 구체적으로 세워 능률적으로 사용할 수 있다

         4) 단점 - 반환시간이 늦고 프로그램의 오류수정 작업이 어려우며 CPU가 유휴상태로 되기 쉽다

             * 단점 보완 방법

               - 상주모니터, 오프라인 연산, 버퍼링, 스풀링

     (4) 다중 프로그래밍 시스템(multi programming system)

         - 하나의 중앙처리장치에 여러 개의 프로그램을 실행시킴으로써 짧은 시간에 많은 작업을 수행할 

           수 있게 하여 시스템의 효율을 높여 주는 것

         1) 고려사항 - CPU스케줄링, 기억장치관리기법, 장치스케줄링, 교착상태, 병행제어 및 보호문제

         2) 장점 - 다중 작업을 구현하므로 시스템의 효율이 높다

         3) 단점 - CPU의 유휴 시간이 길어진다

                 - 기억장치 관리 기법, CPU 스케쥴링 기법이 필요

     (5) 다중 처리 시스템(multi processing system) 기출96

         - 하나의 공용 기억장치를 통하여 두 개 이상의 프로세서를 제어하는 시스템

         - 공유된 주기억장치의 사용을 스케줄링 하는데 어려움이 존재

         1) 장점 - CPU를 여러 개 사용하여 작업속도와 신뢰성을 높일 수 있다

     (6) 시분할 시스템(time sharing system)

         - 한 대의 컴퓨터로 일정한 시간 내에 여러 가지 작업을 처리하는 방법

         1) 장점 - 여러 사람이 공동으로 CPU를 사용하며 여러 개의 프로그램을 기억장치에 적재

         2) 단점 - 운영체제를 복잡하게 한다

     (7) 실시간 시스템(real time system)

         - 처리 대상 데이터가 발생하는 즉시 처리하여 결과를 산출하는 방식

         1) 장점 - 사용자의 노력이 절감되고 처리시간이 단축되며 처리비용이 절감

         2) 단점 - 입출력 자료의 일시저장 및 대기가 필요하고 특정상태의 재현이 불가능

                 - 시스템에 장애가 발생할 때 단순한 재실행이 불가능

     (8) 분산처리 시스템(distributed processing system)

         - 지역적으로 분산되어 있는 여러 대의 컴퓨터가 프로세서 사이의 특별한 데이터 링크를 통해 교신

           하면서 한 조직 내의 동일한 업무를 수행하고 정보 교환을 위해 네트워크로 상호 결합된 시스템

         - 특징 : 자원공유, 신뢰성, 계산속도 증가, 통신


1.1.3 운영체제 관점

 * 운영체제에 대한 사용자의 관점은 시스템 프로그램 특히 명령어 해석기에 의해 결정

     (1) 프로세스 관점

         1) 운영체제를 프로세스의 상태를 변화시키는 프로그램의 일종으로 보는 관점

         2) 중앙처리장치는 한 시점에서 하나의 작업만 수행하므로 각 프로세스의 상태를 변화시켜야 한다

     (2) 자원 관리자 관점

         - 운영체제를 시스템 자원들을 관리하기 위해 설계된 프로그램의 집단이라고 보는 관점

         1) 프로세스 관리 기능 - 어느 작업에게 CPU를 할당할 것인가를 결정

         2) 기억장치 관리 기능 - 어느 프로세스에게 기억장치를 할당할 것인가를 결정

         3) 장치관리 기능 - 장치를 할당하는데 어떤 방법이 효율적인지를 결정

         4) 정보관리 기능 - 어느 작업에게 어떤 자원을 사용하도록 할 것인지를 결정

     (3) 계층구조 관점

         1) 계층 1 - 프로세서 관리

            : 동기화 및 프로세서의 스케쥴링을 위한 프로세서 관리를 담당

         2) 계층 2 - 기억장치 관리

            : 기억공간의 할당 및 회수 기능을 실행하는 기억장치 관리를 담당

         3) 계층 3 - 프로세스 관리

            : 프로세스의 생성, 제거, 프로세스간 메시지전달, 프로세스의 시작과 정지 담당

         4) 계층 4 - 주변장치 관리

            : 주변장치의 상태파악 및 입출력 장치의 스케쥴링을 하고 입출력에 대한 전반 사항 지시

         5) 계층 5 - 파일 및 데이터 관리

            : 파일 생성과 소멸, 파일 오픈과 닫기, 파일의 유지 및 관리 등을 담당

     (4) 하드웨어 확장 관점 - 운영체제를 하드웨어의 기능 확대라는 측면에서 보는 관점

     (5) 기능적 관점 - 운영체제를 시스템 구성원 중의 일부로 보는 관점

     (6) 작업제어 언어 관점


1.2 System Software의 종류

1.2.1 System Software의 개념

     (1) 정의 - 특정한 문제를 해결하기 위한 알고리즘을 하드웨어에 정의해 주는 명령문과 데이터를 가진 

                프로그램으로 구성

     (2) 특징 - 컴퓨터의 작동, 수행에 있어서 기본이 되며 하드웨어 환경을 직접 제어

              - 컴퓨터 제조회사나 시스템 프로그래머에 의해 작성


1.2.2 System Software의 종류

     (1) 매크로(macro) - 프로그램에서 동일한 코드가 반복되어 나타나는 경우 이를 매번 나열하기 보다

                         하나의 간단한 코드로 정의하여 사용하는 기법

     (2) 링커(linker)

         - 목적프로그램 안에서 다른 목적프로그램을 호출하거나 여러 목적 프로그램들이 하나의 데이터를 

           공동으로 이용할 수 있도록 각 모듈간의 호출 및 공동 데이터의 이용을 가능하게 해주는 시스템 

           프로그램

     (3) 로더(loader)

        1) 절대로더(absolute loader) - 기계어 코드 프로그램에서 미리 지정한 번지에 프로그램과 데이터를 

                                      로드 한다

        2) 상대로더(relocating loader) - 로드 과정에서 메모리의 적당한 영역을 찾아 로드


2장 프로세스 관리

2.1 프로세스의 개념

2.1.1 프로세스 기출95

     (1) 개요 - 시스템에서 진행 중에 있는 모든 활동을 의미

     (2) 정의 - 현재 실행중이거나 곧 실행이 가능한 PCB를 가진 프로그램

              - 비동기적 행위, 순차적 실행, 능동적 개체, 수행중의 작업

              - 목적 또는 결과에 따라 발생되는 사건들의 과정

              - 지정된 결과를 얻기 위한 일련의 계통적 동작

              - 프로세스가 할당하는 개체로서 디스패치가 가능한 단위


2.1.2 순차 프로세스   - 의미 : 현재 실행중인 프로세스


2.1.3 프로세스의 상태

     (1) 프로세스 상태도

          보류(pending) → 준비(ready) ← 대기(blocked)

                                ↓↑      ↑

                                실행(running)

                                     ↓

                                완료(terminate)

     (2) 프로세스 상태

         1) 보류상태(pending) - 작업이 제출되어 스풀공간인 디스크에 수록되어 있는 상태

         2) 준비상태(ready)

            - CPU를 할당받을 수 있는 상태로서 CPU가 프로세스 자신을 처리해 주기를 기다리고 있는 것

         3) 실행상태(running)

             - 프로세스가 CPU를 차지하고 있는 상태로서 CPU에 의해 프로세스를 수행하고 있는 것

             - 부모 프로세스는 모든 자식 프로세스들이 종료될 때까지 기다린다

         4) 대기상태(blocked)

             - 프로세스가 CPU를 차지하고 실행되다가 입출력 처리와 같은 사건이 발생하게 되면 CPU를 

               양도하고 입출력 처리가 완료될 때까지 대기 큐에서 대기하고 있는 상태

         5) 완료상태(terminated)

             - 프로세스가 CPU를 할당받아 주어진 시간 내에 수행을 종료한 상태

             - 문장이 실행을 마쳤을 때 부모 프로세스에게 실행 결과를 돌려준다

     (3) 프로세스의 상태 전환 기출94

         1) 준비상태 -> 실행상태 : dispatch

            - 준비 상태의 프로세스들 중에서 우선순위가 가장 높은 프로세스를 선정하여 CPU를 할당함으

              로써 실행상태로 전환

         2) 실행상태 -> 준비상태 : time runout(할당시간 초과)

            - CPU의 지정된 할당 시간을 모두 사용한 프로세스는 다른 프로세스를 위해 다시 준비 상태로 

              되돌아간다

         3) 실행상태 -> 대기상태 : block

            - 실행중인 프로세스가 입출력 명령을 만나면 인터럽트가 발생하여 입출력 전용 프로세서에게 

              CPU를 양도하고 자신은 대기 상태로 전환 

         4) 대기상태 -> 준비상태 : wake up

            - 입출력 완료를 기다리다 입출력 완료 신호가 들어오면 대기중인 프로세스는 준비 상태로 전환


2.1.4 프로세스 제어블록(PCB)

     - 운영체제에 프로세스에 대한 중요한 정보를 제공해 주는 자료구조 테이블

     (1) PCB 수록 내용 기출94 기출96

         1) 프로세스 상태 - 보류, 실행, 준비, 대기, 정지 등의 상태

         2) 프로세스 번호 - 프로세스의 고유 번호

         3) 프로그램 카운터 - 프로세스가 다음에 실행할 명령어의 주소

         4) 레지스터 - 누산기, 인덱스레지스터, 스택 레지스터 등 범용레지스터와 상태코드 정보

         5) 기억장치 관리정보 - 경계 레지스터나 페이지 테이블들을 포함

         6) 계정 정보(회계정보) - CPU가 사용된 시간량, 시간의 범위, 계정번호, 작업 또는 레지스터 번호

         7) 입출력 상태 정보 - 입출력 요구들, 입출력 장치들과 개방된 파일 목록등

     (2) PCB의 관리

       - 프로세스 생성시에 만들어지며 모든 프로세스는 각각 고유한 PCB를 가지게 되고 수행이 완료된 

         프로세스인 경우에는 해당 PCB도 함께 삭제된다


2.1.5 프로세스 스케줄러의 종류 기출96

     (1) 장기 스케줄러(작업 스케쥴러)

         - 모든 job의 상태 파악, 다음에 수행될 job 선택, 시스템 자원 분배

         - 디스크 공간에 제출된 프로세스들을 선택하여 주기억 장치로 적재

         - 실행 간격이 비교적 크기 때문에 다음에 실행할 적절한 프로세스를 선택하는 시간을 더 사용해도 

           된다, 처리될 작업 결정, 다중 프로그래밍의 정도를 결정

     (2) 단기 스케쥴러(CPU스케쥴러)

         - 실행 준비가 되어있는 프로세스들 중에서 한 프로세스를 선택하여 CPU를 할당

         - 프로세스들간에 CPU를 자주 선택하기 때문에 수행 빈도수가 많고 각 프로세스의 CPU 할당 시간

           을 적게 한다면 더욱 자주 수행될 것이다, 주기억장치 내 작업들 중 실행작업 선택

     (3) 중기 스케쥴러

         - 기억장치에서 CPU를 경쟁하는 프로세스들의 수를 줄여서 다중 프로그래밍의 정도를 완화하는 것


2.1.6 프로세스의 종류

     (1) 독립적 프로세스(independent process)

         - 한 프로세스가 실행되면 다른 프로세스에 영향을 주거나 받지 않는 프로세스

         1) 프로세스가 독립적이므로 타 프로세스에 의한 공유가 없다

         2) 동일 입력은 동일한 결과를 갖는다

         3) 실행결과는 입력에 의해서만 결정된다

         4) 안정적으로 중단, 재실행될 수 있다

     (2) 유기적 프로세스(cooperating process)

         - 다른 프로세스와 데이터를 공유함으로써 영향을 주고받는 프로세스를 말한다

         1) 프로세스를 공유한다

         2) 실행결과는 입력뿐 아니라 상대적 실행순서에 의존한다

         3) 동일한 입력이라도 실행결과는 매번 다를 수 있다


2.2 병행 프로세스

2.2.1 병행 프로세스의 개요

  - 의미 : PCB를 가진 두 개 이상의 프로그램이 각각의 프로세스를 형성하여 동시에 수행


2.2.2 병행 프로세스에서 사용되는 주요 개념

     (1) 경쟁조건(race condition)

         - 공유메모리 : 함께 동작하는 프로세스들은 종종 메모리를 공유함

         - 경쟁 조건 : 2개 이상의 프로세스들이 공유 메모리에 읽기/쓰기를 하고, 그 결과가 어떤 프로세스

                       에 언제 실행되느냐에 따라 달라질 수 있는 상황

     (2) 상호배제(mutual exclusion)

         - 경쟁조건을 피하기 위한 방법

         - 상호배제 : 한 프로세스가 공유 메모리 혹은 공유 파일을 사용하고 있을 때 다른 프로세스들이 

                      사용하지 못하도록 배제시키는 제어기법 

                   or 두 프로세스가 하나의 자원을 동시에 점유할 수 없도록 조절하여 순차적으로 사용할 

                      수 있도록 하는 것(=상호보완)

     (3) 임계영역(critical section) 기출94

         - 임계영역 : 공유 메모리가 참조되는 프로그램의 부분

              or 두 프로세스가 한 버퍼에 있는 데이터를 동시에 접근하여 읽기/쓰기를 하고자 할 때의 버퍼 

         - 시간 종속 오류를 다루는 최초의 고급 수준 언어구조

           * 시간 종속 오류 : 프로세스들이 임의적으로 변수들을 공유할 때, 특정 순서로 실행될 때 발생

         - 임계영역 문제

            : 프로세스들이 서로 유기적으로 사용해야 하는 프로토콜을 설계

            : 각 프로세스는 그 임계구역에 들어갈 수 있는지의 여부를 미리 요청

            : 해결 ; 동기화 장치 또는 세마포어

         - 수행 순서를 잘 조절하여 2개 이상의 프로세스가 동시에 임계영역에 들어가지 않도록 한다면 

           경쟁 조건을 피할 수 있다

         - 상호배제를 위한 4가지 요구조건

           ① 상호배제조건 : 두개 이상의 프로세스들이 동시에 임계영역에 있어서는 안됨

           ② 진행조건 : 임계구역 바깥에 있는 프로세스가 다른 프로세스의 임계구역 진입을 막아서는 안됨

           ③ 한계대기조건 : 어떤 프로세스도 임계구역으로 들어가는 것이 무한정 연기되어서는 안됨

           ④ 프로세스들의 상대적인 속도에 대해서는 어떠한 가정도 하지 않는다


2.2.3 병행 프로세스의 문제점

     (1) 동기화(synchronization)

         - 두 프로세스가 한 기능을 사용할 때 상호배제가 이루어지도록 공동 협력하여 사용하는 것

     (2) 결과의 동일성 문제(determinancy)

         - 여러 프로세스가 동시에 수행될 때 각 프로세스의 수행결과는 수행순서와 시간에 관계없이 항상

           같아야 함

     (3) 의사소통 문제(communication)

         - 프로세스 사이의 데이터 교환에 관한 문제로서 일반적으로 메시지 전달 방법을 이용하여 데이터

           의 송수신을 확인

     (4) 외부 스케줄(explicit schedule)

         - 외부에서 프로그래머가 프로그램의 개발, 운영체제의 개발을 통하여 직접 해결할 수 있도록 하는 

           문제

     (5) 교착상태 문제(dead lock)

         - 상호배제와 동기화문제를 해결하지 못하여 프로세스들이 아무런 작업도 수행할 수 없도록 되는 

           문제

     (6) 동시처리 문제(concurrent processing)

         - 프로그래머가 직접 언어를 통하여 병행처리가 가능하도록 프로그래밍하는 것


2.2.4 세마포어(semaphore)

     (1) 세마포어의 개요 기출95 기출96

         1) 세마포어란 ?

            - 복잡한 문제에 있어서 상호배제를 해결하기 위한 동기화 도구

            - 신호기라는 뜻으로 각 프로세서에 제어신호를 전달하여 순차적으로 진행하기 위한 동기화구현

            - Dijkstra-데커의 알고리즘을 n개의 프로세스로 확장하여 상호배제 문제를 소프트웨어로 해결

         2) 세마포어의 사용

            - n개의 프로세스 임계구역 문제를 다루는데 사용

            - 여러 가지 동기화 문제를 해결하는데 사용

     (2) 표준연산

         - 세마포어 S는 표준단위연산 P(wait)와 V(signal)에 의해서만 접근 가능한 변수

         1) P(wait) 연산 : 프로세스를 대기상태로 전환하는 wait 연산을 수행

            # s.wait():

                 if (s.value > 0)  s.value--;

                 else 현재의 프로세스를 s.list에서 기다린다

         2) V(signal) 연산 : 프로세스에게 wake up 신호를 전달하는 signal 연산을 수행

            # s.signal():

                 if (1개 이상의 프로세스가 s에서 대기중이면)  그 중 1개 프로세스 수행

                 else s.value++;

         3) wait와 signal 연산이 세마포어 변수를 수정하는 것은 개별적으로 수행되므로 한 프로세스가 

            세마포어 변수 s를 수정 하면 다른 프로세스는 동일 변수 s에 대해 수정할 수 없다

     (3) 세마포어 응용

         1) 세마포어를 이용한 상호배제의 구현

            - 단지 세마포어 변수의 값을 1로 주고 임계영역에 들어가기 전에 wait를, 나올 때 signal을 호출

              하기만 하면 된다

         2) 세마포어를 이용한 동기화

            - block/wakeup 프로토콜 : 한 프로세스가 입출력을 요구하면 입출력이 끝날 때까지 그

              프로세스는 블록 상태가 되는데 이때 다른 프로세스는 이 블록된 프로세스를 깨워 줌

         3) 세마포어를 이용한 생산자 소비자 문제

            - 생산자는 소비자의 버퍼가 비었는지를 기다리고 소비자는 생산자의 버퍼가 채워졌는지를 

              기다림


2.2.5 모니터(monitor)

     - 상호배제에 대한 문제를 확실히 해결하여 여러 프로세스들이 자원을 안전하고 효과적으로 공유 할 수 

       있도록 한 기법

     (1) 목적 : 동기화를 자동적으로 제공하기 위함

     (2) 특징

         1) 모니터는 상호배제를 엄격하게 실시되어 한 순간에 하나의 프로세스만 모니터 내에서 수행

         2) 순차적으로만 사용할 수 있는 공유자원을 할당하는데 사용된다

         3) 데이터, 프로시저를 포함하는 병행성 구조

         4) 정보의 은폐(information hiding) 기법 - 모니터내부의 변수는 모니터 내부에서만 접근가능

         5) 모니터는 프로세스들이 추상 자료형을 안전하고 효과적으로 공유할 수 있게 함 


2.2.6 프로세스간 통신

     (1) 통신기법 기출94 기출95

         1) 공유 기억장치 기법(shared memory)

            - 통신하는 프로세스간에 기억장치 공간의 일부를 공유하도록 한다.

            - 통신 제공의 책임은 프로그래머에게 달려 있고, 운영체제는 단지 공유 기억장소만 제공

         2) 메시지 시스템 방법

            - 프로세스가 공유 변수에 의존하지 않고도 메시지를 이용하여 서로 통신할 수 있다.

            - 메시지를 관리, 전달하는 책임은 운영체제에 있다.

            - 일반적으로 send 와 receive 두 개의 연산을 제공한다.

            - 발생 가능한 예외적 상황 : 프로세스 종료, 메시지 상실, 메시지 혼합

            - 프로세스에 의해 보내지는 메시지 형태 : 고정크기, 가변크기, 타입을 가진 메시지

     (2) 명명(naming)

         1) 직접 통신 링크

            - 메시지를 주고받기를 원하는 프로세스가 수신자나 송신자의 이름을 명시적으로 표현해야 함

            - 통신을 원하는 프로세스 쌍 사이에는 자동으로 링크가 설정됨

            - 프로세스는 통신하는 상대 프로세스의 고유 이름만 알면 된다.

            - 링크는 두 프로세스와 관계하고 양방향성이다.

            - 어드레싱면에서 대칭적이고 일대일 통신이다.

            - 안정성과 신뢰성이 높다.

         2) 간접 통신 링크

            - 우편함을 통하여 메시지를 주고받을 수 있다.

            - 각 우편함은 메시지를 구별할 수 있는 유일한 이름을 갖는다.

            - 두 개의 프로세스는 공유 우편함을 갖고 있을 때에만 링크가 성립하여 통신이 가능하다.

            - 각 프로세스 쌍 사이에, 하나의 우편함에 관계되는 여러 개의 서로 다른 링크가 있을 수 있다.

            - 링크는 단방향 또는 양방향일 수 있다.


2.3 교착상태(Deadlock)

2.3.1 교착상태의 개요 기출95

     (1) 정의 

         1) 하나 또는 둘 이상의 프로세스가 더 이상 계속할 수 없는 어떤 특정 사건(자원의 할당과 해제)을 

            기다리고 있는 상태

         2) 둘 이상의 서로 다른 프로세스가 요구한 자원을 할당받아 점유하고 있으면서 상호간에 상대방 

            프로세스가 가지고 있는 자원을 요구하는 경우

     (2) 발생 예

         - 프로세스 1은 자원 1을 가지고 있으면서 자원 2를 요구하고, 프로세스 2는 자원 2를 가지고

           있으면서 자원 1을 요구하는 상태

     (3) 스풀링 시스템에서 교착상태

         1) 현재 수행중인 여러 작업이 인쇄할 행을 만들어 스풀링 파일로 보내고 있는 도중 이미 스풀링 

            파일 공간이 차버린 경우

         2) 교착상태 해결방법

            - 예상 필요 공간보다 많은 스풀링 파일 공간을 할당

            - 스풀링 파일이 일정한 포화 임계치를 넘지 못하도록 억제

     (4) 무한연기(infinite postpoment)

         1) 정의 - 여러 다른 프로세스들이 시스템에서 스케쥴링되어 처리되는 동안 한 특정 프로세스의

                   스케쥴링이 무기한으로 연기될 수 잇는 현상

         2) 발생원인 - 시스템(운영체제)의 편중된 자원 할당 정책 때문

         3) 노화(aging) 기법 - 프로세스가 자원을 기다리고 있는 시간에 비례하여 우선순위를 부여 기출95

  * 기아상태(starvation)

     - 자원 선점을 이용하여 교착상태를 제거하는데 있어서 희생자 선택을 할 때 동일한 프로세스가 매번

       선택되어 지정된 작업을 결코 완료할 수 없는 경우.


    # 무한연기와 교착상태의 비교

      

     (5) 자원의 종류

         1) 선점형 자원(preemptive resource)

            - 자원이 어떤 프로세스에게 할당되면 도중에 빼앗기는 경우

            - CPU나 주기억 장치

         2) 비선점형 자원(non-preemptive resource)

            - 일단 그 자원이 어떤 프로세스에게 할당되면 도중에 빼앗기지 않는 경우

            - 디스크, 테이프

         3) 전용 자원

            - 디스크나 테이프 같이 특정의 한 프로세스가 독점하여 사용하는 자원

         4) 공용 자원

            - 주기억장치, CPU같이 다수의 프로세스들 사이에서 공동으로 사용되는 자원

         5) 재사용(reusable) 자원

            - 전체 총량이 고정되고 부수적인 자원들이 생성되거나 파괴되지 않는 경우

         6) 소비(consumable) 자원

            - 전체 용량이 고정되지 않고 부수적인 자원들이 생성되거나 파괴되는 경우

     (6) 시스템 모델

         - 프로세스의 자원 사용 순서

         1) 자원요구(resource request)

            - 한 프로세스가 자원을 요구할 때 다른 프로세스가 이미 그 자원을 사용중이면 할당받을 수 

              없으므로 자원을 요구한 프로세스는 그 자원을 사용할 수 있을 때까지 기다린다

         2) 자원할당(resource allocation)

            - 프로세스는 운영체제로부터 자원을 할당받아 그 자원을 사용하여 수행을 계속한다

         3) 자원해제(resource release)

            - 프로세스는 이전의 자원요구에 의해 할당받았던 자원을 사용 후에는 운영체제에게 반납한다


2.3.2 교착상태 발생의 4가지 필요조건

     (1) 상호배제(mutual exclusion) 조건

         - 프로세스가 사용중이면 다른 프로세스는 반드시 기다려야 한다. 프린터

         - 프로세스들이 자원을 배타적으로 점유하고 있어서 다른 프로세스들이 그 자원을 사용할 수 

           없도록 만든다.

     (2) 점유와 대기(block and wait) 조건 : 부분할당

         - 프로세스들은 동일한 자원이나 다른 종류의 자원을 부가적으로 요구하면서 이미 어떤 자원을

           점유하고 있다

         - 대기조건

            : 프로세스가 자원을 요청할 때 그 프로세스는 어떠한 자원도 할당받지 않은 상태여야 한다.

     (3) 비선점(non-preemption) 조건

         - 자원은 사용이 끝날 때까지 이들을 갖고 있는 프로세스로부터 제거될 수 없다.

         - 자원들은 그들을 점유하고 있는 프로세스로부터 벗어나지 못하고 단지 프로세스들 자신이 

           점유한 자원을 해제할 수 있다

     (4) 환형대기(circular wait) 조건

         - 프로세스와 자원들이 원형을 이루며 각 프로세스는 자신에게 할당된 자원을 가지면서 상대방의

           자원을 상호 요청하는 경우


2.3.3 교착상태의 연구분야

     (1) 교착상태의 예방(deadlock prevention)

         - 교착상태의 발생 가능성을 사전에 모두 제거하도록 시스템을 조절

         - 가장 명료한 해결책으로 널리 사용됨

         - 자원의 비효율적인 이용결과를 낳을 수 있음

         - 교착상태 발생 필요조건의 네 가지 중 하나를 부정함으로써 수행 됨

     (2) 교착상태의 회피(deadlock avoidance) 기출94

         - 교착상태 발생 가능성을 인정하고 교착상태가 발생하려고 할 때 이를 적절히 피해가는 방법

         - 예방보다는 좀더 덜 엄격한 조건을 요구

     (3) 교착상태의 발견(deadlock detection) 기출95

         - 불안정 상태가 만들어졌을 때 검출 알고리즘 실행

         - 원하는 것이든지 아니든지 교착상태가 발생하도록 허용하여 교착상태가 일어났는지를 판단하고

           교착상태에 관련된 프로세스와 자원을 조사하여 결정해 내는 방법

         - 프로세스와 자원을 결정해 내면 교착상태를 시스템으로부터 제거할 수 있다

     (4) 교착상태의 회복(recovery from deadlock)

         - 시스템으로부터 교착상태를 제거하여 이후로는 시스템이 교착상태에 빠지지 않고 잘 진행되게 함

         - 교착상태에 빠진 프로세스가 완료되고 그 프로세스에 할당된 자원을 회수할 수 있도록 한다

         - 교착상태 발생 확률이 작거나 회복비용이 적게 소요되는 컴퓨터 시스템에서 사용할 때 유리


2.3.4 교착상태의 해결방안

     (1) 교착상태의 예방

         - 사전에 교착상태의 발생 가능성을 없애는 것(교착상태 발생요건중 1개만 부정)

         - 자원의 낭비가 따른다

         1) 점유와 대기조건의 부정

            - 프로세스는 필요한 모든 자원을 한꺼번에 요청하고, 시스템은 요청된 자원들을 전부 할당하든

              지 전혀 할당하지 않든지 하는 방식

            - 장점 : 프로세스들이 자원을 기다리는 동안은 아무 자원도 점유하지 않으므로 점유와 대기조건

                     이 부정되며 교착상태도 발생하지 않는다

            - 단점 : 자원 낭비와 비용 증가, 자원공유 불가능, 무한 연기 발생 가능

         2) 비선점 조건의 부정

            - 어떤 자원을 가지고 있는 프로세스가 더 이상 자원 할당 요구가 없으면 가지고 있던 자원을

              반납하고, 필요시 다시 자원을 요구하는 방법

            - 문제점 : 비용증가, 무한연기 발생가능(시간낭비)

         3) 환형대기 조건의 부정

            - 모든 프로세스에게 각 자원의 유형별로 할당순서(고유번호)를 부여하는 방법

            - 문제점 : 새로운 자원 추가 시 재구성 해야함

         4) 상호배제 조건 부정

            - 공유할 수 없는 자원을 사용할 때 성립

     (2) 교착상태의 회피

         - 시스템의 운영중 상황을 보아가면서 교착 상태 가능성을 피해 가는 것

         1) 안전 상태와 불안전 상태

            - 안전상태 : 시스템이 특정 순서대로 각 프로세스에게 자원을 할당할 수 있고 교착상태를 

                         방지하여 모든 작업이 완료될 수 있는 상태

            - 불안전 상태 : 교착상태가 발생할 수 있는 상태

         2) 은행가(banker) 알고리즘

            - 알고리즘 구현을 위한 기본 자료구조

              * n : 시스템의 프로세스 수  m : 자원 형태(종류)의 수

              ① Available : 각 자원의 형태별로 사용가능한 자원의 수를 표시하는 길이가 m인 벡터

                            Available[j] = k라면, 자원형태 Rj인 자원이 k개가 남아 있다

                            (사용 가능하다)는 의미(잔여량)

              ② Max : 각 프로세스의 최대 자원의 요구를 정의하는 n×m 행렬 Max[i,j] = k라면

                        프로세스 Pi는 자원 형태가 Rj인 자원을 최대로 k개까지 요구할 수 있다는

                        의미(최대 요구량)

              ③ Allocation : 현재 각 프로세스에 할당된 자원의 수를 정의한 n×m 행렬 

                             Allocation[i,j] = k라면 프로세스 Pi는 현재 Rj라는 자원형태를 k개 할당 

                             받고 있다는 의미(할당량)

              ④ Need : 각 프로세스의 남아있는 자원요구를 표시하는 n×m 행렬 Need[i,j] = k라면 

                        프로세스 Pi는 자신의 작업을 종료하기 위해 자원형태 Rj를 추가로 k개 더 요

                        구한다는 의미(추가 요구량)

            <은행가 알고리즘>

              : Requesti를 프로세스 Pi를 위한 요청 벡터라 함. Requesti[j] = k라면 프로세스 Pi는

                Rj형 자원을 k개 요구한다. 프로세스 Pi가 자원을 요청하면 다음의 조치를 취함

              (ㄱ) Requesti ≤ Needi라면 (ㄴ)으로 가고 그렇지 않으면 최대 요구량을 초과하기

                   때문에 오류(요구량 > 필요량 → error)

              (ㄴ) Requesti ≤ Available라면 (ㄷ)으로 가고 그렇지 않으면 자원이 부족하기 때문에

                   대기(요구량 > 잔여량 → 대기)

              (ㄷ) 시스템은 상태를 다음과 같이 수행하여 요구된 자원들을 프로세스에게 할당되도록 

                   한다

                  Available(잔여량) = Available(잔여량) - Requesti(요구량)

                  Allocationi(할당량) = Allocationi(할당량) + Requesti(요구량)

                  Needi(필요량) = Needi(필요량) - Requesti(요구량)

         2) 안전 알고리즘

            <안전 알고리즘>

              (ㄱ) Work, Finish를 각각 길이가 m, n인 벡터라고 하면, Work = Available로

                   Finish[i] = false, i = 1, 2, 3, ..... , n으로 초기화 한다. Work에는 남아 있는

                   자원 수인 Available의 임시변수이다.

              (ㄴ) 다음과 같이 되는 i 값을 찾는다.

                   a) Finish[i] = false

                   b) Needi ≤ Work

                   이런 i 값이 존재하면 (ㄷ)으로 없으면 (ㄹ)로 간다.

              (ㄷ) 자원을 할당한 후 해제한다.

                   Work = Work + Allocationi 

                   Finish[i] = true

                   (ㄴ)단계로 간다.

              (ㄹ) 만약 모든 i에 대하여 Finish[i] = true면 시스템은 안전 상태

     (3) 교착상태의 발견

         - 시스템 운영중에 교착상태가 발생했는지 결정하고 교착상태에 관련된 프로세스와 자원을 발견

         1) 자원 유형마다 여러 개의 자원이 있는 경우

            - 자료구조 정의

              ① Available : 각 자원의 형태별로 사용가능한 자원의 수를 표시하는 길이가 m인 벡터

              ② Allocation : 현재 각 프로세스에 할당된 자원의 수를 정의한 n×m 행렬

              ③ Request : 각 프로세스의 현재 요구를 표시하는 n×m 행렬

              ④ Request[i,j] = k라면 프로세스 Pi는 자원형태 Rj의 자원을 k개 더 요구


            <발견 알고리즘>

              (ㄱ) Work, Finish를 각각 길이가 m, n인 벡터라고 하면, Work = Available로 초기화

                   한다. i = 1, 2, 3, ..... , n일 때 만약 Allocation ≠ 0이면 Finish[i] = false 이고,

                   그렇지 않으면 Finish[i] = true로 초기화한다.

              (ㄴ) 다음과 같이 되는 인덱스 i 값을 찾는다.

                   a) Finish[i] = false

                   b) Requesti ≤ Work

                   이런 i 값이 존재하면 (ㄷ)으로 없으면 (ㄹ)로 간다.

              (ㄷ) Work = Work + Allocationi 

                   Finish[i] = true

                   (ㄴ)단계로 간다.

              (ㄹ) Finish[i] = false면 1 ≤ i ≤ n인 범위에서 시스템은 교착상태

         2) 자원 유형마다 하나의 자원이 있는 경우 교착 상태 발견

            - 대기 그래프 사용 : 자원할당 그래프에서 자원형태 노드들을 삭제하고 적절히 연결선들을

                                 제거하여 사용

            - 대기 그래프가 사이클을 포함하는 경우 교착 상태 존재

     (4) 교착상태의 회복

         - 시스템이 교착상태에 빠지면 교착상태는 하나 또는 그 이상의 교착상태 필요조건을 제거함으로서 

           회복된다

         1) 프로세스 중지

            ① 교착상태 프로세스를 모두 중지하는 방법

               : 교착상태 사이클 제거시 효과적, 비용이 많이 든다

            ② 교착상태 사이클이 제거될 때까지 한 프로세스씩 중지 : 오버헤드가 걸림

            ③ 한 프로세스씩 중지를 위한 희생자 선택의 원칙(희생자 선택 시 고려사항) 기출96

               - 프로세스의 우선순위

               - 수행된 시간과 종료 시간(얼마나 수행되었고 앞으로 얼마나 수행될 것인가)

               - 사용한 자원의 유형과 수(얼마나 많은 자원을 사용중인가)

               - 종료를 위해 필요한 자원의 수(얼마나 많은 자원을 더 필요로 할 것인가)

               - 복귀하는데 포함된 프로세스의 수(몇 개의 프로세스를 복귀시킬 것인가)

               - 대화식인지 일괄 처리식인지의 여부

         2) 자원 선점

            - 교착상태의 프로세스로부터 자원을 선점하여 다른 프로세스에게 제공

            - 자원 선점 시 고려해야할 문제(교착상태 처리 시 강제해제의 문제점)

               : 희생자 선정문제, 복귀문제, 기아상태 문제


2.4 CPU 스케쥴링

2.4.1 스케쥴링

     (1) 개요

         1) 정의 - 작업을 처리하기 위해 프로세스들에게 중앙처리 장치나 각종 처리기들을 할당하기 위한

                   정책을 계획하는 것

         2) 목적

            - 공정한 스케줄링 : 무한대기에 빠지는 프로세스가 없어야 함

            - 처리능력 극대화 : 단위 시간당 처리량의 최대화

            - 응답시간 최소화 

            - 반환시간 예측가능 

            - 우선순위제 실시

            - 무한대기 상태 회피

            - 응답시간과 자원이용간의 균형유지

            - 균형있는 자원 사용

         2) 스케쥴링의 기준

            - I/O중심 프로세스와 연산중심 프로세스의 적절한 혼용

            - 작업형태 고려  - 우선순위 고려  - 페이지 부재율 고려  - 자원선점 고려

            - 버스트시간 고려  - 잔여 실행시간 고려

         3) 스케쥴링 알고리즘 성능의 기준

            - CPU이용율  - 처리율  - 수행시간  - 대기시간  - 응답시간

     (2) 프로세스 스케쥴링의 분류

         1) 단계별 분류

            ① 상위수준 스케쥴링(high level scheduling)

               - 시스템의 자원을 어느 작업에 할당할 것인가를 결정 = job 스케쥴링 = 승인 스케줄링

            ② 중간수준 스케쥴링(intermediate level scheduling)

               - CPU를 차지할 프로세스를 결정

               - 프로세스들을 일시중지시키거나 활성화시키는 작업을 수행하여 시스템의 부하를 조정

            ③ 하위단계 스케쥴링(low level scheduling)

               - 어느 프로세스에게 CPU를 할당할 것인가를 결정

               - 수행 속도가 빠르다

         2) 방법별 분류 기출96

            ① 선점(preemptive) 스케쥴링 - RR, SRT, 다단계(피드백) 큐

               - 한 프로세스가 CPU를 차지하고 있을 때 우선순위가 높은 다른 프로세스가 현재

                 프로세스를 중지시키고 자신이 CPU를 차지할 수 있는 경우

               - 높은 우선순위를 가진 프로세스들이 빠른 처리를 요구하는 시스템에서 유용

               - 빠른 응답시간을 요구하는 시분할 시스템에 유용

               - 높은 우선순위 프로세스들이 들어오는 경우 오버헤드를 초래

            ② 비선점(nonpreemptive) 스케쥴링

               - 한 프로세스가 CPU를 할당받으면 다른 프로세스는 CPU를 점유못함 

               - 짧은 작업을 수행하는 프로세스가 긴 작업이 종료될 때까지 기다려야 함

               - 모든 프로세스들에게 공정하고 응답시간의 예측이 가능

         3) CPU 스케쥴링 알고리즘별 분류

            ① 우선순위(priority) 스케줄링 - nonpreemptive

               - 프로세스에게 우선순위를 부여하여 우선순위가 높은 순서대로 처리

               - 일반 프로세스는 0~15사이, 실시간 프로세스는 16~31 사이의 우선순위를 받는다.

               ㄱ) 정적(static) 우선순위 방법

                   - 주변 환경 변화에 적응하지 못하여 실행중 우선순위를 바꾸지 않음, 

                     구현이 쉽고 오버헤드가 적다

               ㄴ) 동적(dynamic) 우선순위 방법

                   - 상황 변화에 적응하여 우선순위를 변경, 구현이 복잡, 오버헤드 많다,

                     시스템의 응답속도를 증가시켜 효율적

            ② 기한부(deadline) 스케줄링 - nonpreemptive

               - 작업을 명시된 시간이나 기한내에 완료되도록 계획

               - 작업시간이나 상황등 정보를 미리 예측하기가 어렵다

            ③ FIFO 스케줄링 - nonpreemptive

               - 프로세스들은 대기 큐에 도착한 순서대로 CPU를 할당 받는다

               - 일괄처리 시스템에서 주로 사용, 작업 완료 시간을 예측하기 용이

               - 짧은 작업이 긴 작업을 기다리게 됨

               - 중요하지 않은 작업이 중요한 작업을 기다리게하여 불합리

            ④ 라운드로빈(round robin) 스케줄링 - preemptive 기출94 기출96

               - FCFS에 의해서 프로세스들이 보내지며

               - 각 프로세스는 같은 크기의 CPU 시간을 할당받음, CPU의 타임슬라이스에 의해 제한 받음

               - 시분할 방식에 효과적, 할당시간의 크기가 매우 중요

               - 할당시간이 크면 FCFS와 같게되고, 작으면 문맥교환이 자주 일어난다.

               * SRR(selfish round robin)

                  - 프로세스가 시스템에 들어오면 우선순위가 활성 큐 내의 프로세스의 수준에 도달할

                    때까지 보류 큐에 머물러 있는 스케줄링 기법

            ⑤ SJF(shortest job first) 스케줄링 - nonpreemptive 기출94

               - 준비 큐 내의 작업 중 수행시간이 가장 짧다고 판단되는 것을 먼저 수행

               - FCFS보다 평균 대기 시간을 감소, 큰 작업은 시간 예측이 어렵다

               - 짧은 작업에 유리

            ⑥ SRT(short remaining time) 스케줄링 - preemptive

               - 가장 짧은 시간이 소요된다고 판단되는 프로세스를 먼저 수행

               - 남은 처리 시간이 더 짧다고 판단되는 프로세스가 준비 큐에 생기면 언제라도 실행중인 

                 프로세스가 선점 됨, 시분할 시스템에 유용, 서비스를 받은 시간 기록

               - 긴 작업은 SJF보다 대기 시간이 길다, 이론적으로 대기시간 최소

            ⑦ HRN(highest response ratio next) 스케줄링 - nonpreemptive

               - 긴 작업과 짧은 작업간의 지나친 불평등을 어느 정도 보완한 기법

               - 짧은 작업이나 대기시간이 긴 작업은 우선순위가 높아진다

               - 우선순위 = 

            ⑧ 다단계 큐(multilevel queue) 스케줄링 - preemptive

               - 작업들을 여러 종류의 그룹으로 나누어 여러개의 큐를 이용하는 기법

            ⑨ 다단계 피드백 큐(multilevel feedback queue) 스케줄링 - preemptive 기출95 기출96

               - 입출력 위주와 CPU 위주인 프로세스의 특성에 따라 서로 다른 CPU의 타임 슬라이스 부여

               - 짧은 작업에 유리, 입출력 위주의 작업에 우선권을 줌

               - 하위단계 큐일수록 할당시간은 커진다

            ⑩ FSS(fair share scheduling)

               - 프로세스들 집합간에 프로세스의 스케줄링을 지원

               - UNIX 환경에서 서로 관계 있는 사용자들에게 한정된 비용으로 시스템 자원을

                 사용할 수 있게 해준다.


제3장 기억장치 관리

3.1 주기억 장치 관리

3.1.1 개요

     (1) 용어

        - 주기억 장치 : CPU가 명령이나 자료를 직접 인출 혹은 반환할 수 있는 기억장치의 부분

        - 가상기억장치 : 특정 컴퓨터 시스템에서 주기억 장치의 이용 가능한 기억 공간보다 훨씬 큰 주소

                         지정을 할 수 있도록 하는 기법

        - 단일 사용자 시스템 : 한 사람이 CPU와 모든 주기억 장치를 할당받아 사용하는기법

        - 동적적재 : 기억장치의 효율을 높이기 위해 사용. 사용되지 않는 루틴은 주기억장치에 적재되지 

                     않는다

        - 동적연결 : 언어 서브루틴 라이브러리들과 같은 시스템 라이브러리의 연결이 수행시간까지 지연

        - 절대로더 : 기계어로 된 프로그램을 미리 지정된 주기억 장치에 적재

        - 재배치로더 : 적재시간에 주기억 장치의 사용여부에 따라 주기억 장치의 여러 다양한 곳에 적재

        - 링킹로더 : 프로그램 적재시 필요한 프로그램들을 결합하여 이진 프로그램 이미지를 주기억장치에 

                     적재

        - 링키지에디터 : 링킹로더의 기능과 더불어 이진프로그램 이미지를 디스크에 보관

     (2) 기억장치 관리 정책

        1) 반입정책(fetch strategic) - 프로그램이나 데이터의 주기억장치 적재 시기 결정

           ① 요구 반입정책(demand fetch strategic)

               : 프로그램이나 자료에 대한 요구가 있을 때 주기억 장치로 가져오는 방식

           ② 예상 반입정책(anticipatory fetch strategic) : 요구가 없어도 앞으로 필요한 것이라 예상되는 

                                                        내용을 주기억장치로 미리 가져오는 방식

        2) 배치정책(placement strategic) - 프로그램이나 자료를 주기억장치의 어디에 위치시킬 것인 가를 

                                          결정하는 정책

           ① 최초적합(first-fit) : 주기억장치 공간 중 프로그램을 저장할 수 있는 최초의 유용한 공간에 

                                 우선적으로 할당하는 방법 기출94

              - 장점 : 기억장치 전체를 조사하지 않아 배치결정을 빨리 내릴 수 있다

              - 단점 : 사용되지 않은 작은 크기의 가용공간이 누적될 경우 할당결정이 늦을 수 있다

             * NEXT-fit

                - 최초 적합의 변형으로 이전에 탐색이 끝난 그 다음부터 사용가능한 공백을 탐색

           ② 최적적합(best-fit) : 주기억장치의 가용공간 중 프로그램을 저장할 때 가장 작은 공간이 남는 

                                 분할에 할당

              - 장점 : 가용공간을 반만 탐색해도 필요 공간을 찾음

              - 단점 : 가용공간이 크기 순으로 정렬되어 있지 않으면 모든 가용공간을 검색해야 한다

                     : 기억장소 정렬에 많은 시간 요구

                     : 할당한 후 작은 가용공간이 또 만들어짐

           ③ 최악적합(worst-fit) : 주기억 장치 가용 공간중 가장 큰 공간에 프로그램을 할당

              - 장점 : 할당후 남은 공간은 크므로 다른 프로그램 실행가능

              - 단점 : 가용공간이 크기순으로 되어있지 않으면 모든 공간을 검색해야 함

                     : 큰 프로그램이 적재될 가용공간이 없어진다

        3) 교체정책 - 새로 입력되는 프로그램이나 자료에 필요한 기억장소 확보를 위해 어떤 프로그램을 

                      제거할 것인가를 결정하는 정책

     (3) 기억장소 할당

        1) 연속 기억장치 할당 - 각 프로그램이 주기억장치 내에 인접되어 연속된 하나의 블록을 차지하도록  

                                배치

        2) 불연속 기억장치 할당 - 하나의 프로그램이 여러 개의 블록으로 나뉘어 분산 배치되는 방법


3.1.2 주기억장치 관리 기법

     (1) 단일 사용자 연속 기억 장치 할당

            ① 기억장치 할당 방법

               : 주기억장치 용량을 초과하는 프로그램은 실행할 수 없으며 한 순간에 오직 한 명의

                 사용자만이 주기억장치를 전용하여 사용하므로 다른 사용자는 기다림

            ② 장점 : 단순하며 이해하기 쉽다

            ③ 단점 : 기억장치의 빈 공간을 이용하지 못하기 때문에 기억장치의 낭비

                    : 한 사용자만이 기억장치로 전용하므로 자원낭비가 심하다

                    : 입출력 시 CPU는 유휴상태

                    : 사용하지 않는 프로그램이 기억장치 내에 위치

        1) 상주 모니터 - 어떤 작업이 다음에 수행되어야할 것인지에 대한 정보유지

        2) 오버레이 기법

           - 디스크에 프로그램을 유지하고 운영체제에 의해서 기억장치를 교체시키는 방법

           - 프로그램 수행도중 주기억장치의 프로그램 일부가 더 이상 필요하지 않다면 그곳에 보조기억 

             장치로부터 다른 프로그램을 적재(load)하여 겹쳐서 사용하는 방법

           - 한정된 기억장치를 확장하여 사용할 수 있는 개념 제공

           - 기억장치 할당방법 : 프로그램이 기억장치의 크기보다 클 경우에는 프로그램 수행을 허용

                              : 오버레이 중첩을 이용하여 오버레이 영역보다 커다란 프로그램도 처리 가능

        3) 교체기법(swapping)

           - 다중 프로그래밍 환경에서는 CPU 할당 시간이 초과되면 기억장치 관리자는 실행이 끝난

             프로세스를 보조기억 장치로 보내고 다른 프로세스를 주기억장치의 가용 공간으로 불러와 실행

           - 교체 순서 : 한번에 하나의 사용자 프로세스만 주기억장치를 할당받는다

             ① 사용자 프로세스가 주기억장치에서 수행되다 교체된다

                - 프로세스의 실행도중 입출력 발생 시

                - CPU 사용 할당시간이 초과될 때 

                - 프로세스 수행이 완료될 때 

             ② 교체영역이 보조기억 장치에 복사됨(swap out)

             ③ 다음 사용자 프로세스가 주기억 장치에 들어와 실행됨(swap in)

        4) 시스템의 보호

           - 사용자 프로그램으로부터 운영체제를 보호하기 위해 CPU 내부에 경계 레지스터를 둔다

           - 경계 레지스터는 운영체제의 제일 마지막 명령의 주소 저장

     (2) 고정 분할 기억장치 할당(MFT : Multiple Contiguous Fixed parTition allocation) 기출95

        - 주기억 장치를 일정수의 고정된 크기들로 분할하여 실행중인 여러 프로세스에게 할당하는 기법

           (=고정분할 다중 프로그래밍)

        - 입출력 요구가 생기게 되면 데이터의 입출력 처리가 끝나기 전까지는 작업을 중단해야 한다.

        - CPU 계산과 입출력은 동시에 행해질 수 있다.

        - 입출력 속도는 CPU 속도에 비해 엄청 느리다.

         1) 절대번역과 적재(absolute compile & loading)

            - 한 작업이 실행준비가 되어있다 하더라도 지정된 자신의 분할이 이미 차 있으면 다른 분할이 

              이용가능 하더라도 그 작업은 기다려야 한다

            - 미리 정해진 주기억 장치의 적재 위치에서만 해당 프로그램을 실행할 수 있게 하는 것 

            - 장점 : 간단하고 구현하기 쉽다

            - 단점 : 기억장치의 낭비 발생

         2) 재배치 번역과 적재(relocation compile & loading)

            - 모든 작업을 하나의 작업 큐에 넣어서 어느 분할에서든지 실행 가능하도록 한 기법

            - 장점 : 기억장소의 낭비가 없다

            - 단점 : 재배치 번역과 적재의 설계가 복잡(운영체제가 복잡)

         3) 고정분할 기억장치 할당에서의 보호

            - 여러 개의 경계 레지스터(합당한 사용자 주소범위를 나타내는 하한 레지스터와 상한 레지스터

              로 되어 있다)를 사용

         4) 고정분할 기억장치 할당의 장단점

            - 장점 : 다중 프로그래밍 가능, 수행속도 증가로 CPU를 효율적으로 사용

                   : 한 작업이 입출력을 수행할 때 CPU는 다른 작업의 계산을 처리할 수 있다.

            - 단점 : 단편화에 의해 기억장치의 낭비가 크다

                   : 수행할 프로그램의 크기를 미리 알고 있어야 함

     (3) 가변분할 기억장치할당(MVT : Multiple contiguous Variable parTition allocation) 기출95

         - 고정된 분할의 경계를 없애고 각 작업의 필요한 만큼의 기억장치를 할당

         - 가장 합리적인 분할의 크기를 결정하여 각 작업에게 주기억장치로 할당, 바운드 레지스터 필요

         - 장점 : 단편화방지, 자원의 효율적 사용

         - 단점 : 기억장치 집약시간 낭비

                : 작업의 크기가 기억장치 용량에 의해 제약됨, 외부단편화 심각

     (4) 기억장치의 단편화(Memory Fragmentation) 기출96

         - 단편화 : 작업을 수행하기 위한 기억장소 분할영역이 부족하거나 남는 경우

         - 단편화 종류 : 내부 단편화 - 하나의 분할에 작업을 할당하고 남은 빈 공간 

                       : 외부 단편화 - 대기중인 작업이 분할영역보다 커서 분할 전체가 빈 공간으로 있을

                                       때의 상태

         1) 고정분할 기억장치 할당에서의 단편화

            : 사용자 작업의 크기가 정확하게 분할에 맞지 않거나 작업보다 분할이 너무 작아서 이 분할에 

              대기중인 어떤 작업도 적재될 수 없는 경우 발생

         2) 가변분할 기억장치 할당에서의 단편화

            : 할당초기와 초기작업이 끝나 그들이 사용하던 기억공간이 공백으로 남을 때까지 기억공간의 

              낭비가 거의 없거나 분명하게 나타나지 않는다. 그러나, 실행을 기다리는 작업들에게 이 공백을

              할당하면서부터 기억장치의 단편화가 발생

         - 단편화의 해결 방법

            ① 공백의 통합(coalescing holes) : 가용 공간 중 이웃되는 가용공간을 하나의 커다란

                                             가용공간으로 만드는 것

            ② 기억장소 집약(storage compaction)

               : 가변분할 다중 프로그래밍에서 존재하는 여러 개의 작은 공간을 모아 하나의 커다란

                 기억공간을 만드는 것 = garbage collection

               : 장점 : 모든 미사용 공간을 모으므로 통합보다 메모리를 효율적으로 사용

                 단점 : 집약이 실행되는 동안 모든 일을 중지

                      : 실시간 처리 시스템의 경우 작업에 치명적

                      : 기억장치의 작업들이 모두 재배치되어야 함 

                      : 시스템 효율저하, 생산적으로 사용 가능한 시스템 자원을 소비한다.


3.2 가상 기억장치의 구성

3.2.1 가상 기억장치의 개요

     - 가상 기억장치(virtual memory)

        : 주기억장치에서 이용 가능한 공간보다 더 큰 저장 공간을 보조기억 장치에 생성하여 마치

          주기억장치의 연속된 공간처럼 사용하는 기억장치

        : 사용자의 논리적 기억장치를 실기억 장치로부터 분리시킨 것으로 요구페이징으로 구현

        : 실행중인 프로세스에 의해 참조되는 주소를 기억장치에서 사용할 수 있는 주소와 분리

        : 여러 사용자가 같이 사용

     - 세그먼트(segment) : 블록의 크기가 다를 때 

     - 페이지(page) : 블록의 크기가 같을 때

     - 가상주소(V) : 프로그래머에 의해 쓰여진 보조기억장치 번지

     - 실 주소(R) : 주기억장치의 사용 가능한 주소

     - 주소 사상(address mapping) : 보조기억장치에 존재하는 가상 번지를 주기억 장소의 실제 주소로 변환

     (1) 동적 주소 변환(DAT : dynamic address translation)

         : 프로세스가 수행될 때 가상주소를 실제 주소로 변환하는 기법

     (2) 블록 사상(block mapping)

         : 모든 내용을 한번에 사상할 수 없으므로 가상기억장치의 내용을 블록 단위로 분류하여 가상

           기억장소 블록이 실기억 장치의 어느 곳에 위치하는지 알아내 블록 단위로 사상하는 방법

         : 블록이 크면 - 사상기법 자체가 필요로 하는 기억공간을 줄일 수 있다

                       - 블록 이동시 전송시간이 많이 걸림

                       - 주기억장치가 많이 소요, 실기억 장소는 작아진다.

         : 블록사상을 통한 가상주소 변환


3.2.2 페이징(paging) 기법 기출94 기출95

     - 페이지는 블록단위로 보조기억장치로부터 주기억장치로 옮겨짐

     - 입력되는 페이지는 사용 가능한 페이지 프레임의 어느 곳에나 위치할 수 있다.

     - paging : 가상 메모리를 일정 크기의 블록으로 나눈 페이지를 주기억장치에 사상

              : 고정된 블록 크기로서 페이지와 관련된 가상기억장치 구성

     - 페이지 프레임 : 가상기억장치의 블록과 사상되는 주기억장치의 한 블록

                     : 고정된 페이지 크기의 정수 배에 해당하는 실기억 장치 주소에서 시작

     - 내부 단편화 발생, 페이지 크기의 1/2, 외부 단편화는 없다

     - V = (p, d) : p 페이지 번호, d 변위

     - 주소변환 방법

        1) 직접 사상에 의한 주소 변환 

           - 페이지 사상 테이블의 시작주소(b) + 페이지번호(p) = p'

           - p' + 변위(d) = 실제주소(r)

           - 컴퓨터 시스템의 속도를 절반으로 떨어뜨린다.(이를 보완하기 위해 캐시기억장치 사용)

           - 가상주소와 PMT(page map table)는 시스템 내의 제어프로세서 내에 존재하여 빠르게 실행

        2) 연관 사상 방법에 의한 주소 변환

           - 위치 지정이 아닌 내용지정의 연관 기억장치에 사상 페이지 사상표를 유지

           - 구현하는 비용이 많이 든다(캐시보다 비싸다), 가장 빠르고 융통성이 있음

           - 직접사상보다 구현이 어려움(잘 사용되지 않는다)

           - 실행 프로그램이 가상주소를 참조, 동적 주소변환을 빠르게 할 수 있다.

           - 연관 사상 테이블 내 페이지 p에 해당하는 페이지 프레임(p') + 변위(d) = r

        3) 연관 / 직접 사상에 의한 페이징 기법

           - 가장 최근에 참조된 페이지 항목들만 유지, 일부 사상 테이블만 포함

           - 캐시와 연관 기억장치의 이점을 효과적으로 혼합

           - 연관 사상 테이블을 먼저 찾은 다음 없으면 직접 사상 테이블을 찾는다.

           - 페이지 p가 사상 테이블에 있는 경우

              : 연관 사상 테이블 내 페이지 p에 사상되는 페이지 프레임(p') + 변위(d) = r

           - 페이지 p가 사상 테이블에 없는 경우

              : 페이지 사상 테이블의 시작주소(b) + 페이지번호(p) + 변위(d) = r

           - 연관 사상표(table) : 최근에 가장 많이 참조된 페이지

              페이지 사상표 : 연관 사상표에서 제외된 나머지 모든 페이지


3.2.3 세그멘테이션(srgmentation) 기법

     - segmentation : 가상 메모리를 가변 크기의 블록으로 나누어 주기억장치에 사상

                    : 가변 블록 크기로서 세그먼트와 관련된 가상 기억장치 구성

     - 외부 단편화 발생

     - 논리적 개념, 고정되어 있지 않다, 배열에 사상하는 세그먼트는 배열의 크기와 같다

     - 자료구조가 커지거나 작아짐에 따라 크고 작게 될 수 있다.

     - 프로세스는 현재 세그먼트가 주기억장치에 있을 때만 실행

     - 보호키를 사용하여 기억장치를 보호

     - V = (s, d) : s 세그먼트, d 변위

     - 접근제어(access control)

        : 엑세스 유형 ; read, write, execute, append

        : 세그먼트 엑세스 방법

          1) 엑세스 종류는 R, W, E, A의 4가지

          2) 4가지 엑세스의 조합으로 프로세스가 제한 없이 세그먼트를 엑세스 하는 것을 방지

          3) 16가지 조합 생성

          4) 세그먼트 보호의 기초 방법

     - 주소변환 방법

        1) 직접 사상에 의한 주소 변환

           - 세그먼트 사상 테이블의 시작주소(b) + 세그먼트번호(s) = s'

           - 세그먼트가 시작되는 실기억장치의 주소(s') + 변위(d) = 실제주소(r)


3.2.4 페이징 / 세그멘테이션 혼용 기법 기출96

     - 가상 기억장치의 구조에 중요한 이점을 제공, 크기는 페이지의 정수 배

     - 변환과정이 진행됨에 따라 실패할 수 있는 많은 단계가 존재

     - 참조된 페이지들은 부분적인 연관 기억장치에 있다.

     - 세그먼트 기법의 보완, 세그먼트를 페이지화 하는 것

     - V = (s, p, d) : s 세그먼트번호,  p 페이지번호,  d 변위

     - 내부 단편화 발생, 사상표가 차지하는 공간(table space)의 오버헤드도 증가

     - 주소변환 과정

        ① 연관 사상인 경우 : 연관 사상표를 탐색하여 발견되면 해당 페이지가 들어있는 주기억장치

                              내의 페이지 프레임 p'와 변위d를 더함

        ② 직접 사상인 경우 : 세그먼트 사상표의 시작주소(b) + 세그먼트번호(s) + 페이지 번호(p) + 

                              변위(d) = 실제주소(r)


3.2.5 요구페이징 기법 기출96

     - 보조기억 장치에 페이지들이 저장되어 있다가 실행 중인 프로세스에 의하여 그 페이지가 요구될 때만

        보조기억 장치에서 주기억장치로 옮겨지는 기법

     - 페이지 부재율을 낮게 유지해야 함 : 주기억장치 유효접근시간이 증가하여 수행시간이 늦어지게 된다.

     - 교체시간을 줄일 수 있다, 기억장치 사용량 절감, 많은 프로그램을 동시에 수행시킬 수 있다.

     - PMT필요, 비례할당, Thrashing문제 발생, 많은 테이블과 레지스터 필요, S/W가 복잡해진다.

   * 페이지 부재(page fault)

     - 프로세스에서 원하는 페이지가 주기억장치 내에 존재하지 않는 경우

     - 페이지 부재 처리시간의 구성요소 : 페이지부재 인터럽트 서비스, 페이지 교체, 프로세스 재실행


3.2.6 예상 페이징 기법

     - 예측 결정이 옳으면 프로세스의 실행시간은 대단히 감소

     - 정확한 결정이 내려질 수 있다. 

     - H/W 가격 하락 등 옳지 못한 결정의 결과도 그리 심각하지 않다.


3.3 가상 기억장치의 관리

3.3.1 가상 기억장치의 관리 기법

     1) 반입정책 - 보조기억장치에서 실기억장치로 사상한 페이지나 세그먼트의 적재시기 선택

     2) 배치정책 - 보조기억장치로부터 적재된 내용을 실기억장치의 어느 위치에 배치할 것인가

     3) 교체정책 - 실기억장치로 들어오는 페이지의 기억공간 확보를 위해 실기억장치의

                   어느 페이지를 가상 기억장치로 돌려보낼 것인가를 결정


3.3.2 페이지 교체 알고리즘

     (1) 최적교체 알고리즘

        - 다른 페이지 교체 기법들이 얼마나 최적성을 갖는지 비교하는데 사용

        - 현 페이지가 참조된 시점에서 그 이후로 가장 오랫동안 사용되지 않을 페이지를 교체

        - 장점 : FIFO의 모순을 피할 수 있는 알고리즘(최소의 페이지 부재율)

        - 단점 : 페이지 호출 순서에 대한 모든 상황을 미리 파악하고 있어야 하기 때문에 다루기가 어렵고 

                 비현실적

     (2) 무작위 페이지 교체 알고리즘

         - 교체할 페이지를 무작위로 선택

         - 장점 : 오버헤드가 적은 페이지 교체 기법

         - 단점 : 최악의 경우 바로뒤에 호출될 페이지도 교체될 수 있다

     (3) 선입선출(FIFO) 교체 알고리즘

         - 각 페이지가 참조된 때와 관계없이 주기억장치에 가장 먼저 들어온 페이지를 교체

         - FIFO 모순 : 페이지 프레임의 수가 증가될 때 페이지 부재가 더 증가하는 것

         - 장점 : 이해가 쉽고 설계가 간단

         - 단점 : 중요 페이지가 오랫동안 페이지 프레임을 차지 했다는 이유로 교체될 수 있다

     (4) 2차 기회 페이지 교체 알고리즘(SCR : second chance replacement)

         - 페이지의 참조비트가 0이면 교체하고 참조비트가 1이면 0으로 바꾼 다음 큐로 피드백 시켜

           두 번째 기회를 부여한 후 다음 페이지를 조사

     (5) LRU(least recently used) 교체 알고리즘 기출94

         - 한 프로세스에서 사용되는 각 페이지마다 카운터를 두어 현 시점에서 가장 오랫동안 사용되지

           않은 페이지를 제거

         - 단점 : 시간 오버헤드가 발생, 실제로 구현하기 복잡

     (6) LFU(least fraquence used) 알고리즘

         - 사용된 빈도(호출회수)가 가장적은 페이지를 교체, 구역성 문제 발생

         - 단점 : 바로 불러온 페이지가 교체될 수 있다

     (7) NUR(not used recently) 교체 알고리즘

         - 최근에 사용되지 않은 페이지를 교체. 2개의 bit를 둔다(참조 비트, 변형 비트)

         - 단점 : 현재 실행중인 페이지도 교체할 수 있다

     (8) Working Set - 프로세스가 최근 참조하는 페이지들의 집합에 속하지 않는 페이지를 모아 놓는

                        방법으로 집합에 속하지 않는 페이지를 교체

     (9) 페이지 부재 빈도 (PFF(page fault frequency))

        - 현재 페이지 부재와 바로전의 페이지 부재 사이의 시간을 관찰하여 그 시간이 지금까지의

          최소시간보다 크다면 그 사이에 호출되지 않았던 페이지들을 모두제거


3.3.3 Thrashing 기출94 기출95

     - 페이지 교체가 너무 자주 일어나는 현상

     - 프로세스 처리 시간보다 페이지 교체 시간이 더 많아지는 현상

     (1) 원인 - 실제로 사용하는 수만큼의 충분한 페이지 프레임을 갖지 못한 경우 페이지 부재가 빈번하게 

              발생하며 이 경우 실행중인 프로세스는 계속 페이지 교체를 수행해야 하므로 thrashing 현상이 

              발생

     (2) 방지 법 - 다중 프로그래밍의 정도를 낮추어야 한다(프로세스들에게 충분한 페이지 프레임을 

                  할당하여 주기억장치 내에 working set을 제대로 유지)

* 구역성(locality) = 국부성

 - 프로세스가 기억장치내의 정보를 균일하게 참조하는 것이 아니라 어느 순간 특정 부분을 집중적으로 참조

   ① 시간구역성(temporal locality) - 최근 참조된 기억장소가 가까운 장래에도 계속 참조될 가능성이 높다.

                                    (looping, subroutine, stack, counting, totaling)

   ② 공간구역성(spatial locality) - 임의 기억장소가 참조되면 그 근처의 기억장소가 연속적으로 참조될

                                  가능성이 높다(배열순례(array traversal), 순차적 코드의 수행,

                                                프로그래머가 관련 변수를 상호 이웃하게 선언하는 경향)

   - 기억장치에서 구역성이 중요한 이유 : 각 프로그램이 자주 참조하는 페이지들(working set)이

                                         주기억장치에 있으면 프로그램의 수행을 효율적으로 할 수 있다


3.3.4 Working Set 기출94

     - working set : 한 프로세스가 일정 시간동안 참조하는 페이지들의 집합

     - 프로그램이 효율적으로 수행되기 위해서는 working set이 주기억장치 내에 유지되어야 함


3.4 보조 기억장치

3.4.1 보조 기억장치의 개요

     * 보조 기억장치 ? 주기억장치에 저장되어 있는 정보를 제외한 모든 정보가 저장되어 있으며 필요에

                       따라 주기억장치에 전송

        1) 순차 기억 매체(SASD:Sequential Access Storage Device)

           - 자기 테이프 장치처럼 적절한 레코드가 찾아질때까지 차례차례 검색

        2) 직접 기억 매체(DASD:Direct Access Storage Device)

           - 자기 디스크 장치처럼 주소를 통해 직접 적절한 레코드를 찾아 가는 매체


3.4.2 자기 테이프(Magnetic Tape)

    (1) 개요

        1) 원리 - 자성 물질이 칠해진 테이프가 자기 테이프 구동장치의 헤드를 지날 때 전류를 변화시켜 

                  테이프에 정보를 기록

        2) 구성 - 총 9트랙 중 8개의 트랙은 데이터를 저장하는데 사용되고 나머지 1트랙은 데이터 전송 시

                  에러 여부를 검사하기 위한 패리티 비트를 저장하는데 사용

    (2) 특성 - 많은 양의 데이터 저장 가능

             - 속도가 느리고 순차접근을 하므로 데이터 보관용으로 사용

             - 순차처리만 가능(SASD:Sequential Access Storage Device)

             - 가격이 저렴하여 Backup용으로 많이 사용

             - 데이터를 읽기 위한 시간이 많이 걸린다

    (3) Label의 구성

        

        1) BOT(Beginning of Tape) : 테이프의 시작 부분

        2) VOL(Volume of Label) : 볼륨 레이블

        3) File Label : 파일의 앞과 뒤에 붙임

        4) TM(Tape Mark) : 레이블과 파일을 구분

        5) DATA : 실제 자료

        6) EOT(End of Tape) : 테이프의 끝 부분

    (4) 데이터의 구성

        

        󰠉<󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏󰠏>󰠋

                   물리 레코드 = BLOCK

        1) 논리 레코드(logical record) : 실제 저장되어 있는 레코드

        2) 물리 레코드(physical record) : 입출력 단위로 취급. 1개 이상의 논리 레코드로 구성 = block

        3) IRG(inter record gap) : 논리 레코드 사이의 간격

        4) IBG(inter block gap) : 블록간 데이터가 기록되지 않은 부분으로 테이프가 정상주행 속도에 

                                 이를 때까지의 시간과 멈출 때까지의 시간을 확보하기 위한 부분

        5) Blocking : 레코드의 입출력 효율을 높이기 위해 여러 개의 논리레코드를 하나의 블록으로

                      묶는 것

           * 블록화 하는 이유

              - 런 비용이 적게 든다, 물리적인 레코드의 기어용량을 절약, 입출력 실행 시 시간 절약

        6) 블록화 인수(blocking factor) : 한 물리 레코드 안에 있는 논리 레코드의 수


3.4.3 자기 디스크(Magnetic Disk)

    (1) 개요 기출94

        1) 구조 - 원형 금속판에 자성체를 입힌 것으로 트랙, 섹터, 실린더로 구성

           ① 트랙(track) - 디스크의 중앙을 중심으로 그려진 동심원

           ② 섹터(sector) - 트랙을 부채꼴 모양으로 분할한 것

           ③ 실린더(cylinder) - 각 면의 같은 위치에 있는 트랙들의 모임 또는 디스크 중앙으로부터 

                                같은 거리에 있는 트랙의 모임

        2) 접근시간

           ① 탐색시간(seek time) - 헤드를 적정 트랙으로 이동하는데 걸리는 시간

           ② 회전지연시간(rotational delay time) - 헤드가 트랙으로부터 데이터가 있는 섹터에

                                                  접근하는데 걸리는 시간

           ③ 헤드활성화시간(head activation time)

           ④ 전송시간(transmission time) - 데이터를 주고 받는데 걸리는 시간

    (2) 디스크 장치의 종류

        1) 이동 헤드 디스크 기출96

           - 판독/기록 헤드가 원하는 트랙에 위치하도록 액세스 암을 이동시켜 데이터를 읽거나 씀

           - 데이터 전송률 = 탐색시간 + 회전지연시간 + 헤드활성화시간 + 전송시간

           - 탐색 시간이 가장 많이 소요

        2) 고정 헤드 디스크

           - 각 트랙마다 읽기/쓰기 헤드를 가지고 있어 탐색시간을 없앰

           - 데이터 전송률 = 회전지연시간 + 헤드활성화시간 + 전송시간

    (3) 디스크 인터리빙(interleaving)

        - 디스크 제어기에게 기억장치로 데이터를 전송하기 위한 시간을 주기 위해 블록을 건너뛰도록 

          하는 기법

        - 지연시간 때문에 인접한 디스크 블록 사이에 두는 일정한 간격 : 인터리빙 인수

    (4) 그 외 디스크 장치

        1) 자기드럼 - 원통형 표면에 자성 데이터를 입힌 것

                    - 헤드가 움직이지 않으므로 탐색시간이 없다

                    - 저장 데이터량이 적고 부피에 비해 용량이 적다

                    - 자기디스크보다 접근시간이 빠르다

        2) 자기코어 - 환상형의 강자성체 물질로 되어 자화방향에따라 0,1을 표시

        3) 광 디스크 - 레이저 빔 이용. 처음 데이터 접근 시간은 느리나 연속된 데이터의 엑세스는 빠르다

                     - 접근시간은 자기 디스크보다 빠르다

    * 캐시(Cache)

       1) CPU 캐시 기억장치

          - CPU와 주기억장치의 속도차이를 완화시키기 위한 장치

          - 개념적으로 CPU와 주기억장치 사이에 존재하나 실제 CPU 내부에 있다

          - CPU는 캐시 기억장치와 주기억장치를 직접 접근할 수 있다

       2) 디스크 캐시

          - 국부적 휴리스틱 기법 사용 : 빈번히 사용되는 레코드가 무엇인지 알기 위해

          - 주기억장치와 디스크의 속도차이를 개선하기 위한 장치

          - 번번이 사용되는 기록을 주기억장치의 디스크 캐시 버퍼에 저장하여 사용

    (5) 디스크 가용공간 관리

        1) 비트 백터

        2) 연결 리스트 - 모든 가용 공간 블록들을 함께 연결

        3) 그룹핑(grouping) - 첫 번째 가용블록 내에 n개의 가용 블록들의 번지를 저장

        4) 카운팅(counting) - 첫 번째 가용블록의 주소와 그 첫 번째 블록에 연속된 가용 블록들의 개수를

                             보존


3.4.4 디스크 스케쥴링 기법

    (1) 개요

        1) 탐색시간 최적화 알고리즘(seek time optimization algorithm)

        2) 회전지연시간 최적화 알고리즘(rotational latency optimization algorithm)

        3) 스케쥴링 분류 기준

           ① 처리율(throughput) - 단위 시간에 디스크의 헤드가 찾을 수 있는 데이터의 수를 최대화

           ② 평균응답시간(mean response time)

           ③ 응답 시간의 편차(variance of response time)

              - 평균 응답시간을 줄이고 예측할 수 있도록 하는 것


    (2) 디스크 스케쥴링 기법

        1) FCFS(First Come First Served) 스케줄링

           - 가장먼저 입력된 요구가 우선적으로 서비스를 받는 방법

           ① 구현 - 대기 큐에 입력된 요구 순서대로 서비스 진행

           ② 특징 - 대기 큐의 순서대로 서비스하며 더 높은 우선 순위의 요청이 입력되어도 순서가

                     바뀌지 않아 공평성이 보장 됨

                   - 디스크 오버헤드(부하)가 커지면 응답시간이 길어진다

        2) SSTF(Shortest Seek Time First) 스케쥴링

           - 탐색 거리가 가장 짧은 요청을 먼저 처리하는 방법

           - 탐색 시간의 극소화, 극단적일 경우 기아상태 발생 가능

           ① 구현 - 현재 위치에서 가장 가까운 거리에 있는 요청을 서비스한다

                   - 대기 큐의 우선순위에 관계없이 다음 최단 거리 요청을 서비스

           ② 특징 - 실린더 지향 기법

                   - 가장 안쪽이나 바깥쪽의 트랙은 가운데 트랙보다 서비스를 받지 못하기 때문에 

                     응답시간의 편차가 크다

                   - FCFS보다 처리량이 많고 평균 응답시간이 짧다

                   - 일괄처리 시스템에 유용하고 응답시간의 편차가 크므로 대화형 시스템에 부적합

        3) SCAN 스케쥴링(엘리베이터 알고리즘)

           - Denning이 개발, SSTF가 갖는 응답시간의 편차와 차별을 극복하기 위한 방법

           - 오버헤드가 적은 경우

           ① 구현 - 헤드진행 방향과 같은 방향의 가장 짧은 거리에 있는 요청을 먼저 서비스하고 진행 중 

                     가장 바깥쪽까지 갔거나 더 이상 요구가 없으면 반대쪽으로 방향을 바꾸어 서비스

           ② 특징 - 디스크 오버헤드가 적어야 가장 좋은 효율을 가짐

                   - 대부분의 디스크 스케줄링의 기본 전략

                   - 밀도가 높은 쪽의 요청은 상당히 오랜 시간 대기하게 됨

        4) C-SCAN(Circular) 스케줄링 기출94 기출95

           - 가장 안쪽이나 가장 바깥쪽 실린더에 대한 차별을 제거

           ① 구현 - 바깥쪽 실린더에서 안쪽으로 진행하면서 최단거리의 요구를 서비스

                   - 더 이상 요구가 없으면 가장 바깥쪽에서 서비스하지 않은 요구로 이동하여 서비스

           ② 특징 - 진행도중 도착한 요청은 다음 수행 시 서비스

                   - 응답시간의 편차가 매우 적다

                   - 회전 시간의 최적화가 가능하며 부하(overhead)가 많이 걸리는 경우 효과적

        5) N-step SCAN 스케줄링

           - 서비스가 한쪽 방향으로 진행될 때 대기 중이던 요구들만 서비스

           ① 구현 - SCAN과 동일

                   - 진행 중 입력된 요청들은 한데 모아 반대방향 진행 때 서비스한다

           ② 특징 - 처리량과 평균응답시간에 있어 효율적

                   - SSTF 나 SCAN 방법보다 응답시간의 편차가 적다

                   - 한 실린더에 많은 요청이 도착해도 대기중인 요청만 처리하므로 무한대기가 없다

        6) 에센바흐 기법(Eshenbach scheme)

           ① 구현 - 헤드는 C-SCAN처럼 움직이는데 예외로 모든 실린더는 그 실린더에 요청이

                     있든 없든 전체 트랙이 한 바퀴 회전할 동안 서비스 받는다

           ② 특징 - 부하가 큰 항공예약 시스템을 위해 개발

                   - 탐색시간과 회전지연시간을 최적화

        7) SLTF(Shortest Latency Time First) 스케줄링

           - 회전지연시간의 최적화를 위한 기법

           ① 구현 - 디스크 헤드가 특정 실린더에 도착하면 여러 트랙을 가리키게 된다

                   - 이 여러 트랙에 대한 많은 요구들 중 가장 짧은 회전지연시간을 갖는 요청에

                     대해 먼저 서비스

           ② 특징 - 구현하기 쉽다. 이론적 최적값과 거의 일치

                   - 회전지연시간 최적화는 디스크 주변의 가장 가까운 섹터가 가장먼저 서비스되므로

                     섹터큐잉(sector queueing)이라 불림

                   - 고정헤드 디스크를 위한 스케쥴링 기법


3.4.5 실시간 처리 디스크 스케쥴링 알고리즘

     1) EDF(Earliest Deadline First) 스케쥴링

     2) P-SCAN(Priority SCAN) 스케쥴링

     3) FD-SCAN(Feasible Deadline SCAN) 스케쥴링

     4) SSEDO(Shortest Seek and Earlist Deadline by Ordering) 스케쥴링 

     5) SSEDV(Shortest Seek and Earlist Deadline by Value) 스케쥴링 

     6) SCAN-EDF 스케쥴링

     7) GSS 스케쥴링


제4장 정보관리

4.1 파일 시스템

4.1.1 개요

    (1) 파일의 개념

        - 프로그램과 데이터로 구성된 작성자에 의해 정의된 상호 관련 있는 정보의 집합체

        - 이름에 의해 참조되고 파일의 형태, 작성시기, 작성자, 길이 등의 속성을 갖는다

    (2) 파일의 종류

        1) 수행되는 기능에 따라 - 마스터, 트랜잭션, 보고서, 작업, 프로그램 파일

        2) 파일 구성에 따라 - 순차, 인덱스 된 순차, 인덱스, 직접, 다중 링 파일

    (3) 파일의 형태

        1) 원시파일   2) 목적파일   3) 텍스트파일

    (4) 디렉토리 개념

        - 디렉토리 구조는 파일 시스템에 있는 여러 파일을 구성하기 위한 기법을 제공

        - 디렉토리에 포함되는 정보 : 파일이름, 파일형태, 파일위치, 파일크기, 현재위치,

                                     보호, 사용 수, 시간, 날짜, 처리식별

    (5) 파일조작

        - 운영체제가 할일 : open, create, write, read, rewind, delete, insert, rename, close

        * 파일 단위 작업 - open, close, create, destroy, copy, rename, list

          레코드 단위 작업 - read, write, update, insert, delete

    (6) 파일 시스템의 기능

        1) 상위기능 - 디렉토리구조제공, 디스크공간할당 및 회수, 파일보호, 데이터 무결성

        2) 하위기능 - 오류검출, 디스크 스케줄링, 암호화, 블록전송

    (7) 파일 시스템의 요소

        1) 엑세스 방식 - 파일에 저장되어 있는 데이터에 대한 접근 방식

        2) 파일 관리 - 파일을 저장, 참조, 공유, 보호할 수 있는 기법 제공

        3) 보조기억장치 관리

        4) 무결성 유지 - 파일의 정보가 소실되지 않도록 보장

    (8) 파일의 특성 결정 기준

        1) 소멸성 - 파일에 자료를 추가하거나 제거하는 작업의 빈도 수

        2) 활성율 - 프로그램이 한 번 수행되는 동안 처리하는 레코드 수

        3) 크기 - 파일에 저장되어 있는 정보의 양


4.1.2 파일의 구조 및 접근방법

    (1) 파일의 구조

        1) 순차파일(sequential file) - 순차적으로 저장되며 일괄처리에 주로 사용

                                  - 테이프 장치와 천공카드, 프린터 등에 주로 쓰임

        2) 인덱스 된 순차파일(indexed sequential file)

           - 레코드가 각 레코드의 키에 따라 논리적 순서대로 배열되어 있는 것

           - 순차데이터 파일과 이 파일에 대한 포인터를 가지고 있는 인덱스로 구성

           - 정적 인덱스와 동적 인덱스방법을 사용하며 디스크 장치에 많이 사용

           - 파일 설계 시 고려해야 할 사항이 많다

        3) 직접파일(direct file)

           - DASD의 상세한 물리적 구조를 알아야 한다.

           - 다른 레코드를 참조하지 않고 어떤 임의의 레코드도 접근 가능

           - 대화형 처리에 이용되며 순차검색은 어렵다

    (2) 파일 접근 방법 기출95

        1) 순차접근(sequential access)

           ① 판독(read) - 테이프의 파일을 순차적으로 읽어 나가며 포인터는 자동 증가

           ② 기록(write) - 파일의 맨 뒤에 추가하며 파일 포인터는 추가된 내용의 끝으로 이동

        2) 직접접근(direct access)

           - 파일이 연속된 블록이나 레코드의 집합으로 간주, 키 값 필요, 가변길이 레코드에 부적합

           - 어떠한 블록도 직접 판독 또는 기록할 수 있다, 접근시간 빠르고 수정용이

        3) 색인순차접근(indexed sequential access method : ISAM)

           - 키 값에 따라 순차적으로 정렬되어있는 레코드에 대한 색인을 사용하여 접근

           - 색인 탐색 후 레코드 영역에서는 순차접근이 수행


4.1.3 기억장소 할당과 회수 방법

    (1) 연속할당(contiguous allocation)

        - 파일들이 디스크 내의 연속적으로 인접된 공간에 할당되는 것

        1) 장점 - 액세스 속도가 빠르고 파일 디렉토리가 단순하다

        2) 단점 - 새로 생성되는 파일의 기억공간의 크기를 미리 결정하며 단편화 발생

                - 원하는 만큼의 기억공간이 확보되지 않으면 그 파일은 생성되지 못함

                - 주기적 압축이 필요

    (2) 연결할당(linked allocation) - 파일이 저장되는 섹터들이 연결 리스트로 구성되고 각 섹터간에는

                                   연결을 위한 포인터를 가지고 있는 형태

        1) 장점 - 단편화가 일어나지 않으며 생성되는 파일의 크기가 문제되지 않는다

        2) 단점 - 논리적으로 연속된 블록의 검색에 긴 시간 요구

                - 연결리스트 구축에 추가시간이 요구되며 포인터를 위한 기억장소가 낭비

                - 포인터가 손상되면 데이터를 찾을 수 없다

    (3) 블록단위할당

        1) 블록체인 기법 - 연결할당과 비슷하나 할당단위가 블록 단위로 이루어지는 방법

           ① 장점 - 삽입과 삭제는 포인터만 수정하므로 간단

           ② 단점 - 속도가 느리다

        2) 색인 블록 체인 기법 - 파일마다 하나의 색인 블록을 두고 이 색인 블록에 포인터를 모아두어 

                                 직접접근을 가능하게 한 기법

           ① 장점 - 탐색 시간이 빠르다. 여러 개의 색인 블록을 서로 연결하여 사용 가능

           ② 단점 - 삽입 시 색인 블록을 재구성해야 함. 기억장치 낭비

        3) 블록지향 파일 사상 기법 - 포인터 대신 블록 번호를 사용


4.1.4 파일의 보호

    - 물리적인 손상으로부터 보호와 파일에 대한 무제한 접근을 방지하는 것

    (1) 보호방법 기출94

        1) 접근제어(access control) - 사용자에 따라 접근 대상을 다르게 구별

        2) 파일이름 명명(naming) - 파일의 이름을 알지 못하는 경우 접근대상에서 제외

        3) 암호(password) - 파일 접근 시 암호를 입력하여 접근하는 방법

    (2) 백업과 복구 - 주기적으로 시스템 파일을 복사하여 안전한 곳에 보관


4.2 보호와 보안

4.2.1 보호(Protection)

    (1) 보호 - 컴퓨터 시스템에 의하여 정의된 자원에 대하여 프로그램, 프로세스, 사용자의 접근을

               제어하는 기법

        1) 보호의 이유

           - 사용자가 자원에 대한 접근 제한을 의도적으로 위반하는 것을 방지

           - 시스템 내에서 동작중인 각 프로그램 요소가 시스템 자원의 정해진 사용정책대로 자원들을 

             사용하도록 보장

           - 시스템의 자원들이 무자격 사용자에 의하여 잘못 사용되는 것을 방지

        2) 보호영역

           - 한 프로세스는 하나의 보호영역에서만 동작하며 보호영역은 프로세스가 접근 가능한 자원을

              의미

           - 하나의 영역은 접근권한의 집합이고 접근권한은 어떤 프로세스가 객체에 대한 조작을 수행할

              수 있는 능력

    (2) 보호기법과 정책

        1) 보호기법

           - 접근제어, 이름부여(naming), 암호화(password), 해독화(cryptography), 사용자 인증

        2) 접근행렬에 의한 보호기법

           ① 전역 테이블(global table)

               - 접근행렬의 가장 단순한 구현으로 3개의 순서쌍<영역, 객체, 권한집합>들의 집합으로 구성

               - 주기억 공간에 보관 시 기억장소 낭비

               - 보조기억 장치로부터 추가적 입출력 필요

           ② 접근제어 리스트(access control list)

               - 접근행렬의 각 객체와 열을 결합하여 <영역, 권한집합>의 순서쌍을 갖는 접근 리스트로 

                 표현하는 방법

           ③ 권한 리스트(capability list) - 객체와 그 객체에 허용된 조작 리스트

           ④ Lock-Key 기법 - 접근제어리스트와 권한리스트의 절충

                             - 각 객체는 lock이라 불리는 유일한 비트 패턴 리스트를 갖고 각 영역은

                                key라는 독특한 비트열을 가지고 있다

                             - 수행중인 프로세스는 해당 영역이 객체의 lock과 일치하는 key가

                                있을 때 만 그 객체에 접근


4.2.2 보안(Security)

    (1) 개요

        1) 보안이란?

           - 컴퓨터 시스템 내에 저장된 프로그램과 데이터에 대하여 통제된 접근 방식을 어떻게 제공할

             것인가를 다루는 문제

           - 적절한 보호 시스템뿐만 아니라 시스템이 동작하는 외부 환경에 대해서도 고려

           - 시스템과 시스템 데이터가 결함 없이 보존

           - 정의된 자원에 대해 프로세스 또는 사용자의 접근을 제어

        2) 종류

           ① 외부보안 - 불법 침입자나 천재지변으로부터 시스템을 보호

             - 시설보안 : 감지기능을 통해 외부 침입자나 천재지변으로부터의 보안

             - 운용보안 : 시스템운영자, 관리자, 경영자들의 정책과 통제절차를 통해 이루어지는 보안

           ② 내부보안 - 하드웨어나 운영체제의 내장된 보안 기능을 통해 신뢰성을 유지

           ③ 사용자 인터페이스 보안 - 사용자의 신원을 운영체제가 확인하는 절차를 통해 불법 

                                       침입자로부터 시스템을 보호

     (2) 보안의 위험을 줄이는 방법

         1) 모니터 기법

            - 허락한다는 신호가 나오면 감시 프로그램이 그 파일을 액세스하고 그 결과를

               사용자 프로그램에 알려준다.

         2) 위험감시 기법

            - 중요한 작업에 대한 제어권을 사용자가 직접 갖지 못하게 하고 운영체제가 갖는 방법

            - 사용자는 운영체제에 요구만 한다.


제5장 분산 운영체제

5.1 개념 및 특징

    (1) 분산처리 시스템(distribute processing system)

        1) 분산처리 시스템이란? - 중앙으로부터 분산되어있는 컴퓨터로 모든 데이터의 처리 작업을 

                                  수행하여 그 결과를 상호 교환하도록 연결되어 있는 시스템

        2) 장점

           ① 제한된 자원의 공유 가능

           ② 시스템의 능력에 비해 업무량이 과중되어도 시스템을 바꿀 필요가 없다

           ③ 업무량 증가에 따라 컴퓨터를 네트워크에 투입하여 시스템의 성능을 향상

           ④ 하나의 컴퓨터가 고장시에도 다른 컴퓨터가 작업을 계속 수행하므로 작업에 대한 신뢰도를 

              높일 수 있다

           ⑤ 한 작업을 병렬로 처리하므로 전체적인 처리율(throughput)을 향상 시킨다

        3) 단점

           ① 분산처리 시스템에 투입되는 컴퓨터 비용 및 시스템의 구축이 쉽지 않다

           ② 여러 시스템간의 호환성을 고려하여 표준을 정해야 한다

    (2) 일반적인 형태

      1) 서브시스템을 중심으로 여러 노드들이 연결되어 있으며 각 노드에는 단말기가 설치 

      2) 통신서브 시스템 - 노드들 사이의 통신을 연결해주는 시스템으로 LAN, WAN


5.2 분산 운영체제

5.2.1 분산처리 시스템의 개발동기

        1) 자원공유(resource sharing)

           - 서로 다른 기능을 가진 많은 수의 사이트들이 서로 연결되어 있다면 한 사이트의 사용자는 

             다른 사이트의 이용 가능한 자원을 사용할 수 있다

        2) 연산속도 향상(computation speed-up)

           - 특정 연산이 동시에 수행 가능한 부분 연산들로 분할될 수 있다면 이들 연산들을 여러

             사이트에 분산시켜 연산 속도를 높일 수 있다

        3) 신뢰성(reliability)

           - 분산체제 내에서 한 사이트가 고장이 발생해도 나머지 사이트들은 계속 동작

        4) 통신(communication)

           - 다수의 사이트가 통신 네트워크를 통해 서로 연결되었을 때는 다른 사이트에 있는 사용자들이 

             정보를 서로 교환할 수 있다.

   * 분산 운영체제 구성동기(설계 이유) 기출95

      - 신뢰성 향상, 작업의 신속한 처리, 여러 자원들의 공유, DB의 공동 이용, 통신 이용


5.2.2 분산처리 시스템의 형태

    (1) 프로세서 모델에 따라

        1) 클라이언트-서버 모델 - LAN을 기본으로 구성되며 응용 프로그램이 사용자의 워크스테이션이나 

                                  PC 환경에서 수행

        2) 프로세서 풀(pool) 모델 - 응용프로그램들이 프로세서 서비스로서 관리되는 컴퓨터에서 수행

        3) 혼합모델 - 사용자의 요구와 자원처리가 매칭 된다

    (2) 위상(topology)에 의한 분류

        1) 완전 연결형 - 각 노드가 시스템내의 모든 다른 노드와 직접 연결된 상태이며 노드 및 회선에 

                         대한 비용 증가는 노드수의 제곱에 비례

                       - 전송속도가 빠르고 신뢰성이 높으나 비용이 많이 든다

        2) 부분 연결 구조 - 직접 연결되지 않은 노드가 존재하여 비용은 완전연결 구조보다 싸나 신뢰성은 

                            떨어진다

        3) 계층 구조형 = 트리 구조형 - 트리 형태로 연결되며 비용은 부분연결형보다 싸다

                                     - 부모노드가 고장나면 자식노드들은 통신이 두절

        4) 링(ring)형 = 환상형

           - 이웃 노드간의 단방향 및 양방향 통신이 가능하며 노드의 고장 발견이 쉽다

           - 보안 문제가 발생하며 새 노드 추가 시 통신회선을 절단해야하며 각 노드에서 전송지연 발생

        5) 성형(star) 구조

           - 각 노드들이 point-to-point 형태로 중앙 컴퓨터에 연결되고 중앙 컴퓨터를 경유하여 통신

           - 보수와 관리가 용이하고 노드의 고장이 다른 노드에 영향을 주지 않는다

           - 중앙컴퓨터 고장 시 전체 네트워크가 정지되며 통신망 전체가 복잡

        6) 버스(bus) 구조

           - 통신회선이 1개이므로 물리적 구조가 간단하고 노드의 추가와 삭제가 용이

           - 데이터 비밀 보장이 어렵고 통신회선의 길이에 제한이 있다

    (3) 분산 범위에 의한 분류

        1) WAN(wide area network) - 원거리 시스템을 연결하므로 통신속도가 느리고 신뢰성이 낮다

        2) LAN(local area network) - 근접 시스템을 연결하므로 속도가 빠르고 오류 발생률이 낮다

    (4) 운영체제 형태에 따른 분류

        1) 네트워크 운영체제(network operating system)

           - 각 노드가 독자적인 운영체제를 가지며 필요시 네트워크를 통해 통신

           - 설계와 구현이 쉽다

           - 자원의 공유가 번거롭고 프로세서의 운영체제가 모두 다를 때 곤란

        2) 분산 운영체제(distributed operating system)

          - 하나의 운영체제가 모든 네트워크, 프로세서 및 시스템내의 자원과 작업을 총괄

          - 사용이 편리하고 시스템간 자원공유가 쉽다

          - 설계와 구현이 어렵다


5.3 병렬처리 시스템(Parallel Processing)

5.3.1 병렬처리 시스템의 개요

    (1) 의미 - 다중처리 시스템에서 하나 또는 그 이상의 운영체제가 여러 개의 프로세서를 관리하며 동시에 

              수행하는 시스템

    (2) 병렬처리 시스템의 발전단계

        1) 1단계 - 단일 프로세서 컴퓨터에 병렬기법 도입

                 - RISC(reduced instruction set computers)

        2) 2단계 - 운영체제를 단일 컴퓨터의 운영에서 벗어나 복수의 연산소자 및 네트워크까지도 운영

                 - 알고리즘 기술 발달

        3) 3단계 - 병렬화를 묵시적으로 나타내는 새로운 언어의 개발 요구

        4) 4단계 - 사용자와 같은 레벨에서 통신할 수 있도록 높은 레벨의 사용자 인터페이스 제공


5.3.2 병렬 처리 시스템의 분류

    (1) Flyne에 의한 컴퓨터 구조의 분류

        1) SISD(Single Instruction stream Single Data stream)

           - 한번에 하나의 명령수행, 가장 일반적인 구조로 폰 노이만 방식

        2) SIMD(Single Instruction stream Multi Data stream)

           - SISD보다 빠르다, 배열처리기

        3) MISD(Multi Instruction stream Single Data stream)

           - 이론적일 뿐 실제 사용하지 않는다

        4) SISD(Multi Instruction stream Multi Data stream)

           - 진정한 의미의 병렬 프로세서(멀티 프로세서라고도 함)

    (2) 자료와 명령어의 흐름에 따른 병렬처리 시스템

        1) 파이프라인 - 하나의 프로세서를 서로 다른 기능을 가진 여러 개의 부 프로세서로 나누어

                         각 부 프로세서가 동시에 서로 다른 데이터를 취급하도록 하는 기법

                       - 한번에 여러 명령어가 실행되게 해서 성능을 향상시키는 방법

        2) 벡터(vector) - 벡터 명령어가 실행되면 벡터(피 연산자)의 각 항목들은 하나씩 파이프라인에 

                         나눠지고 파이프라인의 한 단계가 완성되는 동안 연기되는 기법

        3) 배열 처리기(array processor) - SIMD 컴퓨터로 한 배열의 각 항목에 동시에 같은 명령어를 수행

        4) 데이터 흐름 프로세서(data flow)

           - 많은 연산을 병렬적으로 수행하며 요구되는 데이터가 이용 가능한 명령어를 실행하기 때문에

             데이터 구동방식(data driven) 이라고 한다

        5) 다중 처리기(multiprocessor)

           - 기억장치나 데이터베이스 등의 자원을 공유하며 상호 작용하는 다중 프로세서들을 통하여

              비 동기적 병렬성을 얻는다

           - 2개 이상의 프로세서를 사용하므로 하나가 고장나더라도 다른 프로세서들은 가동할 수 있다

    (3) 기억장치 결합도에 따른 분류

        1) 강결합(tightly coupled)

           - 여러 프로세스가 하나의 저장장치를 공유하며 하나의 운영체제가 모든 프로세스들과 시스템

             하드웨어를 제어

           - 전송속도가 기억장치의 대역폭에 의해 결정

           - 공유 메모리를 차지하기 위한 프로세스간 경쟁이 치열

           - 결합 스위치(combining switch)로 프로세스간 경쟁 해결

        2) 약결합(loosely coupled)

           - 각 프로세스는 각자의 기억장치를 가지고 있다

           - 자체 운영체제를 갖고 있다

           - 프로세스간 통신은 메시지전달과 원격 프로시져 호출로 이루어진다

    (4) 연결방식에 따른 분류

        1) 공유버스(shared bus)

           - 프로세서, 기억장치 및 입출력 장치들간에 하나의 버스만 존재

           - 간단하며 경제적이고 융통성이 있다, 새로운 장치를 연결하기 쉽다.

           - 한번에 한가지 전송만 가능하고 버스에 이상이 생기면 전체 시스템이 중단

           - 시스템이 바빠지면 효율성이 저하된다

        2) 크로스바 교환행렬(crossbar-switch matrix)

           - 공유버스 구조에서 버스의 수를 기억장치의 수만큼 증가시킨 시스템

           - 모든 기억장치 모듈로 동시 전송이 가능

           - 하드웨어가 크고 복잡, 인터페이스는 간단

        3) 하이퍼 큐브(hypercube)

           - 비교적 경제적인 방법으로 많은 프로세서들을 연결하는 방법을 제공

           - 많은 노드가 연결될 경우 비용이 급속도로 증가

        4) 다단계 네트워크(multistage network) = 다중 입 출구 기억장치

           - 한 노드가 어떠한 다른 노드에라도 연결할 수 있도록 하여 여러 프로세서의 연결을 쉽게 한다

           - 교환기의 수가 매우 적으며 단일 경로지만 다양한 연결이 가능

           - 교환 네트워크의 비용을 증가시키며 전송 시간이 비교적 느리다

    (5) 다중처리 시스템의 운영체제 형태에 따른 분류

        1) 주/종 관계(master/slave)

           - 하나의 프로세서가 master로 지정되어 범용 프로세서로서 연산 및 입출력을 담당하고

             나머지들은 slave로 연산만을 담당하고 사용자 프로그램만 수행

           - 구현이 쉬우나 하드웨어의 비 대칭성이 발생하고 하드웨어를 최적으로 사용하지 못한다

        2) 분리수행(separate executives) 

           - 각 프로세서가 독립적으로 자원을 가지는 단일프로세서 시스템처럼 독자적인 운영체제와

             기능을 가지는 형태

           - 각 프로세서에서 발생하는 인터럽트는 해당 프로세서에서 해결

           - 주/종 관계보다 신뢰도가 높아 한 프로세서의 고장이 전체 시스템에 영향을 주지 못한다

           - 일부 프로세서가 유휴 상태로 될 수 있다

        3) 대칭처리

           - 모든 프로세서가 동등한 입장의 대칭성을 가지고 있으며 구현 및 수행이 매우 복잡한 형태

           - 가장 강력한 능력의 시스템

           - 한 운영체제를 동시에 수행할 수 있게 하므로 재진입 코드와 상호배제가 필요

           - 다른 기법에 비해 작업을 효과적으로 분산시킬 수 있다

           - 모든 프로세서들은 동등한 입장에서 입출력 장치와 기억장치를 사용

           - 기억장소를 여러 프로세스가 동시에 엑세스 하려할 경우 보통 하드웨어로 해결

           - 시스템 테이블을 여러 프로세스가 동시에 엑세스 하려할 경우 보통 소프트웨어로 해결

           - 신뢰도가 가장 높다.


제6장 운영체제의 실제

6.1 UNIX

6.1.1 기본 개념 기출95 기출96

     - UNIX 운영체제의 파일 시스템이 관리하고 있는 디렉토리 구조 : 다단계 트리구조

     - CPU 스케줄링 방식 : 기본 우선순위 지정 후에 우선순위 조정

     - I-node : 파일에 할당된 data list의 I번째 node를 의미

     - 파이프(pipe) : UNIX에서 프로세스간의 통신과 동기를 위해 사용

반응형

'연구개발 > Etc..' 카테고리의 다른 글

mac port kill  (0) 2024.01.31
[Docker] 생성 및 실행  (0) 2018.07.04
지표 관련 용어  (0) 2016.08.22
unity key  (0) 2016.05.07
RAID 1+0 과 0+1의 차이점  (0) 2011.07.11
반응형

[유저관련 지표]

  • UV (Unique visitor) : 일정기간 내에 게임의 접속(방문)한 실제 유저 수로 한 유저가 여러번 방문해도 1로 카운트 한다.

  • DAU (Daily Active User) : 일단위로 측정한 UV

  • WAU (Week Active User) : 주단위로 측정한 UV

  • MAU (Monthly Active User) : 월 단위로 UV 측정

  • RU (Registered User) : 일정기간내에 게임에 등록된 유저 수

  • NRU (New Registered User) : 일정기간내에 등록된 신규 유저 수.

  • ARU (Accumulate Register User): 해당 기간까지의 등록된 누적 유저 수

  • 재방문 UV : 해당 기간 동안 게임 클라이언트에 2회 이상 로그인한 회원 수

  • MUV (Multigame Unique Visitor): 해당 기간 동안 게임 클라이언트에 로그인하여 실제 게임을 플레이 한 회원 수

  • MTS (Mutigame Time Spent): 해당 기간 동안의 평균 실제 플레이 타임

  • TS(Time Spent) : 해당기간 동안의 유저1인당 플레이 타임

  • CCU (Concurrent User) : 특정 시점에 접속한 동시 접속자 수

  • MCU (Maxium Concurrent User) : 하루 동안 가장 높은 동시접속자 수치.

  • PCU (Peak Concurrent User) : MCU 동일어

  • ACU (Average Concurrent User) : 1일 동안의 평균 동시 접속자 수

  • Stickness : 고착도

  • EU (Executed User) : 인게임을 플레이한 유저로 UV와 같이 비교대상으로 분석

 

 

 [매출 관련 지표]

  • BU (Buying user) : 구매유저일정기간내에 게임에 아이템 구매월정액 결제 등 돈을 지불한 유저

  • PU (Paying User) : BU 동일어

  • BU rate = BU/UV (순방문자대비 결제 유저 비율)

  • CAC(Customer Acquisition Cost) : 유저 확보 비용으로 유저 1인을 확보하는데 소모되는 비용

  • CRC (Customer Retention Cost) : 유저 유지 비용으로 일정기간내에 유저1인을 유지하는데 소모되는 비용

  • ARPU (Average Revenue Per User) : 일정 기간 내 유저 1인당 평균 수입

  • ARPPU (Average Revenue Per Paying User) : 일정 기간내에 게임에 비용을 지불한 유저의 1인당 평균 수입

  • PPU (Percentage of Paying Users) : DAU 내에서 결제한 비율 또는 비율

  • LTV (Life time value) : 유저 1인당 게임에서 완전히 이탈할 때까지 지불하는 비용

  • Entry Cost : 여러 가지 가격대의 상품을 제공할 때 유저의 최초 구매가 어떤 가격대에서 많이 일어나는지 측정

  • Sales by Purchase : 사용자의 구매 활동을 통해 집계된 매출

  • Sales by Advertisement : 광고 노출을 통해 집계된 매출

  • CPI (Cost per Install) : 게임 다운로드 후 설치하면 보상

  • CPA (Cost per Action) : 설치된 앱을 실행하면 보상

  • CPP (Cost per Play) : CPA 이후 일정 기간 한번씩 실행할 때마다 보상

  • CPL (Cost per Level) : 정량적인 플레이에 대한 레벨을 설정한 뒤 보상

 

 

[투자 퍼블리싱 관련 용어]

MOU (Memorandum of understanding) : 투자 등 거래에 관해 합의한 사항을 명시한 사전 협의문서로 법적 구속력이 없으며 정식 계약 전 업무 준비/친선관계 개선/대외 홍보의 역할로 활용 한다.

Initial fee : 판권 제공/계약 체결 시 판권 부여를 대가로 수령하는 금액으로 흔히 계약금이라고 한다.

Running Royalty : 퍼블리셔가 개발사에게 매출액의 일정 비율을 지급하는 비용으로 러닝 개런티랑 동일하다.

MG(Minimum Guarantee) :  판권 제공자의 최소 러닝 로얄티를 보장해 주는 금액

RS (Revenue Share) : 판권제공사/퍼블리셔 간의 수익 분배 비율

PF (Project Financing) : 회사 지분에 대한 투자가 아닌 프로젝트 성공 수익에 대해 투자하는 투자 방식

KPI(Key Performance Indicator) : 핵심실행지표로 기업이나 조직의 목표달성과 전략을 위한 핵심측정지표

 

 

[참고자료]

http://blog.naver.com/minopie/220362749342

 

 

용어는 업계마다 약간씩 다르지만 의미는 거의 유사하기 때문에 정리된 내용을 알아두면 많은 도움이 되리라 생각한다앞으로 포스팅 예정인 게임 통계 내용도 정리된 용어를 기반으로 설명한다.

 

 

 

게임마케팅게임용어마케팅 용어게임기획게임 분석게임이야기마케팅이야기동시접자수재방문율결제유저, ARPU, ARPPU, DAU, NU, UV, PV MCU, PCU, CCU


반응형

'연구개발 > Etc..' 카테고리의 다른 글

[Docker] 생성 및 실행  (0) 2018.07.04
운영체제 개론  (0) 2017.05.29
unity key  (0) 2016.05.07
RAID 1+0 과 0+1의 차이점  (0) 2011.07.11
윈도우 보안취약점 보완 강화  (0) 2011.05.04
반응형

R3-EERM-DWN7-GFWT-ZA47-RD2P

반응형

'연구개발 > Etc..' 카테고리의 다른 글

운영체제 개론  (0) 2017.05.29
지표 관련 용어  (0) 2016.08.22
RAID 1+0 과 0+1의 차이점  (0) 2011.07.11
윈도우 보안취약점 보완 강화  (0) 2011.05.04
페이스북 소셜 앱 개발 가이드 2011  (0) 2011.03.28
반응형

RAID 1+0 = RAID 10
과 
RAID 0+1 의 차이점


RAID 0 : striping
RAID 1 : mirroring

즉, RAID 1+0 은 각각 미러링 한 볼륨을 스트라이핑 한 것이고
RAID 0+1 은 스트라이핑한 볼륨 두개를 서로 미러링 한 것이다.


공통점
1. 가용량이 같다.
2. 속도가 같다.


다른점
1. 볼륨이 깨지는 조건
2. 볼륨 재구성하는 방법

 




1. 볼륨이 깨지는 조건
그림에서 보면 RAID 1+0과 0+1의 차이점을 알 수 있는데,
RAID 0+1의 경우 1번과 5번 디스크가 동시에 나갈경우 전체볼륨이 깨진다.

RAID 1+0의 경우 1번과 5번이 동시에 나가더라도 볼륨이 깨지지 않는다.
하지만 1+0의 경우라도 1번과 2번이 동시에 나가면 역시 볼륨이 깨진다.

그렇지만 0+1의 경우보다는 1+0의 경우가 깨질 확률에 있어서 더 낮으므로
상대적으로 1+0이 안정성이 높다고 할 수 있다.


2. 볼륨을 재구성 하는 방법
그림에서 0+1의 경우,
1번 디스크가 깨진경우 디스크를 갈아 끼웠을때, 복구는
2번RAID0 전체를 1번RAID0 로 복사한다. 즉, 디스크 4개 분량을 복사한다.

하지만 1+0의 경우,
1번 디스크가 깨진경우 디스크를 갈아 끼웠을때, 복구는
2번 디스크에서 1번 디스크로 디스크 1개만 복사한다.

여러모로 0+1보다는 1+0이 좋다고 할 수 있다.

반응형
반응형

1. 계정 잠금 임계값 설정

위험도 :
취약점 개요 : 로그온 실패 횟수를 제한하면 보안이 강화됨
취약점 영향 : Brute force에 의한 지속적인 계정 공격의 위험
대응책 :
- 시작>실행>SECPOL.MSC>계정 정책>계정 잠금 정책
-“계정 잠금 임계값”을 5번 설정

 

2. 패스워드 복잡도

위험도 :
취약점 개요 : 패스워드의 복잡도에 따른 유추 가능성 확인
취약점 영향 : 비 인가자에 의한 접근 가능성 존재
대응책 :
1. 시작>실행>SECPOL.MSC>계정 정책>암호정책
2. “암호는 복잡성을 만족해야 함” 을 “사용” 으로 설정

 

 

3. 사용자 최근암호 기억

위험도 :
취약점 개요 : 암호를 다시 사용하는 것을 금지하지 않거나 적은 수의 암호를 계속해서 다시 사용할 수 있도록 허용하면 좋은 암호 정책의 효과가 크게 반감됨
취약점 영향 : 취약한 계정을 통해 계정 권한이 도용당할 수 있음.
대응책 :
1. 시작>실행>SECPOL.MSC>암호 정책                
2. “최근 암호 기억”을 12번으로 설정

 

 

4. 패스워드 최소 길이
위험도 :
취약점 개요 : 대부분의 환경에서 8자리의 암호를 사용하면 적절한 보안이 제공될 뿐만 아니라 사용자가 쉽게 기억할 수 있으며 무작위 공격을 적절히 방어할 수 있음
취약점 영향 : 취약한 계정을 통해 계정 권한이 도용당할 수 있음.
대응책 :
1. 시작>실행>SECPOL.MSC>암호 정책                 
2. “최소 암호 길이”을 8문자 설정

 

 

 

5. 디폴트 Administrator 계정명 사용
위험도 :
취약점 개요 : Administrator 계정은 로그온시 실패해도 접근차단하지 않으므로 Brute force 공격에 노출될 수 있음
취약점 영향 : 관리자 권한 획득 및 행사
대응책 :
1. 시작>실행>SECPOL.MSC>보안옵션
2. "Administrator 계정 이름 바꾸기"를 선택하여 이름 변경

 

 

6. 하드디스크 기본 공유 제거
위험도 :
취약점 개요 : 드라이브의 디폴트 공유를 통해 비인가자가 접속할 가능성이 존재함
취약점 영향 : 시스템 권한 획득 및 행사
대응책 :
1. 시작>실행>FSMGMT.MSC>공유>기본공유 선택>공유 중지                                              
 2. 시작>실행>REGEDIT>아래 레지스트리 값을 0 으로 수정(키 값이 없을 경우 새로 생성 DWORD) "HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters\AutoShareServer(Windows NT 일 경우 : AutoShareWks)

 

 

7. 불필요한 ODBC 데이터소스 드라이브 제거
위험도 :
취약점 개요 : 불필요한 ODBC 데이터 소스나 드라이버를 통한 비인가자의 접속 가능성 존재
취약점 영향 : 비인자가에 의한 데이터베이스 접속 및 자료 유출 가능성
대응책 :
1. 시작>실행>Odbccp32.cpl>시스템DSN>해당 드라이브 클릭                      
2. 사용하지 않는 데이터 소스 제거

 


8. TELNET 서비스
위험도 :
취약점 개요 : Telnet 사용 시 데이터가 평문으로 전송되므로 비인가자에 의한 스니핑에 노출됨
취약점 영향 : 비 인가자의 의한 스니핑 가능성
대응책 :
1. 시작>설정>제어판>관리도구>텔넷서버설정
2. NTLM인증방식만 사용

 

 

9. SMTP 서비스
위험도 :
취약점 개요 : SMTP 릴레이 설정 및 필요성 확인
취약점 영향 : 스팸 릴레이 가능성 존재
대응책 :
SMTP 서비스를 사용하지 않으면 SMTP 서비스를 중지시키기를 권고함

 

 

10. SNMP 서비스
위험도 :
취약점 개요 : MIB(관리되어야 할 자원 객체의 분류 정보)의 데이타를 주고받기 위해서 OID번호를 이용하는데, OID번호가 일치할 시 데이타 정보를 획득할수 있음
취약점 영향 : SNMP 서비스를 구동할 경우 MIB 정보가 노출될 가능성이 있음
대응책 :
SNMP 서비스를 사용하지 않으면이면 SNMP 서비스를 중지시키기를 권고함

 

 

11. 이벤트 뷰어
위험도 :
취약점 개요 : 로그파일(응용 프로그램, 보안, 시스템) 크기가 10M 이상 90일로 충분하게 설정되어 있는지 확인
취약점 영향 : 설정 미흡 시 비인가자의 접근에 대한 증거가 남지 않음
대응책 :
1. 시작>실행>EVENTVWR.MSC>해당 로그>속성>일반
2. “최대 로그 크기”->10240, “최대 로그 크기에 미쳤을 때”-> 90

 

 

12. 개체 액서스 감사
위험도 :
취약점 개요 : [시작] - [프로그램] - [관리도구] - [로컬보안정책] - [로컬정책] 의 각 항목의 로컬설정이 "감사없음"이면 보안상 취약하다
취약점 영향 : 감사 설정 미흡 시 침해여부 확인이 어려울 수 있음
대응책 :
1. 시작>실행>SECPOL.MSC>로컬정책>감사정책
2. "개체 액서스"항목 "성공, 실패" 둘다 설정

 

 

13. Null Session 설정
위험도 :
취약점 개요 : Windows에서는 익명 사용자가 네트워크 공유 및 도메인 계정의 이름 열거와 같은 특정 작업을 수행할 수 있음.
C:\> net use \\[IP]\IPC$””/user:”” → null command
익명의 사용자로부터 네트워크 접근이 불가능하도록 설정
취약점 영향 : Null Session을 사용한 비인가자의 접근 가능성이 존재
대응책 :
1. 시작>실행>SECPOL.MSC>로컬정책>보안옵션
2. SAM 계정과 공유의 익명 열거 허용 안 함”, SAM 계정의 익명 열거 허용 안 함” 에 각각 “사용” 을 선택

 

 

14. 레지스트리 보호
위험도 :
취약점 개요 : 환경설정 정보가 저장된 레지스트리에 대한 보호 설정여부 점검
취약점 영향 : 레지스트리 변조로 인한 시스템 파괴 등
대응책 :
1. 시작>실행>SERVICES.MSC>remote registry>속성2. “시작유형”->사용안함, 서비스 상태->중지

 

 


15. 안전한 파일 및 프린터 공유 인증
위험도 :
취약점 개요 :
LAN Manager 인증 수준정책은 네트워크 로그온에 사용할 Challenge/Response 인증 프로토콜을 결정 하고 네트워크를 통한 파일 및 프린터 공유 등과 같은 작업시 인증을 담당함. 보다 안전한 인증을 위해 NTLMv2 를 사용하는 것이 좋음
취약점 영향 :
파일 및 프린터 공유 시 암호 재생 공격 가능성 있음
대응책 :
1. 시작>실행>SECPOL.MSC>로컬 정책>보안옵션 
2. LAN Manager 인증 수준” 정책에 “NTLMv2 응답만 보냄” 을 설정

 

 


16. Everyone사용권한을 익명 사용자에게 적용안함
위험도 :
취약점 개요 : 비 인자가의 Everyone 권한을 통한 시스템 침투 및 공격 가능성 확인
취약점 영향 : 비 인가자에 의한 접근 가능성 존재
대응책 :
1. 시작>실행>SECPOL.MSC>로컬 정책>보안옵션
2. everyone 사용 권한을 익명 사용자에게 적용” 정책이 “사용안함” 으로 설정

 

 

17. 화면보호기 설정
위험도 :
취약점 개요 : 화면 보호기 및 패스워드 설정여부 확인
취약점 영향 : 비 인가자에 의한 시스템 접근
대응책 :
스크린 세이버 적용 혹은 잠김 상태 유지가 되는지 확인.
“암호 사용” 설정, “대기 시간” 5분 권장

 

 

18. 방화벽 사용
위험도 :
취약점 개요 : 비인가 침투 시도를 막기위한 방화벽 설정여부 확인
취약점 영향 : 비 인가자에 의한 시스템 접근 및 이용
대응책 :
사용자의 컴퓨터의 방화벽을 활성화 시킨다.
1. “제어판 – 네트워크 연결”을 클릭한다.
2. “로컬 영역 연결”에서 오른쪽 단추를 눌러 “속성”을 클릭한다.
3. 속성의 고급 탭에 “인터넷 방화벽 설정”을 클릭한다.
4. 인터넷 방화벽 설정의 일반 탭에서 방화벽 “사용”을 체크한다.

 

 

19. 마지막 로그온 사용자 계정 숨김
위험도 :
취약점 개요 : 최종 사용자의 아이디 표시 여부 확인
취약점 영향 : Brute force에 의한 지속적인 계정 공격의 위험
대응책 :
1. 시작>실행>SECPOL.MSC>로컬정책>보안옵션
2. “대화형 로그온 : 마지막 사용자 이름 표시 안 함” 을 사용으로 설정

 

 


20. 로컬 로그온 설정
위험도 :
취약점 개요 : 대화형 로그온 할 수 있는 사용자를 결정하여 로그인시 연결된 키보드에서 <ctrl+Alt+Del>을 누른 이후에 로그온을 할 수 있게 함.
취약점 영향 : <ctrl+Alt+Del>을 눌러 로그온 창을 띄우는 경우 인증된 로그온 창을 띄울 수 있음
대응책 :
1. 시작>실행>SECPOL.MSC>로컬 정책>보안옵션
2. “대화형 로그온:[ctrl+Alt+Del]” 정책에 “사용안함”으로 설정

 

 


21. 사용자 디렉토리 접근 제한
위험도 :
취약점 개요 : 다른 사용자의 홈 디렉터리 접근 가능성
취약점 영향 : 비 인가자에 의한 파일 위/변조 등
대응책 :
1. C:\Documents and Settings\사용자 홈디렉터리>속성>보안                                             
2. Everyone 권한 제거(All Users, Default User 디렉터리는 제외)

 

 


22. AutoLogon 허용여부
위험도 :
취약점 개요 : 비인가자가 레지스트리를 통해 로그인 계정 및 암호를 확인할 수 있음
취약점 영향 :
비 인가자에 의한 시스템 정보 유출
대응책 :
1. 시작>실행>       REGEDIT>HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon
2. AutoAdminLogon 값을 0으로 세팅.
3. DefaultPassword 엔트리가 존재한다면 삭제


반응형
반응형

http://www.slideshare.net/usefulparadigm/010218?from=ss_embed
반응형
반응형

HTTP API의 오류 로깅

기술 자료 ID : 820729
마지막 검토 : 2005년 9월 16일 금요일
수정 : 5.0

요약

이 문서에서는 HTTP(하이퍼텍스트 전송 프로토콜) API의 오류 로깅 기능을 설명합니다.

HTTP 기반 응용 프로그램에서 발생하는 오류 중 일부는 처리를 위해 응용 프로그램으로 다시 전달되는 대신 HTTP API에서 자동으로 처리됩니다. 이 동작은 이러한 오류가 너무 많이 발생하여 이렇게 하지 않으면 이벤트 로그나 응용 프로그램 처리기에서 다룰 수 있는 범위를 초과하기 때문에 발생합니다.

아래의 항목은 HTTP API 오류 로깅의 다양한 측면에 대해 설명합니다.
HTTP API 오류 로깅 구성
레지스트리 설정은 HTTP API 로그 오류, 허용되는 최대 로그 파일 크기 및 로그 파일 위치를 제어합니다.
HTTP API 오류 로그 형식
HTTP API는 W3C(World Wide Web Consortium) 로그 파일 규칙을 준수하는 로그 파일을 만듭니다. 따라서 표준 도구를 사용하여 이 로그 파일을 구문 분석할 수 있습니다. 그러나, W3C 로그 파일과 달리 HTTP API 로그 파일에는 열 이름이 없습니다.
HTTP API가 기록하는 오류 유형
HTTP API는 다양한 일반 오류를 기록합니다.

위로 가기

추가 정보

HTTP API 오류 로깅 구성

HTTP \Parameters 키의 세 가지 레지스트리 값이 HTTP API 오류 로깅을 제어합니다. 이들 키는 다음 레지스트리 키에 있습니다.
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters
참고 이후 버전의 Microsoft Windows 운영 체제에서는 구성 값의 위치와 형식이 바뀔 수 있습니다.

레지스트리 값을 변경하고, 이들이 포함되어 있는 로그 파일과 폴더를 보거나 수정하려면 Administrator/Local System 자격 증명이 있어야 합니다.

레지스트리 값의 구성 정보는 HTTP API 드라이버가 시작될 때 읽혀집니다. 따라서 설정을 변경한 경우에 새 값을 읽으려면 드라이버를 중지했다가 다시 시작해야 합니다. 이렇게 하려면 다음 콘솔 명령을 입력하십시오.
net stop http
net start http
로그 파일의 이름을 지정하는 데 다음과 같은 명명 규칙이 사용됩니다.
httperr + sequence number + .log
예: httperr4.log
로그 파일은 ErrorLogFileTruncateSize 레지스트리 값에서 지정하는 최대 크기에 도달하면 새로 작성됩니다. 최대 크기는 1MB 이상이어야 합니다. 

오류 로깅의 구성이 올바르지 않거나, HTTP API가 로그 파일에 기록하는 동안 오류가 발생하면 HTTP API는 이벤트 로깅을 사용하여 오류 로깅이 발생하지 않음을 관리자에게 알립니다.

아래의 표는 레지스트리 구성 값을 설명합니다. 

레지스트리 값 설명
EnableErrorLogging TRUE로 설정하면 오류 로깅을 사용 가능하게 설정하고 FALSE로 설정하면 오류 로깅을 해제할 수 있는DWORD. TRUE가 기본값입니다.
ErrorLogFileTruncateSize 오류 로그 파일의 최대 크기를 바이트 단위로 지정하는 DWORD. 기본값은 1MB(0x100000)입니다. 

참고 기본값보다 작은 값은 지정할 수 없습니다.
ErrorLoggingDir HTTP API가 해당 로깅 파일을 저장하는 폴더를 지정하는 문자열. 

HTTP API는 지정된 폴더에서 HTTPERR이라는 하위 폴더를 만들어서 여기에 로그 파일을 저장합니다. 이 하위 폴더와 로그 파일은 같은 권한 설정을 받습니다. Administrator 및 Local System 계정은 모든 권한을 갖습니다. 그 밖의 다른 사용자는 액세스할 수 없습니다.

다음은 레지스트리에서 폴더를 지정하지 않은 경우에 사용되는 기본 폴더입니다.
%SystemRoot%\System32\LogFiles 

참고 ErrorLoggingDir 문자열 값은 정규화된 경로여야 합니다. 그러나, %SystemRoot%를 포함할 수도 있습니다.

위로 가기

HTTP API 오류 로그 형식

일반적으로 HTTP API 오류 로그 파일은 열 머리글이 없다는 점을 제외하고 W3C 오류 로그와 같은 형식을 갖고 있습니다. HTTP API 오류 로그 파일은 각 행에 하나씩 오류를 기록합니다. 필드가 특정 순서로 나타납니다. 단일 공백 문자(0x0020)가 각 필드를 이전 필드와 분리합니다. 각 필드에서 공백 문자, 탭 및 인쇄할 수 없는 제어 문자 대신 더하기 기호(0x002B)가 표시됩니다.

아래의 표는 오류 로그 레코드에서 필드와 이들 필드의 순서를 나타냅니다.

필드 설명
날짜 날짜 필드는 W3C 형식을 따릅니다. 이 필드는 UTC(Coordinated Universal Time)를 기준으로 합니다. 날짜 필드는 항상 YYYY-MM-DD 형식으로 된 10개의 문자입니다. 예를 들어, 2003년 5월 1일은 2003-05-01로 표시됩니다.
시간 시간 필드는 W3C 형식을 따릅니다. 이 필드는 UTC를 기준으로 합니다. 시간 필드는 항상 MM:HH:SS의 형식으로 된 8개의 문자입니다. 예를 들어, 오후 5시 30분(UTC)은 17:30:00으로 표시됩니다.
클라이언트 IP 주소 영향을 받는 클라이언트의 IP 주소입니다. 이 필드의 값은 IPv4 주소나 IPv6 주소 중 하나가 될 수 있습니다. 클라이언트 IP 주소가 IPv6 주소인 경우 ScopeId 필드도 주소에 포함됩니다.
클라이언트 포트 영향을 받는 클라이언트의 포트 번호입니다.
서버 IP 주소 영향을 받는 서버의 IP 주소입니다. 이 필드의 값은 IPv4 주소나 IPv6 주소 중 하나가 될 수 있습니다. 서버 IP 주소가 IPv6 주소인 경우 ScopeId 필드도 주소에 포함됩니다.
서버 포트 영향을 받는 서버의 포트 번호입니다.
프로토콜 버전 사용 중인 프로토콜의 버전입니다.

프로토콜 버전을 확인할 수 있도록 구문 분석되지 않은 연결에는 하이픈(0x002D)이 빈 필드에 대한 자리 표시자로 사용됩니다.

구문 분석된 주 버전 번호나 부 버전 번호가 10 이상인 경우에는 버전이 HTTP/?.?로 기록됩니다.
동사 마지막으로 구문 분석된 요청이 전달하는 동사 상태입니다. 알 수 없는 동사가 포함되지만, 255바이트를 초과하는 동사는 이 길이로 잘립니다. 동사를 사용할 수 없는 경우에는 하이픈(0x002D)이 빈 필드에 대한 자리 표시자로 사용됩니다.
CookedURL + 쿼리 URL과 이 URL과 연관된 쿼리는 물음표(0x3F)로 분리된 하나의 필드로 기록됩니다. 이 필드는 4096바이트의 길이 제한에서 잘립니다.

이 URL이 구문 분석("cooked")된 경우 로컬 코드 페이지 변환에서 기록되어 유니코드 필드로 처리됩니다.

이 URL이 로깅 시 구문 분석("cooked")되지 않은 경우 유니코드 변환 없이 정확하게 복사됩니다.

HTTP API가 이 URL을 구문 분석하지 못하면 하이픈(0x002D)이 빈 필드에 대한 자리 표시자로 사용됩니다.
프로토콜 상태 프로토콜 상태는 999를 초과할 수 없습니다.

요청에 대한 응답의 프로토콜 상태가 사용 가능한 경우 이 필드에 기록됩니다.

프로토콜 상태가 사용 불가능한 경우에는 하이픈(0x002D)이 빈 필드에 대한 자리 표시자로 사용됩니다.
사이트 ID 이 버전의 HTTP API에서는 사용되지 않습니다. 이 필드에는 자리 표시자 하이픈(0x002D)이 항상 나타납니다.
원인 문구 이 필드에는 기록 중인 오류의 유형을 나타내는 문자열이 나와 있습니다. 이 필드는 빈 상태로 있을 수 없습니다.
대기열 이름 이것은 요청 대기열 이름입니다.

아래의 예제 행은 HTTP API 오류 로그에서 가져온 것입니다.
2002-07-05 18:45:09 172.31.77.6 2094 172.31.77.6 80 HTTP/1.1 GET /qos/1kbfile.txt 503 ? ConnLimit 2002-07-05 19:51:59 127.0.0.1 2780 127.0.0.1 80 HTTP/1.1 GET /ThisIsMyUrl.htm 400 ? Hostname 2002-07-05 19:53:00 127.0.0.1 2894 127.0.0.1 80 HTTP/2.0 GET / 505 - Version_N/S 2002-07-05 20:06:01 172.31.77.6 64388 127.0.0.1 80 - - - - - Timer_MinBytesPerSecond

위로 가기

HTTP API가 기록하는 오류 유형

HTTP API는 잘못 처리된 클라이언트에 대한 오류 응답, 연결 시간 초과, 고아 요청 및 삭제된 연결을 기록합니다.

아래의 목록은 HTTP API가 기록하는 오류 유형을 나타냅니다.
클라이언트에 대한 응답 HTTP API는 클라이언트에 대한 오류 응답(예: 마지막으로 받은 요청에서 구문 분석 오류로 인해 발생한 400 오류)을 보냅니다. HTTP API는 오류 응답을 보낸 후 연결을 종료합니다.
연결 시간 초과 HTTP API가 연결 시간을 초과합니다. 연결 시간이 초과될 때까지도 요청이 계속 보류 중이면 이 요청은 오류 로그에서 연결에 대한 자세한 정보를 제공하는 데 사용됩니다.
고아 요청 대기열에 사용자 모드 프로세스로 라우팅되는 요청이 아직 남아 있을 때 프로세스가 예기치 않게 종료됩니다. HTTP API는 오류 로그에 고아 요청을 기록합니다.
특정 오류 형식은 항상 각 오류 행의 마지막 필드로 나타나는 원인 문구 문자열에서 지정됩니다. 아래의 표는 HTTP API 원인 문구를 나타냅니다.

원인 문구

 

설명

AppOffline "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 응용 프로그램 오류로 인해 응용 프로그램이 오프라인 상태가 되었기 때문에 서비스를 사용할 수 없습니다.
AppPoolTimer "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 응용 프로그램 풀 프로세스가 사용 중이어서 요청을 처리할 수 없기 때문에 서비스를 사용할 수 없습니다.
AppShutdown "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 응용 프로그램이 관리자 정책에 대한 응답으로 자동으로 종료되기 때문에 서비스를 사용할 수 없습니다.
BadRequest 요청을 처리하는 동안 구문 분석 오류가 발생했습니다.
Connection_Abandoned_By_AppPool 핸들을 닫아서 보류 중인 요청의 연결을 끊거나 예기치 않게 종료된 응용 프로그램 풀의 작업자 프로세스
Connection_Dropped 예약됨. 현재 사용되고 있지 않습니다.
ConnLimit "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 사이트 수준 연결 한계에 도달했거나 초과했기 때문에 서비스를 사용할 수 없습니다.
Connections_Refused 커널 NonPagedPool 메모리가 20MB 아래로 떨어지고 http.sys가 새 연결 수신을 중단했습니다.
Disabled "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 관리자가 응용 프로그램을 오프라인 상태로 만들었기 때문에서 서비스를 사용할 수 없습니다.
EntityTooLarge 엔터티가 허용된 최대 크기를 초과했습니다.
FieldLength 필드 길이 한계를 초과했습니다.
Forbidden 구문 분석 동안 금지된 요소나 시퀀스가 발생했습니다.
Header 머리글에서 구문 분석 오류가 발생했습니다.
Hostname 호스트 이름을 처리하는 동안 구문 분석 오류가 발생했습니다.
Internal 내부 서버 오류가 발생했습니다(HTTP 오류 500).
Invalid_CR/LF 잘못된 캐리지 리턴이나 줄 바꿈이 발생했습니다.
LengthRequired 필수 길이 값이 없습니다.
N/A "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 메모리 할당 실패 같은 내부 오류가 발생했기 때문에 서비스를 사용할 수 없습니다.
N/I 알 수 없는 전송 인코딩으로 인해 "구현되지 않음" 오류가 발생했거나(HTTP 오류 501), "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503).
Number 숫자를 처리하는 동안 구문 분석 오류가 발생했습니다.
Precondition 필수 전제 조건이 없습니다.
QueueFull "서비스 사용할 수 없음" 오류가 발생했습니다(HTTP 오류 503). 응용 프로그램 요청 대기열이 꽉 찼기 때문에 서비스를 사용할 수 없습니다.
RequestLength 요청 길이 한계를 초과했습니다.
Timer_AppPool 서버 응용 프로그램이 대기열에서 가져와 요청을 처리할 때까지 요청이 응용 프로그램 풀 대기열에서 너무 오랫 동안 대기했기 때문에 연결이 만료되었습니다. 이 제한 시간은ConnectionTimeout입니다. 기본적으로 이 값은 2분으로 설정됩니다.
Timer_ConnectionIdle 연결이 만료되어 계속 유휴 상태로 있습니다. 기본 ConnectionTimeout 시간은 2분입니다.
Timer_EntityBody 요청 엔터티 본문이 도착하기 전에 연결이 만료되었습니다. 요청에 엔터티 본문이 있는 경우 HTTP API는 Timer_EntityBody 타이머를 켭니다. 처음에는 이 타이머의 제한이 ConnectionTimeout값(보통 2분)으로 설정됩니다. 이 요청에서 다른 데이터 표시가 수신될 때마다 HTTP API는 타이머를 재설정하여 연결에 추가적인 2분(또는 ConnectionTimeout에 지정된 시간)을 더 제공합니다.
Timer_HeaderWait 요청에 대한 머리글 구문 분석을 수행하는 데 기본 제한인 2분보다 많이 소요되었기 때문에 연결이 만료되었습니다.
Timer_MinBytesPerSecond 클라이언트가 적절한 속도로 응답을 받지 못했기 때문에 연결이 만료되었습니다. 응답 전송 속도가 기본값인 240바이트/초보다 느렸습니다.
Timer_Response 예약됨. 현재 사용되고 있지 않습니다.
URL URL을 처리하는 동안 구문 분석 오류가 발생했습니다.
URL_Length URL이 허용되는 최대 크기를 초과했습니다.
Verb 동사를 처리하는 동안 구문 분석 오류가 발생했습니다.
Version_N/S 지원되지 않는 버전 오류가 발생했습니다(HTTP 오류 505).

 

 

출처 : MS ( http://support.microsoft.com/kb/820729/ko#appliesto )

반응형

'연구개발 > Etc..' 카테고리의 다른 글

윈도우 보안취약점 보완 강화  (0) 2011.05.04
페이스북 소셜 앱 개발 가이드 2011  (0) 2011.03.28
자동 링크걸기 함수  (0) 2010.03.16
사이트 주소 추출  (0) 2010.03.16
LINQ정리분  (0) 2009.09.06
반응형
<%
function AutoLink(text)
  Dim regEx
 
  Set regEx = New RegExp
  
  regEx.Pattern = "((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"
  regEx.IgnoreCase = True
 regEx.Global = True
 
  AutoLink = regEx.Replace(text, "<a href='$1'>$1</a>")
end function
 
dim txtTest
 
txtTest = "어쩌구 저쩌구...울랄라 http://www.naver.com 으로 보내주삼"
 
response.write AutoLink(txtTest)
%>
반응형
반응형
별거 아닌거에 박모 과장땀시 무자게 헷갈렸다...-_-; 정규식이 어떻고 저떻고 해서리..-_-;;;;;

get_URL = Request.ServerVariables("HTTP_REFERER")

get_URL = LCase(LEFT(get_URL, InstrRev(get_URL, "/")))

밑에 껀 페이지

get_URL = Request.ServerVariables("HTTP_REFERER")

get_URL = LCase(mid(get_URL, InstrRev(get_URL, "/") + 1))
반응형
반응형



첨부파일은 한발(http://www.hanbal.net)에서 스터디 진행한 내용입니다.
Debug.Pring찍히니깐 브레이트 포인터 걸어놓고 출력창을 확인하면서~~
응용예)
Finding Unmatched Records in Dataset Tables Using Linq
http://www.eggheadcafe.com/tutorials/aspnet/9b443d4a-0ec3-4599-be41-d4454c1fbd9b/finding-unmatched-records.aspx

1. LINQ(Language Integrated Query )
http://msdn.microsoft.com/ko-kr/library/bb397926.aspx
쿼리를 이용하여 개체와 데이터 간 격차를 줄여주는 기술.
객체지향 기술을 사용하여 네이티브에 정의되지 않은 정보 접근이나 통합의 복잡함을 경감시키는 방식으로  모든 Data소스에 대해 쿼리가 가능하게 한 framework  
주요장점들
   -  여러 조건을 필터링할 때 더욱 명료하며 읽기 쉽다.
   -  최소한의 응용 프로그램 코드를 사용하여 강력한 필터링, 정렬 및 그룹화 기능을 제공.
   -  거의 수정하지 않거나 약간만 수정하여 다른 데이터 소스에 이식할 수 있다.

1.1 다양한 종류의 데이터 소스와 형식에서 작업하기 위한 일관된 모델을 제공

1.1.1 쿼리 가능한 형식 
   - IEnumerable 또는 IEnumerable<(Of <(T>)>)
   - IQueryable<(Of <(T>)>) 같은 파생 인터페이스를 지원하는 형식
   - SQL Server 데이터베이스, XML 문서, ADO.NET 데이터 집합 

1.2. 코딩시 기본 쿼리 작업 특징들

// Data source.
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
1.2.0 쿼리생성(Query creation)
// var 키워드는 from 절에 지정된 데이터 소스를 검사하여 쿼리 변수의 형식을 추론하도록  컴파일러에 지시
// numQuery변수는는 이 쿼리식만 가지고 실행은 되지 않는다.
var numQuery =  
        from num in numbers where (num % 2) == 0
        select num;

1.2.1. 지연실행
foreach문 사용 시 실재로 실행을함
        foreach (int num in numQuery)
            Console.Write("{0,1} ", num);
1.2.2. 즉시실행강제
-  Count, Max, Average 및 First와 같은 집계함수를 수행 할 때는 내부적으로 내장 foreach문이 실행됨
       int numCount = numQuery .Count();
1.2.3.  실행결과 캐싱
-  ToList<(Of <(TSource>)>) 또는 ToArray<(Of <(TSource>)>) 메서드를 호출 결과를 캐싱
         List<int> numQuery2 = (from num in numbers where (num % 2) == 0 select num).ToList();
        // or like this:
        var numQuery3 = (from num in numbers where (num % 2) == 0 select num).ToArray();
1.2.4.
정렬
      var queryLondonCustomers3 = 
             from cust in customers where cust.City == "London"
            
orderby cust.Name ascending
             select cust;
1.2.5. 그룹화
-
group 절은 그룹의 키 값과 일치하는 하나 이상의 항목을 포함하는 IGrouping<(Of <(TKey, TElement>)>) 개체 시퀀스를 반환
      // Query variable is an IEnumerable<IGrouping<char, Student>>
      var studentQuery1 =
      from student in students
      group student by student.Last[0]; //char형 키를 저장하게된다.

1.2.5.1. 각 그룹에서 추가 쿼리 작업을 수행하려면  into 컨텍스트키워드를 이용하여 임시식별자를 만들어서 수행
      // custQuery is an IEnumerable<IGrouping<string, Customer>>
      var custQuery = from cust in customers
      group cust by cust.City into custGroup
      where
custGroup.Count() > 2
      orderby custGroup.Key
      select custGroup;

1.2.5.2. 그룹쿼리 결과얻기
      // Iterate group items with a nested foreach. This IGrouping encapsulates a sequence of Student objects, and a Key of type char.
      // For convenience, var can also be used in the foreach statement.
       foreach (IGrouping<char, Student> studentGroup in studentQuery2)
      {
            Console.WriteLine(studentGroup.Key);
            // Explicit type for student could also be used here.
            foreach (var student in studentGroup)
           {
                Console.WriteLine("   {0}, {1}", student.Last, student.First);
           }
       }
       
1.2.5.3. 그루핑 시 키 지정
        그룹 키는 문자열, 기본 제공 숫자 형식 또는 사용자 정의 명명된 형식이나 익명 형식과 같은 임의의 형식가능

1.2.5.3.1. 문자열값으로 그룹화예
 Query variable(studentQuery3 ) is an IEnumerable<IGrouping<string, Student>> 이 됨
 var studentQuery3 = from student in students group student by student.Last;

1.2.5.3.2. 부울값으로 그룹화 예
 group by 다음에 조건을 지정하여 조건에 해당하는 두 그룹으로 나누는 경우
 데이타가 아래와 같이 정의된경우,
         List<Student> students = new List<Student>
        {
           new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 72, 81, 60}},
           new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}},
           new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int> {99, 89, 91, 95}},
           new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int> {72, 81, 65, 84}},
           new Student {First="Debra", Last="Garcia", ID=115, Scores= new List<int> {97, 89, 85, 82}}
        };
 다음과 같이 조건으로 그루핑하면 키값이 boolean형으로 저장됨
         var booleanGroupQuery =
            from student in students
            group student by student.Scores.Average() >= 80; //pass or fail!

        // Execute the query and access items in each group
        foreach (var studentGroup in booleanGroupQuery)
        {
            Console.WriteLine(studentGroup.Key == true ? "High averages" : "Low averages");
            foreach (var student in studentGroup)
            {
                Console.WriteLine("   {0}, {1}:{2}", student.Last, student.First, student.Scores.Average());
            }
        }
1.2.5.3.3. 숫자범위로 그룹화 예
 group by 다음에 범위형태로 조건을 줄 수도 있다. 10단위로 키값이 그루핑되나봅니다.
        var studentQuery =
            from student in students
            let avg = (int)student.Scores.Average()
            group student by (avg == 0 ? 0 : avg / 10) into g
            orderby g.Key
            select g;           

        // Execute the query.
        foreach (var studentGroup in studentQuery)
        {
            int temp = studentGroup.Key * 10;
            Console.WriteLine("Students with an average between {0} and {1}", temp, temp + 10);
            foreach (var student in studentGroup)
            {
                Console.WriteLine("   {0}, {1}:{2}", student.Last, student.First, student.Scores.Average());
            }
        }
1.2.5.3.3. 복합키로 그룹화 예
group person by new {name = person.surname, city = person.city};

1.2.6. 조인

1.2.6.1. 내부조인
  var innerJoinQuery =
  from category in categories
            join prod in products on category.ID equals prod.CategoryID
  select new { ProductName = prod.Name, Category = category.Name }; //produces flat sequence

1.2.6.2. 그룹조인
  - into 식이 있는 join 절을 그룹 조인을 말한다. T-Sql에 이런게 없는걸로 아는데... 재미난 조인인듯
  - 그룹 조인은 왼쪽 소스 시퀀스의 요소를 오른쪽 소스 시퀀스에 있는 하나 이상의 일치하는 요소와 연결하는 계층적 결과를 생성
  - 왼쪽 소스의 요소와 일치하는 오른쪽 소스 시퀀스의 요소가 없을 경우 join 절은 해당 항목에 대해 빈 배열을 생성
  - 그룹 조인은 결과 시퀀스가 그룹으로 구성된다는 점을 제외하고 기본적으로 내부 동등 조인과 같다?
    var innerGroupJoinQuery = 
    from category in categories  
               join prod in products on category.ID equals prod.CategoryID
into prodGroup
    select new { CategoryName = category.Name, Products = prodGroup };
  - 그룹 조인의 결과를 다른 하위 쿼리의 생성기로 사용 (T-Sql에서 중첩쿼리에 해당하겠네요)
    var innerGroupJoinQuery2 =
    from category in categories
               join prod in products on category.ID equals prod.CategoryID into prodGroup
    from prod2 in prodGroup
    where prod2.UnitPrice > 2.50M
    select prod2;   

1.2.6.3.
왼쪽우선 외부조인 (Tsql의 Left Outer Join)
  - LINQ에서 왼쪽 우선 외부 조인을 수행하려면 DefaultIfEmpty 메서드를 그룹 조인과 함께 사용하여
    왼쪽 요소에 일치 항목이 없을 경우 생성할 기본 오른쪽 요소를 지정
    문법이 매끄럽지가 못하다는 느낌이...(그냥 Left Join으로 표기하지 않구.. 엄청 어렵게 표현T.T)
          var leftOuterJoinQuery =
          from category in categories
                   join prod in products on category.ID equals prod.CategoryID
into prodGroup
          from item in prodGroup.DefaultIfEmpty(new Product{Name = String.Empty, CategoryID = 0})
          select new { CatName = category.Name, ProdName = item.Name };

1.2.6.4. 개체 컬렉션 및 관계형 테이블의 조인
         LINQ 쿼리 식에서는 조인 작업이 개체 컬렉션에서 수행되며 두 개의 관계형 테이블과 동일한 방식으로 "조인"할 수 없다.
         LINQ에서 명시적 join 절은 두 개의 소스 콜렉션이 어떤 관계로도 연결되지 않은 경우에만 필요
         LINQ to SQL을 사용하는 경우 외래 키 테이블은 개체 모델에 기본 테이블의 속성으로 표현되므로 조인이 이미 된 상태임
        ( 예를 들어 Northwind 데이터베이스의 Customer 테이블은 Orders 테이블과 외래 키 관계가 있습니다.
          테이블을 개체 모델에 매핑하면 Customer 클래스에 해당 Customer와 연결된 Orders 컬렉션을 포함하는 Orders 속성이 자동생성됨)

 1.2.6.5. 복합키 조인 
         익명 형식의 복합 키를 만들거나, 비교할 값이 포함된 명명된 형식으로 복합 키를 만듬.
        (참고: db라는 collection의 속성으로 Orders와 Products가 이미 포함되었다고 가정함)
         var query = 
         from o in db.Orders
         from p in db.Products
                          join d in db.OrderDetails on new {o.OrderID, p.ProductID} equals new {d.OrderID,        d.ProductID}
         into details
         from d in details
         select new {o.OrderID, p.ProductID, d.UnitPrice};    

1.3. LINQ를 통한 데이터 변환
 LINQ(통합 언어 쿼리)는 데이터를 검색할 뿐 아니라 데이터를 변환하는 강력한 도구.
 LINQ 쿼리를 사용하면 소스 시퀀스를 입력으로 사용하고 다양한 방식으로 수정하여 새 출력 시퀀스를 만들 수 있다.
 LINQ 쿼리의 가장 강력한 기능은 select절을 이용한 새 형식을 만드는 기능

1.3.1. 여러 입력을 하나의 출력 시퀀스로 결합 
두 개의 메모리 내 데이터 구조를 결합하는 방법을 보여 주지만, XML이나 SQL 또는 DataSet 소스의 데이터를 결합하는 경우에도 동일한 원칙을 적용할 수 있다.        
        // Create the first data source.
        List<Student> students = new List<Student>()
        {
            new Student {First="Svetlana", Last="Omelchenko",  ID=111, Street="123 Main Street", City="Seattle", Scores= new List<int> {97, 92, 81, 60}},
            new Student {First="Claire", Last="O’Donnell",  ID=112, Street="124 Main Street", City="Redmond", Scores= new List<int> {75, 84, 91, 39}},
            new Student {First="Sven", Last="Mortensen", ID=113, Street="125 Main Street", City="Lake City", Scores= new List<int> {88, 94, 65, 91}},
        };

        // Create the second data source.
        List<Teacher> teachers = new List<Teacher>()
        {               
            new Teacher {First="Ann", Last="Beebe", ID=945, City = "Seattle"},
            new Teacher {First="Alex", Last="Robinson", ID=956, City = "Redmond"},
            new Teacher {First="Michiyo", Last="Sato", ID=972, City = "Tacoma"}
        };

        // Create the query.
        var peopleInSeattle =
        (
           from student in students
           where student.City == "Seattle"
           select student.Last
        )
        .Concat  // 쿼리의 union all 에 해당
       (
          from teacher in teachers
          where teacher.City == "Seattle"
          select teacher.Last
       );

        Console.WriteLine("The following students and teachers live in Seattle:");
       
        // Execute the query.
        foreach (var person in peopleInSeattle)
        {
            Console.WriteLine(person);
        }

1.3.2. 각 소스 요소의 하위 집합 선택 
 - 단순한 Select
    var query = from cust in Customers
            select cust.City;
 - 새로운 인스턴트스로 생성하며 select
   var query = from cust in Customer
            select new {Name = cust.Name, City = cust.City}; 

1.3.3. 메모리 내부 개체를 XML로 변환 
// Create the data source by using a collection initializer.
        List<Student> students = new List<Student>()
        {
            new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores = new List<int>{97, 92, 81, 60}},
            new Student {First="Claire", Last="O’Donnell", ID=112, Scores = new List<int>{75, 84, 91, 39}},
            new Student {First="Sven", Last="Mortensen", ID=113, Scores = new List<int>{88, 94, 65, 91}},
        };

        // Create the query. 이렇게 XElement를 이용하여~~~
        var studentsToXML =
        new XElement("Root",
            from student in students
            let x = String.Format("{0},{1},{2},{3}", student.Scores[0], student.Scores[1], student.Scores[2], student.Scores[3])
            select new XElement("student",
                       new XElement("First", student.First),
                       new XElement("Last", student.Last),
                       new XElement("Scores", x)
                    ) // end "student"
                ); // end "Root"

        // Execute the query.
        Console.WriteLine(studentsToXML);

1.3.4.  소스 요소에서 작업 수행
        // Data source.
        double[] radii = { 1, 2, 3 };

        // Query.
        IEnumerable<string> query =
            from rad in radii
            select String.Format("Area = {0}", (rad * rad) * 3.14);

        // Query execution.
        foreach (string s in query)
            Console.WriteLine(s);

1.4. 쿼리 구문과 메서드 구문 비교
NET CLR(공용 언어 런타임) 자체에는 쿼리 구문의 개념이 없고 컴파일 타임에 쿼리 식은 CLR이 인식가능한 메서드 호출로 변환됨
이러한 메서드를 표준 쿼리 연산자 라고 하며 Where, Select, GroupBy, Join, Max, Average,... 등이 있다.
쿼리 구문 대신 메서드 구문을 사용하여 이를 직접 호출할 수 있다.
          int[] numbers = { 5, 10, 8, 3, 6, 12};
         //Query syntax:
        IEnumerable<int> numQuery1 =
            from num in numbers
            where num % 2 == 0
            orderby num
            select num;

        //Method syntax:
        IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
둘의 결과는 동일하다.
Where(num => num % 2 == 0) 이 인라인 식을 람다식 이라한다.
람다식을 사용하지 않을 경우 익명 메서드나 제네릭 대리자 또는 식 트리와 같은 형식으로 코드를 작성해야 한다.
C#에서 =>는 "goes to"를 나타내는 람다 연산자
 

1.5. 람다식
http://msdn.microsoft.com/ko-kr/library/bb397687.aspx 계속
http://msdn.microsoft.com/ko-kr/library/bb397951.aspx 식트리
http://msdn.microsoft.com/ko-kr/library/bb882636.aspx
식과 문을 포함하고 대리자나 식 트리 형식을 만드는 데 사용할 수 있는 익명 함수
모든 람다 식에는 람다 연산자 =>("이동"이라고 읽음)사용
왼쪽에는 입력 매개 변수(있는 경우)를 지정하고 오른쪽에는 식 또는 문 블록이 위치
=> 연산자는 할당 연산자(=)와 우선 순위가 같으며 오른쪽 결합성이 있다.
예) x => x * x라는 람다 식은 "x는 x 곱하기 x로 이동"으로 읽으며, 이 식은 다음과 같이 대리자 형식에 할당할 수 있다.
delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

메서드 기반 LINQ 쿼리에서 Where 및 Where 같은 표준 쿼리 연산자 메서드의 인수로 사용.
LINQ to Objects 및 LINQ to XML에서처럼 메서드 기반의 구문을 사용하여 Enumerable 클래스에서 Where 메서드를 호출하는 경우
매개 변수는 System..::.Func<(Of <(T, TResult>)>) 대리자 형식
람다식은 대리자를 만드는 가장 간단한 방법이다.
LINQ to SQL에서 System.Linq..::.Queryable 클래스 에서 호출하는 경우 매개 변수 형식은 System.Linq.Expressions..::.Expression<Func>이고, 여기서 Func는 입력 매개 변수를 5개까지 가질 수 있는 임의의 Func 대리자이다.

1.5.1. 식 람다(expression lamda)
- 오른쪽에 식이 있는 람다 식,  식 트리를 만드는 데 광범위하게 사용,식 람다는 식의 결과를 반환
 (input parameters) => expression
- 괄호는 람다 식에 입력 매개 변수가 하나뿐인 경우에만 생략
- 둘 이상의 입력 매개 변수는 다음과 같이 괄호로 묶고 쉼표로 구분
 (x, y) => x == y
- 컴파일러에서 입력 형식을 유추할 수 없는 경우 다음과 같이 형식을 명시적으로 지정
 (int x, string s) => s.Length > x
- 입력 매개 변수가 0개이면 다음과 같이 빈 괄호를 지정
 () => SomeMethod()
1.5.2.  식트리
System.Linq.Expressions 네임스페이스 필요
IQueryable<(Of <(T>)>)을 구현하는 데이터의 소스를 대상으로 하는 구조화된 쿼리를 나타내기 위해 식 트리를 사용
LINQ에서 Expression<(Of <(TDelegate>)>) 형식 변수에 할당되는 람다 식을 나타내는 데에도 사용
   Expression<Func<int, bool>> exprTree = num => num < 5;
   와같이 Delegate표현대신 Expression클래스 형식을 사용하여 트리형태로 식을저장
ParameterExpression,ConstantExpression,BinaryExpression등과같이 식에표현된 각 부분에 해당하는 클래스들존재

// Manually build the expression tree for the lambda expression num => num < 5.
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expression<Func<int, bool>> lambda1 =
    Expression.Lambda<Func<int, bool>>(
        numLessThanFive,
        new ParameterExpression[] { numParam });
와 동일한 람다식표현
// Let the compiler generate the expression tree for the lambda expression num => num < 5.
Expression<Func<int, bool>> lambda2 = num => num < 5;
이정도 개념만 있어도 충분할듯, 더 자세한 부분은 MSDN을 찾아보시고 http://msdn.microsoft.com/ko-kr/library/bb882637.aspx


1.5.3. 문 람다 (statement lamda)
- 문 람다는 다음과 같이 중괄호 안에 문을 지정한다는 점을 제외하면 식 람다와 비슷
 (input parameters) => {statement;}
- 문 람다의 본문에 지정할 수 있는 문의 개수에는 제한이 없지만 일반적으로 2-3개 정도만 지정
  (문 람다는 식 트리를 만드는 데 사용될 수 없다)
 delegate void TestDelegate(string s);
 …
 TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };
 myDel("Hello");

1.5.4. 표준 쿼리 연산자와 람다 식
- 대부분의 표준 쿼리 연산자에는 형식이 제네릭 대리자의 Func<(Of <(T, TResult>)>) 패밀리 중 하나인 입력 매개 변수를 사용
 public delegate TResult Func<TArg0, TResult>(TArg0 arg0)
 이 경우 대리자를 Func<int,bool> myFunc로 인스턴스화할 수 있다.
 int는 입력 매개 변수이고, bool은 반환 값(반환 값은 항상 마지막 형식 매개 변수로 지정)

예) 5인지 여부판단하여 bool로 리턴
    Func<int, bool> myFunc = x => x == 5;
    bool result = myFunc(4); // returns false of course
- System.Linq.Queryable에 정의되어 있는 표준 쿼리 연산자의 경우와 같이 인수 형식이 Expression<Func>인 경우에도 람다 식을 사용.
  Expression<Func> 인수를 지정하면 식 트리에 람다 식이 컴파일됨

예) 2로 나누었을 때 나머지가 1인 정수(n)의 수를 계산
      int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
      int oddNumbers = numbers.Count(n => n % 2 == 1);
    시작부터 검사하여 6보다 작은 값들 추출
      var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
    2개의 파라메타를 입력받아 동적으로 임계치 변경
      var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);

1.5.5. 람다 식에서의 형식 유추
입력 매개 변수의 형식은 대부분의 표준 쿼리 연산자에서 첫 번째 입력 형식은 소스 시퀀스 요소의 형식으로 컴파일러가 유추함
IEnumerable<Customer>을 쿼리할 경우 입력 변수가 Customer 개체로 유추
customers.Where(c => c.City == "London");
- 람다 식적용 규칙
  람다 식과 대리자 형식에 포함된 매개 변수 수가 같아야 한다. 
   람다 식의 각 입력 매개 변수는 해당되는 대리자 매개 변수로 암시적으로 변환될 수 있어야 한다.
  람다 식의 반환 값(있는 경우)은 대리자의 반환 형식으로 암시적으로 변환될 수 있어야 한다.
  람다 식의 "형식"을 비공식적으로 언급해야 할 경우 대리자 형식 또는 람다 식이 변환되는 Expression 형식을 의미

1.5.6. 람다 식의 변수 범위
람다 식은 람다 식이 정의된 바깥쪽 메서드나 형식의 범위에 포함되어 있는 외부 변수를 참조할 수 있다.
이러한 방식으로 캡처되는 변수는 변수가 범위를 벗어나 가비지 수집되는 경우에도 람다 식에 사용할 수 있도록 저장된다.
외부 변수는 명확하게 할당해야만 람다 식에 사용할 수 있다
- 람다 식의 변수 범위규칙
  캡처된 변수는 해당 변수를 참조하는 대리자가 범위에서 벗어날 때까지 가비지 수집되지 않는다.
  람다 식에 사용된 변수는 외부 메서드에 표시되지 않는다.
  람다 식은 바깥쪽 메서드에서 ref 또는 out 매개 변수를 직접 캡처할 수 없습니다.
  람다 식의 return 문에 의해서는 바깥쪽 메서드가 반환되지는 않는다.?
  람다 식에는 포함된 익명 함수의 본문 또는 본문 외부를 대상으로 하는 goto 문, break 문 또는 continue 문이 포함될 수 없다

예)
    delegate bool D();
    delegate bool D2(int i);

    class Test
    {
        D del;
        D2 del2;
        public void TestMethod(int input)
        {
            int j = 0;
            // Initialize the delegates with lambda expressions.
            // Note access to 2 outer variables.
            // del will be invoked within this method.
            del = () => { j = 10;  return j > input; };

            // del2 will be invoked after TestMethod goes out of scope.
            del2 = (x) => {return x == j; };
           
            // Demonstrate value of j:
            // Output: j = 0
            // The delegate has not been invoked yet.
            Console.WriteLine("j = {0}", j);

            // Invoke the delegate.
            bool boolResult = del();

            // Output: j = 10 b = True
            Console.WriteLine("j = {0}. b = {1}", j, boolResult);
        }

        static void Main()
        {
            Test test = new Test();
            test.TestMethod(5);

            // Prove that del2 still has a copy of
            // local variable j from TestMethod.
            bool result = test.del2(10);

            // Output: True
            Console.WriteLine(result);
           
            Console.ReadKey();
        }
    }

2. LINQ to Objects
중간 LINQ 공급자나 API는 사용하지 않고 LINQ to SQL,LINQ to XML처럼 IEnumerable,IEnumerable<(Of <(T>)>) 파생 컬렉션을 직접 사용하는 LINQ쿼리를 말함
LINQ를 사용하여 List<(Of <(T>)>), Array 또는 Dictionary<(Of <(TKey, TValue>)>)와 같은 열거 가능한 컬렉션을 모두 쿼리가능

2.1. LINQ 및 문자열
문자열 및 문자열의 컬렉션을 쿼리하고 변환
일반적인 문자열 함수 및 정규식과 결합될 수 있다.

2.1.1 문자열에서 단어가 나오는 횟수 세기(LINQ)
 class CountWords
{
    static void Main()
    {
        string text = @"Historically, the world of data and the world of objects" +
          @" have not been well integrated. Programmers work in C# or Visual Basic" +
          @" and also in SQL or XQuery. On the one side are concepts such as classes," +
          @" objects, fields, inheritance, and .NET Framework APIs. On the other side" +
          @" are tables, columns, rows, nodes, and separate languages for dealing with" +
          @" them. Data types often require translation between the two worlds; there are" +
          @" different standard functions. Because the object world has no notion of query, a" +
          @" query can only be represented as a string without compile-time type checking or" +
          @" IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to" +
          @" objects in memory is often tedious and error-prone.";

        string searchTerm = "data";

        //Convert the string into an array of words
        string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries);

        // Create and execute the query. It executes immediately because a singleton value is produced. 즉시실행???
        // Use ToLowerInvariant to match "data" and "Data"
        var matchQuery = from word in source
                         where word.ToLowerInvariant() == searchTerm.ToLowerInvariant()
                         select word;

        // Count the matches.
        int wordCount = matchQuery.Count();
        Console.WriteLine("{0} occurrences(s) of the search term \"{1}\" were found.", wordCount, searchTerm);

    }
}
/* Output:
   3 occurrences(s) of the search term "data" were found.
*/

2.1.2 지정된 단어 집합이 들어 있는 문장 쿼리(LINQ)
//나눈 문장들에서 "Historically", "data" 및 "integrated"이라는 단어를 모두 포함한 문장을 반환.
        // Split the text block into an array of sentences.
        string[] sentences = text.Split(new char[] { '.', '?', '!' });

        // Define the search terms. This list could also be dynamically populated at runtime.
        string[] wordsToMatch = { "Historically", "data", "integrated" };

        // let에서 문장들 나누고, Distinct로 중복된 문장제거, Intersect로 교집합연산의 개수가 wordsToMatch의 개수와 동일한 문장만 Select
        // Note that the number of terms to match is not specified at compile time.
        var sentenceQuery = from sentence in sentences
                            let w = sentence.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' },StringSplitOptions.RemoveEmptyEntries)
                            where w.Distinct().Intersect(wordsToMatch).Count() == wordsToMatch.Count()
                            select sentence;
     
        // Execute the query. Note that you can explicitly type the iteration variable here even though sentenceQuery
        // was implicitly typed.
        foreach (string str in sentenceQuery)
        {
            Console.WriteLine(str);
        }
2.1.3 문자열의 문자 쿼리(LINQ)
String 클래스는 제네릭 IEnumerable<(Of <(T>)>) 인터페이스를 구현하기 때문에 모든 문자열을 문자 시퀀스로 쿼리할 수 있다.
class QueryAString
{
    static void Main()
    {
        string aString = "ABCDE99F-J74-12-89A";

        // Select only those characters that are numbers 숫자로~~
        IEnumerable<char> stringQuery =
          from ch in aString
          where Char.IsDigit(ch)
          select ch;

        // Execute the query
        foreach (char c in stringQuery)
            Console.Write(c + " ");

        // Call the Count method on the existing query.
        int count = stringQuery.Count();
        Console.WriteLine("Count = {0}", count);

        // Select all characters before the first '-'
        IEnumerable<char> stringQuery2 = aString.TakeWhile(c => c != '-');

        // Execute the second query
        foreach (char c in stringQuery2)
            Console.Write(c);

        Console.WriteLine(System.Environment.NewLine + "Press any key to exit");
        Console.ReadKey();

    }
}
/* Output:
  Output: 9 9 7 4 1 2 8 9
  Count = 8
  ABCDE99F
*/

2.1.4. LINQ 쿼리와 정규식 결합
Regex 클래스를 사용하여 텍스트 문자열에서 좀 더 복잡한 비교를 위해 정규식을 만드는 방법
class QueryWithRegEx
{
     // This method assumes that the application has discovery permissions for all folders under the specified path.
    static IEnumerable<System.IO.FileInfo> GetFiles(string path)
    {
        if (!System.IO.Directory.Exists(path))
            throw new System.IO.DirectoryNotFoundException();

        string[] fileNames = null;
        List<System.IO.FileInfo> files = new List<System.IO.FileInfo>();

        fileNames = System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories);
        foreach (string name in fileNames)
        {
            files.Add(new System.IO.FileInfo(name));
        }
        return files;
    }
    public static void Main()
    {
        // Modify this path as necessary.
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder); //폴더의 모든 파일정보

        // Create the regular expression to find all things "Visual".
        System.Text.RegularExpressions.Regex searchTerm =
            new System.Text.RegularExpressions.Regex(@"Visual (Basic|C#|C\+\+|J#|SourceSafe|Studio)");

        // Search the contents of each .htm file.
        // Remove the where clause to find even more matches!
        // This query produces a list of files where a match was found, and a list of the matches in that file.
        // Note: Explicit typing of "Match" in select clause.
        // This is required because MatchCollection is not a generic IEnumerable collection.
        var queryMatchingFiles =
            from file in fileList
            where file.Extension == ".htm" //확장자가 htm인 것들중에
            let fileText = System.IO.File.ReadAllText(file.FullName) // 파일명만 fileText 목록(집합)으로두고
            let matches = searchTerm.Matches(fileText) // fileText에서 searchTerm에 해당하는 것들만
            where searchTerm.Matches(fileText).Count > 0 //이게 없으면 matches에 null도 들어가나??? 확인필요
            select new
            {
                name = file.FullName,
                matches = from System.Text.RegularExpressions.Match match in matches
                          select match.Value
            };

        // Execute the query.
        Console.WriteLine("The term \"{0}\" was found in:", searchTerm.ToString());

        foreach (var v in queryMatchingFiles)
        {
            // Trim the path a bit, then write the file name in which a match was found.
            string s = v.name.Substring(startFolder.Length - 1);
            Console.WriteLine(s);

            // For this file, write out all the matching strings
            foreach (var v2 in v.matches)
            {
                Console.WriteLine("  " + v2);
            }
        }
    } 
}
2.1.5. 두 목록 간의 차집합 구하기(LINQ)
 names1.txt에 있지만 names2.txt에는 없는 해당 줄을 출력
class CompareLists
{       
    static void Main()
    {
        // Create the IEnumerable data sources.
        string[] names1 = System.IO.File.ReadAllLines(@"../../../names1.txt");
        string[] names2 = System.IO.File.ReadAllLines(@"../../../names2.txt");

        // Create the query. Note that method syntax must be used here.
        IEnumerable<string> differenceQuery =
          names1.Except(names2);

        // Execute the query.
        Console.WriteLine("The following lines are in names1.txt but not names2.txt");
        foreach (string s in differenceQuery)
            Console.WriteLine(s);
    }
}
2.1.6. 단어 또는 필드에 따라 텍스트 데이터 정렬 또는 필터링(LINQ)
쉼표로 구분된 값과 같은 구조화된 텍스트 줄을 해당 줄에서 임의의 필드를 기준으로 정렬하는 방법
scores.csv의 필드는 학생의 ID 번호와 4개의 테스트 점수를 나타낸다고 가정
public class SortLines
{
    static void Main()
    {
        // Create an IEnumerable data source
        string[] scores = System.IO.File.ReadAllLines(@"../../../scores.csv");

        // Change this to any value from 0 to 4.
        int sortField = 1; //두번째 필드 말하죠.. (0부터시작)

        Console.WriteLine("Sorted highest to lowest by field [{0}]:", sortField);

        // Demonstrates how to return query from a method.
        // The query is executed here.
        foreach (string str in RunQuery(scores, sortField))
        {
            Console.WriteLine(str);
        }
    }

    // Returns the query variable, not query results!
    static IEnumerable<string> RunQuery(IEnumerable<string> source, int num)
    {
        // Split the string and sort on field[num]
        var scoreQuery = from line in source
                         let fields = line.Split(',')
                         orderby fields[num] descending
                         select line;

        return scoreQuery;
    }
}
/* Output (if sortField == 1):
   Sorted highest to lowest by field [1]:
    116, 99, 86, 90, 94
    120, 99, 82, 81, 79
    111, 97, 92, 81, 60
    114, 97, 89, 85, 82
    121, 96, 85, 91, 60
    122, 94, 92, 91, 91
    117, 93, 92, 80, 87
    118, 92, 90, 83, 78
    113, 88, 94, 65, 91
    112, 75, 84, 91, 39
    119, 68, 79, 88, 92
    115, 35, 72, 91, 70
 */
2.1.7. 구분된 파일의 필드 다시 정렬후 파일로 저장.
- spreadsheet1.csv라는 일반 텍스트 내용
Adams,Terry,120
Fakhouri,Fadi,116
Feng,Hanying,117
Garcia,Cesar,114
Garcia,Debra,115
Garcia,Hugo,118
Mortensen,Sven,113
O'Donnell,Claire,112
Omelchenko,Svetlana,111
Tucker,Lance,119
Tucker,Michael,122
Zabokritski,Eugene,121

-파일을 읽어 쉼표로 구분하고,  3번쨰 필드로 정렬한 후 다시 파일로 저장
        // Create the IEnumerable data source
        string[] lines = System.IO.File.ReadAllLines(@"../../../spreadsheet1.csv");

        // Create the query. Put field 2 first, then
        // reverse and combine fields 0 and 1 from the old field
        IEnumerable<string> query =
            from line in lines
            let x = line.Split(',')
            orderby x[2] 
            select x[2] + ", " + (x[1] + " " + x[0]);

        // Execute the query and write out the new file. Note that WriteAllLines
        // takes a string[], so ToArray is called on the query.
        System.IO.File.WriteAllLines(@"../../../spreadsheet2.csv", query.ToArray());

2.1.7. 문자열 컬렉션 결합 및 비교
텍스트 줄이 포함된 파일을 병합한 다음 결과를 정렬하는 방법
특히 두 개의 텍스트 줄 집합에서의 간단한 연결, 공용 구조체 및 교집합을 수행
- names1.txt 내용
Bankov, Peter
Holm, Michael
Garcia, Hugo
Potra, Cristina
Noriega, Fabricio
Aw, Kam Foo
Beebe, Ann
Toyoshima, Tim
Guy, Wey Yuan
Garcia, Debra
- names2.txt 내용
Liu, Jinghao
Bankov, Peter
Holm, Michael
Garcia, Hugo
Beebe, Ann
Gilchrist, Beth
Myrcha, Jacek
Giakoumakis, Leo
McLin, Nkenge
El Yassir, Mehdi

        static void OutputQueryResults(IEnumerable<string> query, string message)
        {
            Console.WriteLine(System.Environment.NewLine + message);
            foreach (string item in query)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("{0} total names in list", query.Count());
        }
//위 함수가 미리 정의돼 있다고 가정
            //Put text files in your solution folder
            string[] fileA = System.IO.File.ReadAllLines(@"../../../names1.txt");
            string[] fileB = System.IO.File.ReadAllLines(@"../../../names2.txt");

            //Simple concatenation and sort. Duplicates are preserved.
            IEnumerable<string> concatQuery = fileA.Concat(fileB).OrderBy(s => s);

            // Pass the query variable to another function for execution.
            OutputQueryResults(concatQuery, "Simple concatenate and sort. Duplicates are preserved:");

            // Concatenate and remove duplicate names based on default string comparer.(병합)
            IEnumerable<string> uniqueNamesQuery =
                fileA.Union(fileB).OrderBy(s => s); //병합하면서 distinct도 될터
            OutputQueryResults(uniqueNamesQuery, "Union removes duplicate names:");

            // Find the names that occur in both files (based on default string comparer). (교집합)
            IEnumerable<string> commonNamesQuery =
                fileA.Intersect(fileB);
            OutputQueryResults(commonNamesQuery, "Merge based on intersect:");

            // Find the matching fields in each list. Merge the two results by using Concat,
            // and then
sort using the default string comparer.
            string nameMatch = "Garcia";

            IEnumerable<String> tempQuery1 =
                from name in fileA
                let n = name.Split(',')
                where n[0] == nameMatch //,로 분리후 0번필드중에  nameMatch와 일치하는  것들 

                select name;

            IEnumerable<string> tempQuery2 =
                from name2 in fileB
                let n2 = name2.Split(',')
                where n2[0] == nameMatch
                select name2;

            IEnumerable<string> nameMatchQuery =
                tempQuery1.Concat(tempQuery2).OrderBy(s => s); // 이러면 union효과가 되나? 아님 Left join?? 확인필요
            OutputQueryResults(nameMatchQuery, String.Format("Concat based on partial name match \"{0}\":", nameMatch));

2.1.8. 여러 소스로 개체 컬렉션 채우기(두 파일읽어서 조인효과 구현)
- scores.csv
111, 97, 92, 81, 60
112, 75, 84, 91, 39
113, 88, 94, 65, 91
114, 97, 89, 85, 82
115, 35, 72, 91, 70
116, 99, 86, 90, 94
117, 93, 92, 80, 87
118, 92, 90, 83, 78
119, 68, 79, 88, 92
120, 99, 82, 81, 79
121, 96, 85, 91, 60
122, 94, 92, 91, 91
- names.csv
Omelchenko,Svetlana,111
O'Donnell,Claire,112
Mortensen,Sven,113
Garcia,Cesar,114
Garcia,Debra,115
Fakhouri,Fadi,116
Feng,Hanying,117
Garcia,Hugo,118
Tucker,Lance,119
Adams,Terry,120
Zabokritski,Eugene,121
Tucker,Michael,122
        // These data files are defined in How to: Join Content from Dissimilar Files (LINQ)
        string[] names = System.IO.File.ReadAllLines(@"../../../names.csv");
        string[] scores = System.IO.File.ReadAllLines(@"../../../scores.csv");

        // Merge the data sources using a named type.
        // var could be used instead of an explicit type.
        // Note the dynamic creation of a list of ints for the TestScores member. We skip 1 because the first string
        // in the array is the student ID, not an exam score.
        IEnumerable<Student> queryNamesScores =
            from name in names
            let x = name.Split(',')
            from score in scores
            let s = score.Split(',')
            where x[2] == s[0]  // score의 첫번째 컬럼과 names의 두번째 컬럼과 조인(학생ID)
            select new Student()  //이렇게 새로운 타입으로 new
            {
                FirstName = x[0],
                LastName = x[1],
                ID = Convert.ToInt32(x[2]), //타입명시 
                ExamScores = (from scoreAsText in s.Skip(1) //첫번째 값은 ID이므로 skip 
                              select Convert.ToInt32(scoreAsText)).
                              ToList()
            };

        // Optional. Store the newly created student objects in memory for faster access in future queries. Could be useful with
        // very large data files.
        List<Student> students = queryNamesScores.ToList();

        // Display the results and perform one further calculation.
        foreach (var student in students)
        {
            Console.WriteLine("The average score of {0} {1} is {2}.",
                student.FirstName, student.LastName, student.ExamScores.Average());
        }
2.1.9. 그룹을 사용하여 파일을 여러 파일로 분할
- names1.csv
Bankov, Peter
Holm, Michael
Garcia, Hugo
Potra, Cristina
Noriega, Fabricio
Aw, Kam Foo
Beebe, Ann
Toyoshima, Tim
Guy, Wey Yuan
Garcia, Debra
- names2.csv
Liu, Jinghao
Bankov, Peter
Holm, Michael
Garcia, Hugo
Beebe, Ann
Gilchrist, Beth
Myrcha, Jacek
Giakoumakis, Leo
McLin, Nkenge
El Yassir, Mehdi

        string[] fileA = System.IO.File.ReadAllLines(@"../../../names1.txt");
        string[] fileB = System.IO.File.ReadAllLines(@"../../../names2.txt");

        // Concatenate and remove duplicate names based on default string comparer
        var mergeQuery = fileA.Union(fileB);

        // Group the names by the first letter in the last name.
        var groupQuery = from name in mergeQuery
                         let n = name.Split(',')
                         group name by n[0][0] into g  //제일 첫글자 , n[0]은 첫번쨰 컬럼
                         orderby g.Key
                         select g;

        // Create a new file for each group that was created
        // Note that nested foreach loops are required to access
        // individual items with each group.
        foreach (var g in groupQuery)
        {
            // Create the new file name.
            string fileName = @"../../../testFile_" + g.Key + ".txt";
            // Write file. 그룹별로 파일생성
            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fileName))
            {
                foreach (var item in g)
                {
                    sw.WriteLine(item);
                    // Output to console for example purposes.
                    Console.WriteLine("   {0}", item);
                }
            }
        }

2.1.10. 서로 다른 파일의 콘텐츠 조인 
코드만 봐도 될듯
        string[] names = System.IO.File.ReadAllLines(@"../../../names.csv");
        string[] scores = System.IO.File.ReadAllLines(@"../../../scores.csv");
        // Name:    Last[0],                First[1],      ID[2],     Grade Level[3]
        //                  Omelchenko,    Svetlana,      11,          2
        // Score:   StudentID[0],  Exam1[1]   Exam2[2],  Exam3[3],  Exam4[4]
        //          111,           97,        92,        81,        60

        // This query joins two dissimilar spreadsheets based on common ID value.
        // Multiple from clauses are used instead of a join clause
        // in order to store results of id.Split.
        IEnumerable<string> scoreQuery1 =
            from name in names
            let nameFields = name.Split(',')
            from id in scores
            let scoreFields = id.Split(',')
            where nameFields[2] == scoreFields[0]
            select nameFields[0] + "," + scoreFields[1] + "," + scoreFields[2]
                   + "," + scoreFields[3] + "," + scoreFields[4];

        // Pass a query variable to a method and
        // execute it in the method. The query itself
        // is unchanged.
        OutputQueryResults(scoreQuery1, "Merge two spreadsheets:");

2.1.10. CSV 텍스트 파일의 열 값 계산 

         string[] lines = System.IO.File.ReadAllLines(@"../../../scores.csv");
          .....
        IEnumerable<IEnumerable<int>> query = from line in strs
            let x = line.Split(',')
            let y = x.Skip(1)
            select (
                            from str in y
                            select Convert.ToInt32(str));

        // Execute and cache the results for performance.
        // ToArray could also be used here.
        var results = query.ToList();

        // Find out how many columns we have.
        int columnCount = results[0].Count();

        // Perform aggregate calculations on each column.           
        // One loop for each score column in scores.
        // We can use a for loop because we have already executed the columnQuery in the call to ToList.
        for (int column = 0; column < columnCount; column++)
        {
            var res2 = from row in results
                       select row.ElementAt(column);

            double average = res2.Average(); //컬럼에 대한 average
            int max = res2.Max();
            int min = res2.Min();

            // 1 is added to column because Exam numbers
            // begin with 1
            Console.WriteLine("Exam #{0} Average: {1:##.##} High Score: {2} Low Score: {3}",
                          column + 1, average, max, min);
        }

2.2. LINQ 및 리플렉션
LINQ를 리플렉션과 함께 사용하여 지정한 검색 조건에 일치하는 메서드에 대한 특정 메타데이터를 검색할 수 있다

using System.Reflection;
using System.IO;
namespace LINQReflection
{
    class ReflectionHowTO
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken= b77a5c561934e089");
            var pubTypesQuery = 
            from type in assembly.GetTypes() // 타입목록 추출
            where type.IsPublic
            from method in type.GetMethods() // 각 타입에서 메소드목록 추출
            where method.ReturnType.IsArray == true 
                      || ( method.ReturnType.GetInterface(typeof(System.Collections.Generic.IEnumerable<>).FullName ) != null
                     && method.ReturnType.FullName != "System.String" )
            group method.ToString() by type.ToString();
            // 이렇게 되면 타입콜렉션의 속성으로 method가 들어가는 형태임. 아래에서 키(콜렉션 내에서 타입을 식별하는)별로 메소드 출력
            foreach (var groupOfMethods in pubTypesQuery)
            {
                Console.WriteLine("Type: {0}", groupOfMethods.Key);
                foreach (var method in groupOfMethods)
                {
                    Console.WriteLine("  {0}", method);
                }
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    } 
}

2.3. LINQ 및 파일 디렉터리
문자열을 다루면서 파일에 관련된 내용이 나오긴 했지만 여기에서 더 상세히 다룸.

2.1.1. 지정된 특성 또는 이름을 갖는 파일 쿼리 
//주어진 경로의 파일정보 가져오는 함수  
// This method assumes that the application has discovery  permissions for all folders under the specified path.
    static IEnumerable<System.IO.FileInfo> GetFiles(string path)
    {
        if (!System.IO.Directory.Exists(path))
            throw new System.IO.DirectoryNotFoundException();

        string[] fileNames = null;
        List<System.IO.FileInfo> files = new List<System.IO.FileInfo>();

        fileNames = System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories);           
        foreach (string name in fileNames)
        {
            files.Add(new System.IO.FileInfo(name));
        }
        return files;
    }
...
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);

        //Create the query
        IEnumerable<System.IO.FileInfo> fileQuery =
            from file in fileList
            where file.Extension == ".txt"
            orderby file.Name
            select file;

        //Execute the query. This might write out a lot of files!
        foreach (System.IO.FileInfo fi in fileQuery)         
             Console.WriteLine(fi.FullName);    // Create and execute a new query by using the previous
        // query as a starting point. fileQuery is not
        // executed again until the call to Last()
        var newestFile =
            (from file in fileQuery
            orderby file.CreationTime
            select new { file.FullName, file.CreationTime })
            .Last();

        Console.WriteLine("\r\nThe newest .txt file is {0}. Creation time: {1}",
            newestFile.FullName, newestFile.CreationTime);

2.1.2. 확장명에 따라 파일 그룹화 

        // Take a snapshot of the file system.
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\Common7";

        // Used in WriteLine to trim output lines.
        int trimLength = startFolder.Length;

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);

        // Create the query.
        var queryGroupByExt =
            from file in fileList
            group file by file.Extension.ToLower() into fileGroup
            orderby fileGroup.Key //그루핑이 되면서 동일그룹에 키값들이 할당됨에 유의
            select fileGroup;
      PageOutput(trimLength, queryGroupByExt); // 바로아래에 정의

   private static void PageOutput( int rootLength,
                                    IEnumerable<System.Linq.IGrouping<string, System.IO.FileInfo>> groupByExtList)
    {
        // Flag to break out of paging loop.
        bool goAgain = true;

        // "3" = 1 line for extension + 1 for "Press any key" + 1 for input cursor.
        int numLines = Console.WindowHeight - 3;

        // Iterate through the outer collection of groups.
        foreach (var filegroup in groupByExtList)
        {
            // Start a new extension at the top of a page.
            int currentLine = 0;

            // Output only as many lines of the current group as will fit in the window.
            do
            {
                Console.Clear();
                Console.WriteLine(filegroup.Key == String.Empty ? "[none]" : filegroup.Key);

                // Get 'numLines' number of items starting at number 'currentLine'.
                var resultPage = filegroup.Skip(currentLine).Take(numLines);

                //Execute the resultPage query
                foreach (var f in resultPage)
                {
                    Console.WriteLine("\t{0}", f.FullName.Substring(rootLength));
                }

                // Increment the line counter.
                currentLine += numLines;

                // Give the user a chance to escape.
                Console.WriteLine("Press any key to continue or the 'End' key to break...");
                ConsoleKey key = Console.ReadKey().Key;
                if (key == ConsoleKey.End)
                {
                    goAgain = false;
                    break;
                }
            } while (currentLine < filegroup.Count());

            if (goAgain == false)
                break;
        }
    }
2.1.3. 폴더 집합의 전체 바이트 수 쿼리
    static long GetFileLength(string filename)
    {
        long retval;
        try { System.IO.FileInfo fi = new System.IO.FileInfo(filename);
            retval = fi.Length;
        }
        catch (System.IO.FileNotFoundException)
        {
            // If a file is no longer present,
            // just add zero bytes to the total.
            retval = 0;
        }
        return retval;
    }
.....
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\VC#";

        // Take a snapshot of the file system.
        // This method assumes that the application has discovery permissions
        // for all folders under the specified path.
        IEnumerable<string> fileList = System.IO.Directory.GetFiles(startFolder, "*.*", System.IO.SearchOption.AllDirectories);

        var fileQuery = from file in fileList
                        select GetFileLength(file);

        // Cache the results to avoid multiple trips to the file system.
        long[] fileLengths = fileQuery.ToArray();

        // Return the size of the largest file
        long largestFile = fileLengths.Max();

        // Return the total number of bytes in all the files under the specified folder.
        long totalBytes = fileLengths.Sum();

        Console.WriteLine("There are {0} bytes in {1} files under {2}",
            totalBytes, fileList.Count(), startFolder);
        Console.WriteLine("The largest files is {0} bytes.", largestFile);
2.1.3. 두 폴더의 내용 비교
세 가지 방법
- 두 개의 파일 목록이 동일한지 여부를 지정하는 부울 값 쿼리
- 양쪽 파일에 있는 파일을 검색하는 교차 부분 쿼리
- 한 폴더에는 있지만 다른 폴더에는 없는 파일을 검색하는 차집합 쿼리

    class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
    {
        public FileCompare() { }

        public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
        {
            return (f1.Name == f2.Name && f1.Length == f2.Length); //파일명과 길이비교
        }

        // Return a hash that reflects the comparison criteria. According to the
        // rules for IEqualityComparer<T>, if Equals is true, then the hash codes must
        // also be equal. Because equality as defined here is a simple value equality, not
        // reference identity, it is possible that two or more objects will produce the same
        // hash code.
        public int GetHashCode(System.IO.FileInfo fi)
        {
            string s = String.Format("{0}{1}", fi.Name, fi.Length);
            return s.GetHashCode();
        }
    }
라는 Compare클래스 미리정의 된 경우
            string pathA = @"C:\TestDir";
            string pathB = @"C:\TestDir2"; // Take a snapshot of the file system.
            IEnumerable<System.IO.FileInfo> list1 = GetFiles(pathA);
            IEnumerable<System.IO.FileInfo> list2 = GetFiles(pathB);

            //A custom file comparer defined below
            FileCompare myFileCompare = new FileCompare();

            // This query determines whether the two folders contain identical file lists, based on the custom file comparer
            // that is defined in the FileCompare class.
            // The query executes immediately because it returns a bool.
            bool areIdentical = list1.SequenceEqual(list2, myFileCompare);
            if (areIdentical == true)
                Console.WriteLine("the two folders are the same");
            else
                Console.WriteLine("The two folders are not the same");

            // Find the common files. It produces a sequence and doesn't execute until the foreach statement.
            var queryCommonFiles = list1.Intersect(list2, myFileCompare);
           if (queryCommonFiles.Count() > 0)
           {
                Console.WriteLine("The following files are in both folders:");
                foreach (var v in queryCommonFiles)
                {
                    Console.WriteLine(v.FullName); //shows which items end up in result list
                }
            }
            else
            {
                Console.WriteLine("There are no common files in the two folders.");
            }

            // Find the set difference between the two folders.
            // For this example we only check one way.
            var queryList1Only = (from file in list1 select file).Except(list2, myFileCompare);

            Console.WriteLine("The following files are in list1 but not list2:");
            foreach (var v in queryList1Only)
            {
                Console.WriteLine(v.FullName);
            }
2.1.4. 디렉터리 트리에서 가장 큰 파일을 하나 이상 쿼리 
파일 크기(바이트)와 관련된 5개의 쿼리방법
- 가장 큰 파일의 크기(바이트)를 검색하는 방법
- 가장 작은 파일의 크기(바이트)를 검색하는 방법
- 지정한 루트 폴더에 있는 하나 이상의 폴더에서 FileInfo 개체의 가장 큰 파일이나 가장 작은 파일을 검색하는 방법
- 가장 큰 10개 파일과 같은 시퀀스를 검색하는 방법
- 지정한 크기보다 작은 파일을 무시하여 파일 크기(바이트)에 따라 파일을 그룹으로 정렬하는 방법
       string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        // fileList is an IEnumerable<System.IO.FileInfo>
        var fileList = GetFiles(startFolder);

        //Return the size of the largest file
        long maxSize =
            (from file in fileList
             let len = GetFileLength(file)
             select len).Max();

        Console.WriteLine("The length of the largest file under {0} is {1}",
            startFolder, maxSize);

        // Return the FileInfo object for the largest file by sorting and selecting from beginning of list
        System.IO.FileInfo longestFile =
            (from file in fileList
            let len = GetFileLength(file)
            where len > 0
            orderby len descending
            select file).First();

        Console.WriteLine("The largest file under {0} is {1} with a length of {2} bytes",
                            startFolder, longestFile.FullName, longestFile.Length);

        //Return the FileInfo of the smallest file
        System.IO.FileInfo smallestFile =
            (from file in fileList
            let len = GetFileLength(file)
            where len > 0
            orderby len ascending
            select file).First();

        Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes",
                            startFolder, smallestFile.FullName, smallestFile.Length);

        //Return the FileInfos for the 10 largest files queryTenLargest is an IEnumerable<System.IO.FileInfo>
        var queryTenLargest =
            (from file in fileList
            let len = GetFileLength(file)
            orderby len descending
            select file).Take(10);

        Console.WriteLine("The 10 largest files under {0} are:", startFolder);

        foreach (var v in queryTenLargest)
        {
            Console.WriteLine("{0}: {1} bytes", v.FullName, v.Length);
        }


        // Group the files according to their size, leaving out files that are less than 200000 bytes.
        var querySizeGroups =
            from file in fileList
            let len = GetFileLength(file)
            where len > 0
            group file by (len / 100000) into fileGroup
            where fileGroup.Key >= 2
            orderby fileGroup.Key descending
            select fileGroup;


        foreach (var filegroup in querySizeGroups)
        {
            Console.WriteLine(filegroup.Key.ToString() + "00000");
            foreach (var item in filegroup)
            {
                Console.WriteLine("\t{0}: {1}", item.Name, item.Length);
            }
        }

2.1.5. 디렉터리 트리의 중복 파일 쿼리
 첫 번째 쿼리에서는 간단한 키를 사용하여 일치하는 항목을 확인(이름은 같지만 내용은 다를 수 있는 파일임)
 두 번째 쿼리에서는 복합 키를 사용하여 FileInfo 개체의 세 가지 속성에 대한 일치 여부를 확인
class QueryDuplicateFileNames
{
    static void Main(string[] args)
    {  
        // Uncomment QueryDuplicates2 to run that query.
        QueryDuplicates();           
        // QueryDuplicates2();

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    static void QueryDuplicates()
    {
        // Change the root drive or folder if necessary
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);

        // used in WriteLine to keep the lines shorter
        int charsToSkip = startFolder.Length;

        // var can be used for convenience with groups.
        var queryDupNames =
            from file in fileList
            group file.FullName.Substring(charsToSkip) by file.Name into fileGroup
            where fileGroup.Count() > 1
            select fileGroup;

        // Pass the query to a method that will
        // output one page at a time.
        PageOutput<string,string>(queryDupNames);
    }

    // A Group key that can be passed to a separate method.
    // Override Equals and GetHashCode to define equality for the key.
    // Override ToString to provide a friendly name for Key.ToString()
    class PortableKey
    {
        public string Name { get; set; }
        public DateTime CreationTime { get; set; }
        public long Length {get;  set;}

        public override bool Equals(object obj)
        {
            PortableKey other = (PortableKey)obj;
            return other.CreationTime == this.CreationTime &&
                   other.Length == this.Length &&
                   other.Name == this.Name;
        }

        public override int GetHashCode()
        {
            string str = String.Format("{0}{1}{2}", this.CreationTime, this.Length, this.Name);
            return str.GetHashCode();
        }
        public override string ToString()
        {
            return String.Format("{0} {1} {2}", this.Name, this.Length, this.CreationTime);
        }
    }
    static void QueryDuplicates2()
    {
        // Change the root drive or folder if necessary.
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\Common7";

        // Make the the lines shorter for the console display
        int charsToSkip = startFolder.Length;

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);

        // Note the use of a compound key. Files that match
        // all three properties belong to the same group.
        // A named type is used to enable the query to be
        // passed to another method. Anonymous types can also be used
        // for composite keys but cannot be passed across method boundaries
        //
        var queryDupFiles =
            from file in fileList
            group file.FullName.Substring(charsToSkip) by
                new PortableKey{ Name=file.Name, CreationTime=file.CreationTime, Length=file.Length } into fileGroup
            where fileGroup.Count() > 1

            select fileGroup;

        var list = queryDupFiles.ToList();

        int i = queryDupFiles.Count();

        PageOutput<PortableKey, string>(queryDupFiles);              
    }


    // A generic method to page the output of the QueryDuplications methods
    // Here the type of the group must be specified explicitly. "var" cannot
    // be used in method signatures. This method does not display more than one
    // group per page.
    private static void PageOutput<K,V>(IEnumerable<System.Linq.IGrouping<K, V>> groupByExtList)
    {
        // Flag to break out of paging loop.
        bool goAgain = true;

        // "3" = 1 line for extension + 1 for "Press any key" + 1 for input cursor.
        int numLines = Console.WindowHeight - 3;

        // Iterate through the outer collection of groups.
        foreach (var filegroup in groupByExtList)
        {
            // Start a new extension at the top of a page.
            int currentLine = 0;

            // Output only as many lines of the current group as will fit in the window.
            do
            {
                Console.Clear();
                Console.WriteLine("Filename = {0}", filegroup.Key.ToString() == String.Empty ? "[none]" : filegroup.Key.ToString());

                // Get 'numLines' number of items starting at number 'currentLine'.
                var resultPage = filegroup.Skip(currentLine).Take(numLines);

                //Execute the resultPage query
                foreach (var fileName in resultPage)
                {
                    Console.WriteLine("\t{0}", fileName);
                }

                // Increment the line counter.
                currentLine += numLines;

                // Give the user a chance to escape.
                Console.WriteLine("Press any key to continue or the 'End' key to break...");
                ConsoleKey key = Console.ReadKey().Key;
                if (key == ConsoleKey.End)
                {
                    goAgain = false;
                    break;
                }
            } while (currentLine < filegroup.Count());

            if (goAgain == false)
                break;
        }
    }


    // This method assumes that the application has discovery
    // permissions for all folders under the specified path.
    static IEnumerable<System.IO.FileInfo> GetFiles(string path)
    {
        if (!System.IO.Directory.Exists(path))
            throw new System.IO.DirectoryNotFoundException();

        string[] fileNames = null;
        List<System.IO.FileInfo> files = new List<System.IO.FileInfo>();

        fileNames = System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories);
        foreach (string name in fileNames)
        {
            files.Add(new System.IO.FileInfo(name));
        }
        return files;
    }
}

2.1.6. 폴더의 파일 내용 쿼리  

        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);

        string searchTerm = @"Visual Studio";

        // Search the contents of each file.
        // A regular expression created with the RegEx class
        // could be used instead of the Contains method.
        // queryMatchingFiles is an IEnumerable<string>.
        var queryMatchingFiles =
            from file in fileList
            where file.Extension == ".htm"
            let fileText = GetFileText(file.FullName)
            where fileText.Contains(searchTerm)
            select file.FullName;

        // Execute the query.
        Console.WriteLine("The term \"{0}\" was found in:", searchTerm);
        foreach (string filename in queryMatchingFiles)
        {
            Console.WriteLine(filename);
        }

3. LINQ to XML
http://msdn.microsoft.com/ko-kr/library/bb387098.aspx
DOM(문서 개체 모델) XML 프로그래밍 인터페이스와 유사.
LINQ to XML의 쿼리 기능은 기능 면에서(구문 면에서는 아니지만) XPath 및 XQuery와 유사.
클래스들

3.1. LINQ to XML과 DOM 비교
LINQ to XML과 현재 주로 사용되는 XML 프로그래밍 API인 W3C DOM(문서 개체 모델)의 몇 가지 주요 차이점

3.1.1. W3C DOM에서는 상향식으로 XML 트리를 빌드. 즉, 문서를 만들고 요소를 만든 다음 요소를 문서에 아래코드와 같이 추가 하는 형식이지만
LINQ to XML에서 함수 생성을 사용하여 훨씬 직관적인 코드를 생성할 수 있다.
 예) DOM의 Microsoft 구현인 XmlDocument를 사용하여 XML 트리를 만드는 일반적인 방법
XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
XmlElement phone1 = doc.CreateElement("Phone");
phone1.SetAttribute("Type", "Home");
phone1.InnerText = "206-555-0144";       
XmlElement phone2 = doc.CreateElement("Phone");
phone2.SetAttribute("Type", "Work");
phone2.InnerText = "425-555-0145";       
XmlElement street1 = doc.CreateElement("Street1");       
street1.InnerText = "123 Main St";
XmlElement city = doc.CreateElement("City");
city.InnerText = "Mercer Island";
XmlElement state = doc.CreateElement("State");
state.InnerText = "WA";
XmlElement postal = doc.CreateElement("Postal");
postal.InnerText = "68042";
XmlElement address = doc.CreateElement("Address");
address.AppendChild(street1);
address.AppendChild(city);
address.AppendChild(state);
address.AppendChild(postal);
XmlElement contact = doc.CreateElement("Contact");
contact.AppendChild(name);
contact.AppendChild(phone1);
contact.AppendChild(phone2);
contact.AppendChild(address);
XmlElement contacts = doc.CreateElement("Contacts");
contacts.AppendChild(contact);
doc.AppendChild(contacts);
이 코딩 스타일은 XML 트리의 구조에 대한 많은 정보를 시각적으로 제공하지 않는다.
LINQ to XML에서는 이러한 XML 트리 생성 방법을 지원하며 추가적으로 다음과 같이
함수 생성에서는 XElement 및 XAttribute 생성자를 사용하여 XML 트리를 빌드하는 방법을 제공

비교) LINQ to XML에서 함수 생성을 사용하여 동일한 XML 트리를 생성하는 방법
XElement contacts =
    new XElement("Contacts",
        new XElement("Contact",
            new XElement("Name", "Patrick Hines"),
            new XElement("Phone", "206-555-0144",
                new XAttribute("Type", "Home")),
            new XElement("phone", "425-555-0145",
                new XAttribute("Type", "Work")),
            new XElement("Address",
                new XElement("Street1", "123 Main St"),
                new XElement("City", "Mercer Island"),
                new XElement("State", "WA"),
                new XElement("Postal", "68042")
            )
        )
    );
3.1.2 LINQtoXML에서는  바로 위 코드와 같이  LINQ XML 요소(XElement)로 직접 XML핸들링이 가능하다.
XML 파일에서 T:System.Xml.Linq.XElement 개체를 직접 로드도 가능
T:System.Xml.Linq.XElement 개체를 파일이나 스트림으로 serialize가능


반면에 W3C DOM에서는 아래코드와 같이 XML 문서가 XML 트리의 논리 컨테이너로 사용
XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
doc.AppendChild(name);
여러 문서에서 요소를 사용하려면 여러 문서의 노드를 가져와야 하지만 LINQ to XML에서는 이러한 복잡한 작업이 필요 없다.
LINQ to XML을 사용할 때 문서의 루트 수준에서 주석이나 처리 명령을 추가하려는 경우에만 XDocument 클래스를 사용.

3.1.3 LINQ to XML에서는 이름 및 네임스페이스의 처리가 간단하다.
기존 DOM 프로그래밍에서는 이름, 네임스페이스 및 네임스페이스 접두사의 처리는 XML 프로그래밍의 복잡한 부분.
LINQ to XML에서는 네임스페이스 접두사를 처리하는 요구 사항을 제거하여 이름과 네임스페이스를 단순화.
네임스페이스 접두사를 제어할 수 있다.
네임스페이스 접두사를 명시적으로 제어하지 않을경우
LINQ to XML에서는 serialize할 때 네임스페이스 접두사를 할당하거나, 기본 네임스페이스를 사용하여 serialize해야한다.
기본 네임스페이스가 사용되는 경우 생성되는 문서에는 네임스페이스 접두사가 없다.
기존 DOM 프로그래밍 방식에서는 노드의 이름을 변경할 수 없다.
대신 새 노드를 만들고 모든 자식 노드를 새 노드에 복사해야 하므로 원래 노드 ID가 손실됩니다.
LINQ to XML에서는 노드에서 XName 속성을 설정할 수 있도록 하여 이 문제를 방지합니다.

3.1.3.1. XML 네임스페이스 작업(네임스페이스 접두사 제어)
 LINQ to XML에서 XML 이름을 나타내는 클래스는 XName
 - 네임스페이스를 사용하여 문서 만들기(C#)(LINQ to XML)

 예1) 네임스페이스가 하나 포함된 문서를생성. 기본적으로 LINQ to XML은 기본 네임스페이스를 사용하여 이 문서를 serialize
  // Create an XML tree in a namespace.
XNamespace aw = "http://www.adventure-works.com";
XElement root = new XElement(aw + "Root", new XElement(aw + "Child", "child content"));
Console.WriteLine(root);
결과)
<Root xmlns="http://www.adventure-works.com">
  <Child>child content</Child>
</Root>

예2) 네임스페이스 접두사가 포함된 네임스페이스를 선언
// Create an XML tree in a namespace, with a specified prefix
XNamespace aw = "http://www.adventure-works.com";
XElement root = new XElement(aw + "Root",
    new XAttribute(XNamespace.Xmlns + "aw", "http://www.adventure-works.com"),
    new XElement(aw + "Child", "child content")
);
Console.WriteLine(root);
결과)
<aw:Root xmlns:aw="http://www.adventure-works.com">
  <aw:Child>child content</aw:Child>
</aw:Root>

예3)두 네임스페이스가 포함된 문서를 만드는 방법
두 네임스페이스 중 하나는 기본 네임스페이스이고 다른 하나는 접두사가 포함된 네임스페이스
루트 요소에 네임스페이스 특성을 포함하면 http://www.adventure-works.com이 기본 네임스페이스가 되도록 네임스페이스가 serialize되고
www.fourthcoffee.com이 "fc" 접두사를 사용하여 serialize됩니다.
기본 네임스페이스를 선언하는 특성을 만들려면 네임스페이스 없이 이름이 "xmlns"인 특성을 만듭니다.
특성 값은 기본 네임스페이스 URI입니다.
// The http://www.adventure-works.com namespace is forced to be the default namespace.
XNamespace aw = "http://www.adventure-works.com";
XNamespace fc = "www.fourthcoffee.com";
XElement root = new XElement(aw + "Root",
    new XAttribute("xmlns", http://www.adventure-works.com), //기본 네임스페이스가 된다.
    new XAttribute(XNamespace.Xmlns + "fc", "www.fourthcoffee.com"),
    new XElement(fc + "Child",
        new XElement(aw + "DifferentChild", "other content")
    ),
    new XElement(aw + "Child2", "c2 content"),
    new XElement(fc + "Child3", "c3 content")
);
Console.WriteLine(root);
결과)
<Root xmlns="http://www.adventure-works.com" xmlns:fc="www.fourthcoffee.com">
  <fc:Child>
    <DifferentChild>other content</DifferentChild>
  </fc:Child>
  <Child2>c2 content</Child2>
  <fc:Child3>c3 content</fc:Child3>
</Root>

예4)네임스페이스 접두사가 있는 두 가지 네임스페이스가 포함된 문서를 만들기
XNamespace aw = "http://www.adventure-works.com";
XNamespace fc = "www.fourthcoffee.com";
XElement root = new XElement(aw + "Root",
    new XAttribute(XNamespace.Xmlns + "aw", aw.NamespaceName),
    new XAttribute(XNamespace.Xmlns + "fc", fc.NamespaceName),
    new XElement(fc + "Child",
        new XElement(aw + "DifferentChild", "other content")
    ),
    new XElement(aw + "Child2", "c2 content"),
    new XElement(fc + "Child3", "c3 content")
);
Console.WriteLine(root);
결과)
<aw:Root xmlns:aw="http://www.adventure-works.com" xmlns:fc="www.fourthcoffee.com">
  <fc:Child>
    <aw:DifferentChild>other content</aw:DifferentChild>
  </fc:Child>
  <aw:Child2>c2 content</aw:Child2>
  <fc:Child3>c3 content</fc:Child3>
</aw:Root>

예5)확장된 이름이 포함된 문자열을 전달하여 위와 동일한 결과얻기
{}안의 내용을 파싱해야하므로 성능이 명시적으로 XNamespace를 선언하는 경우보다 떨어진다.
// Create an XML tree in a namespace, with a specified prefix
XElement root = new XElement("{http://www.adventure-works.com}Root",
    new XAttribute(XNamespace.Xmlns + "aw", "http://www.adventure-works.com"),
    new XElement("{http://www.adventure-works.com}Child", "child content")
);
Console.WriteLine(root);
결과)
<aw:Root xmlns:aw="http://www.adventure-works.com">
  <aw:Child>child content</aw:Child>
</aw:Root>

3.1.3.2. C#에서 기본 네임스페이스 범위(LINQ to XML)
XML 트리에 나타나는 기본 네임스페이스는 쿼리의 범위에 포함되지 않는다.
기본 네임스페이스에 있는 XML을 사용하는 경우 XNamespace 변수를 선언하고 로컬 이름과 결합하여
쿼리에서 사용할 정규화된 이름을 만들어야만 쿼리식에서 사용할 수 있다.

예1)집합에서는 기본 네임스페이스의 XML이 로드되지만 적절하지 않게 쿼리되는 경우의 예
XElement root = XElement.Parse(
@"<Root xmlns='http://www.adventure-works.com'>
    <Child>1</Child>
    <Child>2</Child>
    <Child>3</Child>
    <AnotherChild>4</AnotherChild>
    <AnotherChild>5</AnotherChild>
    <AnotherChild>6</AnotherChild>
</Root>");
IEnumerable<XElement> c1 =
    from el in root.Elements("Child")
    select el;
Console.WriteLine("Result set follows:");
foreach (XElement el in c1)
    Console.WriteLine((int)el);
Console.WriteLine("End of result set");
결과)
Result set follows:
End of result set

예2) 집합에서는 네임스페이스의 XML을 쿼리할 수 있도록 필요한 수정을 하는 방법을
XElement root = XElement.Parse(
@"<Root xmlns='http://www.adventure-works.com'>
    <Child>1</Child>
    <Child>2</Child>
    <Child>3</Child>
    <AnotherChild>4</AnotherChild>
    <AnotherChild>5</AnotherChild>
    <AnotherChild>6</AnotherChild>
</Root>");
XNamespace aw = "http://www.adventure-works.com";
IEnumerable<XElement> c1 =
    from el in root.Elements(aw + "Child") //명시적으로 지정.
    select el;
Console.WriteLine("Result set follows:");
foreach (XElement el in c1)
    Console.WriteLine((int)el);
Console.WriteLine("End of result set");
결과)
Result set follows:
1
2
3
End of result set

3.1.4 XML을 로드하기 위한 정적 메서드 지원 
예) 파일에서 XML 로드
XElement booksFromFile = XElement.Load(@"books.xml");
Console.WriteLine(booksFromFile);

3.1.5 DTD 구문에 대한 지원 제거  
LINQ to XML에서는 엔터티와 엔터티 참조에 대한 지원 기능을 제거하여 XML 프로그래밍을 더욱 단순화.  

3.1.6 조각에 대한 지원   
LINQ to XML에서는 XmlDocumentFragment 클래스와 동일한 항목을 제공하지만 대부분의 경우에 XmlDocumentFragment 개념은 XNode의 IEnumerable<(Of <(T>)>)이나 XElement의 IEnumerable<(Of <(T>)>)로 형식화된 쿼리의 결과에 의해 처리될 수 있다.

3.1.7 XPathNavigator에 대한 지원  
LINQ to XML에서는 System.Xml.XPath 네임스페이스의 확장 메서드를 통해 XPathNavigator를 지원.
System.Xml.XPath..::.Extensions 클래스의 멤버함수를 이용

3.1.7.1 Extensions..::.CreateNavigator 메서드
XNode에 대해 XPathNavigator를 만듬.
이 메서드에서 반환되는 XPathNavigator를 사용하여 XML 트리를 편집할 수 없다. (CanEdit 속성은 false로 반환).
XDocumentType 노드에 대해 XPathNavigator를 만들 수 없다.(문서형식(XDocumentType)은 XPath 데이터 모델과 관련이 없다)
네임스페이스 선언은 왼쪽에서 오른쪽으로 보고.
XmlDocument 네임스페이스는 오른쪽에서 왼쪽으로 보고.
이 메서드에서 반환되는 탐색기에 대해 MoveToId 메서드는 지원되지 않음.
이 메서드를 사용하여 XSLT 변환가능.

 예)XML 트리를 만들고, XML 트리에서 XPathNavigator를 만들고, 새 문서를 만들고, 새 문서에 쓸 XmlWriter를 만든다.
그런 다음 XPathNavigator 및 XmlWriter를 변환에 전달하여 XSLT 변환을 호출할 수 있다.
변환이 완료된 후 새 XML 트리는 변환 결과로 채운다.

XSLT 변환을 수행하려면 XmlReader 또는 XPathNavigator를 사용.
XmlReader를 사용할 때 더 빨리 실행되는 변환도 있고, XPathNavigator를 사용할 때 더 빨리 실행되는 변환도 있습니다.

string xslMarkup = @"<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
    <xsl:template match='/Parent'>
        <Root>
            <C1><xsl:value-of select='Child1'/></C1>
            <C2><xsl:value-of select='Child2'/></C2>
        </Root>
    </xsl:template>
</xsl:stylesheet>";

XDocument xmlTree = new XDocument(
    new XElement("Parent",
        new XElement("Child1", "Child1 data"),
        new XElement("Child2", "Child2 data")
    )
);

XDocument newTree = new XDocument();
using (XmlWriter writer = newTree.CreateWriter()) {
    // Load the style sheet.
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load(XmlReader.Create(new StringReader(xslMarkup)));

    // Execute the transform and output the results to a writer.
    xslt.Transform(xmlTree.CreateNavigator(), writer);
}

Console.WriteLine(newTree);
결과)
<Root>
  <C1>Child1 data</C1>
  <C2>Child2 data</C2>
</Root>

3.1.7.2 Extensions..::.XPathEvaluate 메서드
XPath 식을 평가
예) 다음 예제에서는 특성이 있는 작은 XML 트리를 만든 다음 XPathEvaluate 메서드를 사용하여 특성을 검색합니다.
String xml = "<root a='value'/>";
XDocument d = XDocument.Parse(xml);
IEnumerable att = (IEnumerable)d.XPathEvaluate("/root/@a");
Console.WriteLine(att.Cast<XAttribute>().FirstOrDefault());
결과)
a="value"

3.1.7.3 Extensions..::.XPathSelectElement 메서드
XPath 식을 사용하여 XElement를 선택
예) 작은 XML 트리를 만든 다음 XPathSelectElement를 사용하여 단일 요소를 선택
XElement root = new XElement("Root",
    new XElement("Child1", 1),
    new XElement("Child2", 2),
    new XElement("Child3", 3),
    new XElement("Child4", 4),
    new XElement("Child5", 5),
    new XElement("Child6", 6)
);
XElement el = root.XPathSelectElement("./Child4");
Console.WriteLine(el);
결과)
<Child4>4</Child4>

3.1.7.4 Extensions..::.XPathSelectElements 메서드
XPath 식을 사용하여 요소 컬렉션을 선택
예) 작은 XML 트리를 만든 다음 XPathSelectElements를 사용하여 요소 집합을 선택합
XElement root = new XElement("Root",
    new XElement("Child1", 1),
    new XElement("Child1", 2),
    new XElement("Child1", 3),
    new XElement("Child2", 4),
    new XElement("Child2", 5),
    new XElement("Child2", 6)
);
IEnumerable<XElement> list = root.XPathSelectElements("./Child2");
foreach (XElement el in list)
    Console.WriteLine(el);
결과)
<Child2>4</Child2>
<Child2>5</Child2>
<Child2>6</Child2>

3.1.8 공백 및 들여쓰기에 대한 지원   
서식이 있는 XML을 serialize하는 경우 XML 트리의 유효 공백만 유지(LINQ to XML의 기본 동작)
LINQ to XML에서는 DOM의 경우처럼 serialize된 Whitespace 노드 형식을 사용하는 대신 XText 노드로 공백을 저장.

3.1.9 주석에 대한 지원    
LINQ to XML에서 주석을 사용하여 임의의 형식에 대한 임의의 개체를 XML 트리의 XML 구성 요소와 연결
주석은 XML infoset의 일부가 아니므로 serialize되거나 deserialize되지 않는다.
아래 메서드호출(형식별로 주석을 검색가능)
AddAnnotation - XObject의 주석 목록에 개체를 추가합니다.
Annotation - 지정된 형식의 첫 번째 주석 개체를 XObject에서 가져옵니다.
Annotations -  XObject에 대한 지정된 형식의 주석 컬렉션을 가져옵니다.
RemoveAnnotations - 지정된 형식의 주석을 XObject에서 제거합니다.

예1) XElement에 주석을 추가
 public class MyAnnotation {
    private string tag;
    public string Tag {get{return tag;} set{tag=value;}}
    public MyAnnotation(string tag) {
        this.tag = tag; }} public class Program {
    public static void Main(string[] args) {  
        MyAnnotation ma = new MyAnnotation("T1");
        XElement root = new XElement("Root", "content");
        root.AddAnnotation(ma);

        MyAnnotation ma2 = (MyAnnotation)root.Annotation<MyAnnotation>();
        Console.WriteLine(ma2.Tag);
    }
}
결과)
T1

예2)  요소의 주석을 검색.
public class MyAnnotation {
    private string tag;
    public string Tag {get{return tag;} set{tag=value;}}
    public MyAnnotation(string tag) {
        this.tag = tag; }} class Program {
    static void Main(string[] args) {  
        XElement root = new XElement("Root", "content");
        root.AddAnnotation(new MyAnnotation("T1"));
        root.AddAnnotation(new MyAnnotation("T2"));
        root.AddAnnotation("abc");
        root.AddAnnotation("def");

        IEnumerable<MyAnnotation> annotationList;
        annotationList = root.Annotations<MyAnnotation>();
        foreach (MyAnnotation ma in annotationList)
            Console.WriteLine(ma.Tag);
        Console.WriteLine("----");

        IEnumerable<string> stringAnnotationList;
        stringAnnotationList = root.Annotations<string>();
        foreach (string str in stringAnnotationList)
            Console.WriteLine(str);
    }
}
결과)
T1
T2
----
abc
def

3.1.10 스키마 정보에 대한 지원
LINQ to XML에서는 System.Xml.Schema 네임스페이스의 확장 메서드를 통해 XSD 유효성 검사를 지원
XML 트리가 XSD를 준수하는지 확인할 수 있으며, PSVI(Post-Schema-Validation Infoset)를 사용하여 XML 트리를 채울 수 있다
예1) XmlSchemaSet을 만든 다음 스키마 집합에 대해 두 XDocument 개체의 유효성을 검사.
string xsdMarkup =
    @"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
       <xsd:element name='Root'>
        <xsd:complexType>
         <xsd:sequence>
          <xsd:element name='Child1' minOccurs='1' maxOccurs='1'/>
          <xsd:element name='Child2' minOccurs='1' maxOccurs='1'/>
         </xsd:sequence>
        </xsd:complexType>
       </xsd:element>
      </xsd:schema>";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsdMarkup)));

XDocument doc1 = new XDocument(
    new XElement("Root",
        new XElement("Child1", "content1"),
        new XElement("Child2", "content1")
    )
);

XDocument doc2 = new XDocument(
    new XElement("Root",
        new XElement("Child1", "content1"),
        new XElement("Child3", "content1")
    )
);

Console.WriteLine("Validating doc1");
bool errors = false;
doc1.Validate(schemas, (o, e) =>
                     {
                         Console.WriteLine("{0}", e.Message);
                         errors = true;
                     });
Console.WriteLine("doc1 {0}", errors ? "did not validate" : "validated");

Console.WriteLine();
Console.WriteLine("Validating doc2");
errors = false;
doc2.Validate(schemas, (o, e) =>
                     {
                         Console.WriteLine("{0}", e.Message);
                         errors = true;
                     });
Console.WriteLine("doc2 {0}", errors ? "did not validate" : "validated");
결과)
Validating doc1
doc1 validated

Validating doc2
The element 'Root' has invalid child element 'Child3'. List of possible elements expected: 'Child2'.
doc2 did not validate

예2) :Track('ctl00_rs1_mainContentContainer_cpe497038_c|ctl00_rs1_mainContentContainer_ctl23',this);" href="http://msdn.microsoft.com/ko-kr/library/bb387025.aspx">샘플 XML 파일: 고객 및 주문(LINQ to XML)에 있는 XML 문서가 :Track('ctl00_rs1_mainContentContainer_cpe497038_c|ctl00_rs1_mainContentContainer_ctl24',this);" href="http://msdn.microsoft.com/ko-kr/library/bb675181.aspx">샘플 XSD 파일: 고객 및 주문에 있는 스키마별로 유효한지 확인한 다음 소스 XML 문서를 수정합니다. 여기에서는 첫 번째 고객에 대한 CustomerID 특성을 변경합니다. 변경한 후에는 주문이 존재하지 않는 고객을 참조하게 되므로 XML 문서가 더 이상 유효하지 않습니다.
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", "CustomersOrders.xsd");

Console.WriteLine("Attempting to validate");
XDocument custOrdDoc = XDocument.Load("CustomersOrders.xml");
bool errors = false;
custOrdDoc.Validate(schemas, (o, e) =>
                     {
                         Console.WriteLine("{0}", e.Message);
                         errors = true;
                     });
Console.WriteLine("custOrdDoc {0}", errors ? "did not validate" : "validated");

Console.WriteLine();
// Modify the source document so that it will not validate.
custOrdDoc.Root.Element("Orders").Element("Order").Element("CustomerID").Value = "AAAAA";
Console.WriteLine("Attempting to validate after modification");
errors = false;
custOrdDoc.Validate(schemas, (o, e) =>
                     {
                         Console.WriteLine("{0}", e.Message);
                         errors = true;
                     });
Console.WriteLine("custOrdDoc {0}", errors ? "did not validate" : "validated");
결과)
Attempting to validate
custOrdDoc validated

Attempting to validate after modification
The key sequence 'AAAAA' in Keyref fails to refer to some key.
custOrdDoc did not validate


3.2. LINQ to XML과 다른 XML 기술 비교
LINQ to XML, XmlReader, XSLT, MSXML 및 XmlLite와 같은 XML 기술을비교

3.2.1 LINQ to XML 와 XmlReader
XmlReader는 캐시하지 않으며 정방향으로만 작동하는 빠른 파서.
LINQ to XML은 XmlReader를 기반으로 구현되었으며 두 기술은 밀접하게 통합되어 있다.( XmlReader를 단독으로 사용가능)

예)초당 수백 개의 XML 문서를 구문 분석할 웹 서비스를 빌드하는데 문서의 구조가 동일하여
XML의 구문을 분석하는 코드의 구현을 하나만 작성하면 되는 경우 XmlReader를 단독으로 사용할 수 있습니다.
반면에 크기가 작은 다양한 XML 문서의 구문을 분석하는 시스템을 빌드하는데 각 문서의 구조가 서로 다르면
LINQ to XML에서 제공하는 성능 향상 기능을 사용할 수 있습니다.

3.2.2 LINQ to XML 와 XSLT
LINQ to XML과 XSLT는 모두 광범위한 XML 문서 변환 기능을 제공
XSLT는 규칙 기반의 선언적 방법.
고급 XSLT 프로그래머는 상태 비저장 방법을 강조하는 함수형 프로그래밍 스타일로 XSLT를 작성.
이 경우 부작용 없이 구현되는 순수 함수를 사용하여 변환을 작성할 수 있다.
이 규칙 기반 방법 또는 함수 방법은 대부분의 개발자에게 익숙하지 않으며 배우는 데 많은 시간과 노력이 필요.

XSLT는 고성능 응용 프로그램을 생성하는 생산성이 매우 높은 시스템.
예를 들어 규모가 큰 일부 웹 회사에서는 다양한 데이터 저장소에서 가져온 XML에서 HTML을 생성하는 방법으로 XSLT를 사용.
관리되는 XSLT 엔진은 XSLT를 CLR 코드로 컴파일하며 일부 시나리오에서 네이티브 XSLT 엔진보다 성능이 훨씬 좋다.
그러나 XSLT에서는 개발자가 C# 및 Visual Basic 지식을 활용할 수 없으며 복잡하고 다른 프로그래밍 언어로 코드를 작성해야 합니다.
C#(또는 Visual Basic) 및 XSLT와 같은 통합되지 않은 두 가지 개발 시스템을 사용하면 소프트웨어 시스템을 개발하고 유지 관리하기가 더 어렵습니다.

LINQ to XML 쿼리 식을 완전히 익히고 나면 강력한 LINQ to XML 변환 기술을 쉽게 사용할 수 있다.
기본적으로 다양한 소스에서 데이터를 가져와서 XElement 개체를 동적으로 생성하고 전체 데이터를 새 XML 트리로 어셈블하는 함수 생성을 사용하여 XML 문서를 만든다.
변환을 통해 완전히 새로운 문서가 생성될 수 있다.
LINQ to XML에서는 비교적 쉽고 직관적으로 변환을 생성할 수 있으며 생성되는 코드도 쉽게 읽을 수 있다.
따라서 개발 및 유지 관리 비용이 줄어듭니다.

LINQ to XML은 XSLT를 대체하기 위한 것이 아니다.
XSLT는 여전히 복잡하고 문서 중심적인 XML(특히 문서 구조가 제대로 정의되지 않은 경우) 변환에 사용할 수 있다.

XSLT는 W3C(World Wide Web Consortium) 표준이므로 표준 기술만 사용해야 하는 요구 사항이 있는 경우 XSLT가 더 적합할 수 있다.
XSLT는 XML이므로 프로그래밍 방식으로 조작할 수 있다.

3.2.3 LINQ to XML과 MSXML 비교
MSXML은 Microsoft Windows에 포함된 XML을 처리할 수 있는 COM 기반 기술.
MSXML은 XPath 및 XSLT를 지원하는 DOM의 기본적인 구현을 제공하며 캐시하지 않는 이벤트 기반의 SAX2 파서도 포함하고 있다.
MSXML은 성능이 좋으며 대부분의 시나리오에서 기본적으로 안전.
AJAX 스타일의 응용 프로그램에서 클라이언트측 XML 처리를 수행하기 위해 Internet Explorer에서 MSXML에 액세스할 수 있다.
C++, JavaScript 및 Visual Basic 6.0을 비롯한 COM을 지원하는 모든 프로그래밍 언어에서 MSXML을 사용할 수 있다.
CLR(공용 언어 런타임) 기반의 관리 코드에서는 MSXML을 사용하지 않는 것이 좋다.

3.2.4 LINQ to XML과 XmlLite 비교
XmlLite는 캐시하지 않으며 정방향으로만 작동하는 가져오기 파서.
개발자는 주로 C++와 함께 XmlLite를 사용.
관리 코드와 함께 XmlLite를 사용하는 것은 권장되지 않는다.
XmlLite의 주요 이점은 대부분의 시나리오에서 안전하며 간단하고 빠른 XML 파서다.
 XmlLite에서 위협에 노출되는 영역은 매우 작다.
신뢰할 수 없는 문서의 구문을 분석해야 하고 서비스 거부나 데이터 노출과 같은 공격으로부터 보호하려면 XmlLite를 선택하는 것이 좋다.
XmlLite는 LINQ(통합 언어 쿼리)와 통합되지 않았으며 LINQ에 핵심적인 프로그래머 생산성 향상 기능을 제공하지 않는다.

반응형

+ Recent posts

반응형