출처 : http://techbard.tistory.com/8

testing 관련 자료를 찾을려면 실제로 거의 존재 하지 않는다.
아래 아티클은 의외의  글들이다. 현업에서 품질을 책임 지고 있는 한 사람으로서
이론과 현실이라는 딜레마에 빠지게 된다.. 위에서 요구하는 품질의 수준을 test case의 양으로만 판단 하려 들고 오로지 갯수만 늘리는데 혈안이 되어 있다.
잘못을 인식하고 있지만 어쩔수 없이 젖어들수 밖에 없는 현실에 아쉬움을.....

아래 글 출처 : http://techbard.tistory.com/8 에서 발췌 한것입니다.
삭제 요청이 있으면 바로 삭제 하겟습니다. 주인장의 허락없이 펌질한것 진심으로 사과 드립니다.

* 역자주: IEEE 소프트웨어 잡지에 이런 내용이 실리는 것에 대해서 참으로 놀라울 따름이다. 내용이 거의 소프트웨어 테스팅의 핵심 및 중요한 부분을 모두 망라하는 아티클이다! 내가 최초에 이런 아티클을 어떻게 알게 되었냐면, 그나마 소프트웨어 공학 책중에서 가장 깔끔하게 번역되고 원전에 충실한 이안 썸머빌의 "소프트웨어 공학 제 7판"에서다. 이 책의 pp. 531을 보면 레퍼런스에 언급되어 있다. 여기에 뭐라고 나와있나면...

 결점이 거의 없는 소프트웨어를 인도하는 데 매우 좋은 평판을 가지고 있는 일본 기업으로부터 시험 사례 설계 방법을 다룬 논문이다. (T. Yamaura, IEEE Software, 15(6), November 1998.)
아, 이 얼마나 극찬의 얘기인가! 이 사실에서 (물론 번역을 해보니 정말 그렇지만) 알 수 있는 건 다음과 같다고 생각한다.

  1. IEEE에 소프트웨어 테스팅 주제로 글이 실린다. (누가 IEEE 소프트웨어 과월호를 가지고 계신 분이 있다면 연락 바란다. 갠적으로 친하게 지내고 싶다! ^^)
  2. 일본 기업도 소프트웨어 테스팅에서 유명한 저명 인사는 없지만 실제적으로 매우 핵심과 이론들을 잘 사용하고 알고 있다.
  3. 이안 썸머빌 같은 유명한 공학 교수가 자기 책에 인용할 정도로 대단하다.
  4. 역시 모국어로 영어를 쓰는 사람들이 아닌 제 3 국인의 영어는 그나마 번역하기 참 평이하다. ^^

번역을 위해 잠도 안자고 여러 날을 고생했다. 고생한 역자를 생각해서 이글을 보는 분들은 다음의 내용을 지켜주셨으면 한다.

* PDF 자체는 역자가 인터넷에서 찾은 것으로 누군가 스캔을 한 것을 PDF화 한 것 같다. 이것을 재배포하는 것은 여러분들의 맘이겠지만, 번역을 해놓은 글을 다른 곳에 옮겨다 두거나 심지어 자기가 한 것처럼 하는 행동은 하지 않으셨으면 한다. (솔직히 나 이거 번역하느라 고생 많았다. ^^)
* 어딘가 번역한 내용을 옮기고 싶은 충동이 강하게 들때는 꼭 역자인 쥔장에게 문의바란다. (아니면 번역한 것 보지 않고 본인들이 직접 번역하시든지... ㅋㅋ)
* 번역한 내용을 옮기는 경우 원전 표기를 지켜 주십사 당부 드린다.

자 아래에 번역 나가신다~~

How To Design Practical Test Cases by Tsuneo Yamaura, 1998 IEEE


pp. 30


히다치 소프트웨어에서 우리 소프트웨어는 프로그램 내부의 모든 버그중 0.02 퍼센트만이 유저 사이트에서 발생하는 그런 놀라운 품질을 가졌었다. 한 개의 전형적인 프로젝트가 - 100,000 라인의 코드를 개발하기 위해 12달동안 10명의 엔지니어들이 작업하는 - 1,000개의 버그를 내재한다면, 최대 한개는 유저 사이트에서 드러날 것이다. 우리는 현대적인 툴이나 예술적인 방법론을 사용하지 않았다. 오히려 단순히 프로그램을 테스트하고 발견된 버그를 수정했을 뿐이다.


우리의 비밀은 디버깅과 테스팅을 시작하기 전에 모든 테스트 케이스들을 문서화한 것이다. 미리 작성된 테스트 케이스들은 놀라운 이득을 제공하는데, 우리의 모든 품질 보증 활동은 이 시점에서 시작한다.


그림 1은 1990년의 히다치 소프트웨어 개발 프로젝트의 각각의 단계에서 발견된 버그의 비율을 나타낸다.(좀더 최근의 데이터는 계속 수집중이지만, 이것과 극적인 차이를 보이지는 않을 것이다.) 프로젝트의 시작 이후 발견된 모든 버그중 단지 0.02 퍼센트가 고객의 사이트에서 드러났다. 그러한 높은 품질은 우리가 미리 작성된 테스트 케이스를 운용하지 않았다면, 달성할 수 없었을 것이다.


그림 1. 1990년도 프로젝트의 개발 단계 동안의 버그 발견


DOCUMENTING TEST CASES


문서화된 테스트 케이스들은 몇가지 중요한 점에서 당신의 개발 프로세스에 이익이 될 수 있다.


  • 테스트 케이스의 디자인과정은 또 다른 관점에서 스펙을 분석할 수 있는 기회를 제공한다.
  • 동일한 테스트 케이스들을 반복할 수 있다.
  • 누군가 다른 사람이 당신을 위해 테스트 케이스들을 수행할 수 있다.
  • 당신은 쉽게 테스트 케이스들의 품질을 검증할 수 있다.
  • 당신은 초기에 목표 소프트웨어의 품질을 추정할 수 있다.

A new viewpoint


테스트 케이스들은 기능적인 스펙의 또 다른 해석을 제공한다. 테스트 케이스를 디자인하는 것은 잠시간의 생각할 여지를 제공할 것인데 말하자면 다음과 같은 것이다. "아하, 내가 이런 저런 조건들을 고려하지 않았었구나. 그 스펙이 정말로 옳은 걸까?" 이런 방식으로 드러난 버그는 찾아내기 더 어렵거나 시스템 통합 단계 같은 이후 단계에서는 수정하는데 많은 시간과 비용이 필요할 것이다. 대략, 당신은 테스트 케이스를 디자인하면서 시스템의 버그의 10퍼센트를 잡아낼 수 있으며, 이것이 놀라운 이득이다.


Repeating test scenarios


당신은 모든것이 문서화되어 있다면, 쉽게 어떤 테스트 케이스들을 재반복할 수 있다. 테스트 케이스의 재사용은 버그를 재현하게하며, 이것은 발견된 버그가 올바르게 수정되었는지에 대해 확신을 가지는데 도움이 된다.


Passing the test along


당신이 테스트 조건, 입력 데이터 세트, 기대 결과을 명세화한다면, 누군가 다른 사람에게 테스트를 수행하도록 요청할 수 있다. 이것은 프로젝트 진행이 늦어진 경우에 특히 가치가 있는 것으로 판명될 것이다. 추가적인 프로그래머를 프로젝트에 추가하는 것은, 종종 스케줄을 늘어지게 하여 더 많은 지연의 원인이 된다. 왜냐하면, 그 프로젝트 엔지니어들은 새로운 투입 인원을 교육시키기 위해 소중한 시간을 들여야 하기 때문이다. 만일 테스트 케이스들이 올바르게 문서화되었다면, 새로 투입된 인원은 작성된대로 테스트 케이스들을 수행할 수 있다.


Validating test case quality


물론 당신은 소프트웨어에 구현된 모든 기능이 수행되었는지 확신하기 위해 테스트 케이스들을 테스트해야 한다. 또한, 그 테스트 케이스들이 정상, 비정상, 경계 케이스등 간에 잘 균형잡혀 있는지 점검하고, 그들의 전체적으로 충분한지 평가해야 한다. 임의나 랜덤 테스팅으로는 충분치 않을 것이다. 말하자면, 당신이 명확하게 테스트 케이스들을 문서화하지 않는다면, 당신은 그들의 품질 메트릭과 성공을 정확하게 평가할 수 없다.


Estimating software quality


만일 테스트 케이스들이 올바르게 개발되었다면, 연못속의 물고기와의 유사점을 적용함으로써 디버깅 동안에 목표 소프트웨어의 품질을 쉽게 추정할 수 있다. 즉, 당신이 1000개 중 100개의 테스트 케이스들을 수행한 이후에 4개의 버그를 발견했다면, 상식적으로 소프트웨어는 전체적으로 약 40개의 버그를 지니고 있을 것이다. 예술적인 수준의 소프트웨어 신뢰성 이론은 간단치 않다. 하지만 이런 방법은 빠르고 쉬운 추정은 소프트웨어의 품질에 대한 대강의 아이디어를 제공한다.


SCHEDULE, COST, AND PERSONNEL


당신은 이제 테스트 케이스들을 문서화하는 것이 얼마나 유용한 것인지 알았을 것이다. 하지만, 모든게 공짜는 없다. 당신은 이익을 누리기 위해서 시간, 비용, 인원을 투자해야 한다. 관건은 당신이 필요한 것이 어느정도냐 일 것이다. 여기에 약간의 통계적인 데이터를 가지고 대강의 아이디어를 설명한다.


그림 2. 매트릭스 기반의 테스트 시트.


100,000라인의 코드를 가진 C 기반의 소프트웨어를 개발하는데 10명의 엔지니어가 평균 12개월 동안 작업을 해야하는 프로젝트를 가정하면, 평균적인 프로젝트는 다음의 단계들에 12개월을 배분할 수 있다.


  • 요구사항 명세화: 2달
  • 디자인: 3달
  • 코딩: 2달
  • 디버깅: 3달
  • 테스팅 (QA팀에 의해 수행): 2달

히다치 소프트웨어에서는 프로젝트가 디버깅을 완료하면, 그 제품은 QA 부서로 보내져서, 약 2달을 사용하여 그 소프트웨어가 출시할만한가를 평가받게 한다. 테스터들이 치우침이 없고 고객의 요구사항을 이해해야 하기 때문에, 그들은 프로그래머들의 테스트 수트를 결코 재사용하지 않고, 오히려 원점에서 모든 테스트 아이템들을 재디자인한다.

테스트 케이스 밀도 즉, "얼마나 많은 테스트 케이스들이 필요할까?"는 테스팅에서 가장 중요한 엔지니어링 이슈중 하나 이다. 너무 적은 테스트 케이스들은 손쉬운 버그들을 못 찾게될 것이고, 너무 많은 테스트 케이스들은 시간의 부족을 불러올 것이다.

시행착오에 근거한 우리의 30년간의 경험적인 연구에서 적절한 테스트 케이스 밀도는 10에서 15개의 LOC당 하나의 테스트 케이스의 수준으로 모아졌다. 이것은 100,000 LOC의 제품이 약 10,000개의 테스트 케이스들을 필요로 하며, 프로그래머당 1,000개를 의미한다. 1,000개의 테스트 케이스들 중 약 100개는 코드 인스펙션 단계에서 체크될 것이고, 그들 전체는 머신 디버깅 단계에서 체크될 것이다. (이것의 의미는 코드 인스펙션 단계에서의 첫번 100개의 테스트 케이스는 머신 디버깅과 중복된다.) 우리의 연구에 기초할때 이러한 숫자들은 비현실적인 것으로 보이지 않는다. 평균적인 프로그래머는 코드 인스펙션 단계에서 100개의 테스트 케이스들을 수행하는데 2주일이 걸린다. (하루에 10개 케이스) 그리고 머신 디버깅 단계에서 1,000개의 테스트 케이스들을 수행하는데 2달이 걸린다. (하루에 25개 케이스) 열명의 프로그래머가 테스트 케이스들을 디자인하는 데는 2주일이 걸릴것이다. (프로그래머당 하루에 100개의 테스트 케이스를 가정) 이것은 전체 프로젝트에서 2.8퍼센트에 해당한다.


STEPS FOR DEBUGGING AND TESTING


시스템적인 테스팅은 6개의 핵심 절차들을 따른다.


  1. 테스트 케이스들의 집합을 디자인한다.
  2. 테스트 케이스들을 체크한다.
  3. 테스트 케이스를 기초로 코드 인스펙션을 수행한다.
  4. 테스트 케이스를 기초로 머신 디버깅을 수행한다.
  5. 디버깅 동안에 품질 관련된 데이터를 수집한다.
  6. 디버깅 동안에 데이터를 분석한다.

Designing test cases


테스트 케이스를 디자인하는데 유일한 한가지 규칙이 있다. 모든 기능을 커버해야 하지만, 너무나 많은 케이스들을 만들지 말라는 것이다. 우리는 매트릭스 기반의 테스트 시트를 사용해 필요한 모든 기능을 수행해 보았고, 동치 분할과 경계값 분석을 적용해 중복적인 테스트 케이스들을 제거했다. 필요할 때는 상태 변이 모델, 결정 테이블, 데이터흐름 모델에 기반한 다른 테스트 방법도 사용했다.

그림 2는 우리가 적용한 매트릭스 기반의 테스트 시트를 나타낸다. 첫째 단계는 모든 조건들을 아이템화하고 그 다음 가능한 모든 조합들을 고려하는 것이다. 이런 단계는 중요한 결점들을 드러나게 하는데, 왜냐하면 이런 방식으로 테스트 케이스들을 디자인하는 것은 또 다른 모델에 기초해서 소프트웨어를 재디자인하는 것을 의미한다. 말하자면, 결정 테이블인 것이다.


그림 1의 모든 테스트 케이스는 테스트 디자인을 하는 동안에 버그를 드러내지 못하는 것을 제외하고는 각각의 기대 결과들을 가지고 있다는 것을 주목하라. 또한 당신은 테스트 케이스가 정상, 비정상, 경계 케이스들을 체크하는지에 대해서 명시할 필요가 있다. 이것은 테스트 케이스들의 품질을 평가하는데 필수적이다. 그리고 당신은 테스팅 순서를 나타내는 테스팅 우선순위를 명시해야 한다.


1970년대 초반에 우리는 테스트 케이스의 단계조건을 기술하는데 자연어를 적용했다. 예를 들면,


  • 양식에 있는 사람이 65세이거나 더 많을때:
  • 사람의 연간 수입이 $10,000 또는 적을때:
  • 사람이 A-1지역에 살때: ... (조건들의 중첩이 더 깊어진다)

이러한 접근법은 종종 우리로 하여금 다양한 조건의 조합(또는 테스트 아이템간에 놓침)을 간과하게 만들었다. 우리는 1970년대 중반부터는 매트릭스 기반의 테스트 디자인으로 이전했다.


동치 분할로 잘 알려져 있는 테스팅 기법은 동일 도메인을 대표하는 단일한 값을 사용하는 것이다. 나이에 따른 입장료의 예를 들면, 6세이하는 입장료를 받지 않으며, 12세까지는 $5, 18세까지는 $8 그리고 19세 이상은 $10이라고 가정하자. 각각의 도메인에서 당신은 도메인 0<=age<=6에 대해서는 "2세", 도메인 6<age<=12는 "10세", 도메인 12<age<=18은 "14세", 도메인 18<age에는 "43세"의 테스트 케이스들을 선정할 수 있을 것이다. "43세"와 "50세"를 선정하는 것은 각각이 화이트박스 테스팅에 대해서 서로 다른 도메인을 나타내는 경우 이외에는 과도한 것이다.


경계값 분석은 잘 알려져 있는 또 다른 테스팅 기법으로 버그들이 도메인의 경계에 존재하는 경향이 있다는 아이디어를 근거로 한다. 따라서, 위의 입장료 예에서는 -1, 0, 6, 7, 12, 13, 18, 19의 나이를 테스트할 필요가 있다.


우리는 경험적인 연구를 통해 아래와 같은 테스트 케이스 디자인 기준 (또는 교훈)을 도출하였다.


  • 앞에서도 언급했듯이 테스트 케이스의 최적화되고 실용적인 밀도는 10에서 15 LOC당 한개이다. 일반적으로 언어 처리기는 배치 프로그램보다 더 많은 테스트 케이스들을 필요로 한다.(12 LOC 당 약 한 개의 테스트 케이스) 그리고, 온라인 프로그램은 언어 처리기보다 더 많은 수를 필요로 한다. (10 LOC당 한 개)
  • 화이트 박스 테스팅의 관점에서는 IF 구문의 숫자가 LOC 보다 더 나은 지표를 제공한다. 왜냐하면, 이것이 프로그램 내의 실행 가능한 경로의 숫자와 직접적으로 연관되어 있기 때문이다. 가장 에러가 잘 유발되는 구조는 루프이다. 화이트 박스 테스팅에서 당신은 0, 1, 2, 평균적인 숫자, max-1, max, max+1개의 횟수로 반복을 테스트해야 한다.
  • 기본적이고 정상적인 케이스들은 전체 테스트 케이스들 중에 60퍼센트 이하를 구성하고, 경계나 제한 케이스들은 10퍼센트 미만, 에러 케이스들은 15퍼센트 그리고 환경적인 테스트 케이스들(다른 OS에서는 프로그램이 어떻게 동작하는지, 성능 요구사항)은 15퍼센트를 구성해야 한다.
  • 마지막 점검으로서 우리는 48시간 지속운용 테스트를 수행했다. 당신이 제공해야 하는 모든 것은 동일한 기본 기능들을 무한히 재반복하는 테스트 수트이다. 이러한 테스트는 메모리 릭, 데드락 그리고 연결 타임아웃과 연관된 많은 버그들을 드러나게 한다.

그림 3. 테스트 수행과 버그 발견의 예


몇가지 팁이 당신이 성공적이고 효과적으로 테스트 케이스들을 디자인하는데 도움이된다.


  • 너무 많은 테스트 케이스들을 디자인하지 말라. 특히 문법 테스팅(syntax testing)에 그렇다. 만일 당신이 12개중 6개 파라메터의 에러 조합을 고려하고 있다면, 최종적으로는 수천개의 테스트 케이스들을 겪게될 것이다. 이것은 수행하는데 몇 달이 걸릴수도 있다. 현실은 누군가(대부분은 당신이 되겠지만)가 테스트를 수행해야 한다는 것이다. 이런 상황을 고려하고 디자인하면 계획된 기간 안에 완료될 수 있을 것이다.
  • 유사한 소프트웨어가 개발되었던 이전 프로젝트를 참조하라. 그 프로젝트가 테스트 수트를 가지고 있다면, 반드시 무슨일이 있더라도 그것을 획득하라. 당신이 그것들을 재사용할 수 없을지라도, 당신에게 통찰력을 제공해 줄 것이다.
  • 당신이 어떤 테스트 케이스들을 코드 인스펙션 단계에서 실행할 것인지, 머신 체킹 단계에서는 어떤 테스트 케이스들을 실행할 것인지 지정하라. 코드 인스펙션에서는 전체 테스트 케이스들중 약 10퍼센트만 사용하는 것을 추천한다. 이렇게 되면, 소프트웨어의 주요한 지점들을 추적하기 시작하는데 도움이 된다.
  • 소프트웨어 엔지니어는 본인들이 잘 알고 있는 기능들에 대해서는 너무 많은 테스트 케이스를 만들고, 친숙하지 않은 기능들에 대해서는 너무 적게 만드는 경향이 있다. 이런 수치가 비정상적인 것인지 판단하기 위해 LOC에 기반하거나 IF문들의 수를 가지고 테스트 케이스 수와 비교하라.

Checking test case quality


테스트 케이스들은 당연히 테스트되어야 한다. 당신의 테스트 케이스 디자인이 완료되면, 그것의 정확성과 적절성을 다음에 근거하여 평가한다.


  • 테스트 케이스들이 모든 기능들을 커버하는가
  • 정상, 비정상, 경계 그리고 환경적인 테스트 케이스들 간의 균형이 맞는가
  • 코드 인스펙션(제공하기 어려운 조건들에 대한 체크 그리고 쉽고 효율적으로 수정할 수 있는 버그들의 발견을 가능하게 하는)과 머신 실행(테스팅 시간을 소모하는)간의 균형이 맞는가
  • 블랙 박스와 화이트 박스 테스팅 간의 균형이 맞는가
  • 기능적인 테스트와 성능 테스트 간의 균형이 맞는가

Code inspection


우리의 경험적인 연구는 모든 버그중 21.5퍼센트가 이 단계에서 발견되었다고 나타낸다. 이 전체 숫자중 나는 대강 코드 인스펙션에서 절반, 테스트 케이스 디자인 과정에서 나머지가 드러났다고 추정한다. 코드 인스펙션에서와 마찬가지로 테스트 케이스들 중 10퍼센트를 체크하기 위해 디버깅 시간의 25에서 33퍼센트를 할당하는 것을 권장한다.


이 단계에서 발견된 결점들을 기록한다. 이것은 어떤 버그들이 수정되지 않고 남아 있는지, 어디에, 어떤 유형의 버그가 될 것인지, 어떤 모듈이 더 많은 결점을 지니고 있는지를 말해줄 것이다. 당신이 테스트 케이스들을 성공적으로 수행했다면, 완료한 날짜를 테스트 케이스 시트에 기록한다.


그림 4. 테스트 진행의 분석


Machine debugging


이 단계는 간단하다. 단지 실제 머신(또는 시뮬레이터)에서 테스트 케이스를 수행하고 그 결과 기록이 통과인지 실패인지 유지하는 것이다. 테스트 케이스가 하나의 결점을 드러냈다면 누가 무엇을, 언제, 버그의 증상, 그리고 테스트 케이스 ID와 같은 정보를 기록하여 버그 리포트를 완성한다. 이러한 정보 없이는 버그가 출현할 때까지 이미 수정된 버그라고 생각하게 될 것이다.


머신 디버깅을 시작하기 전에, 가능하다면 테스트 수트로서 테스트 케이스들을 구현한다. 테스트 수트란 자동적으로 테스트 케이스들을 수행하고 실제 결과와 기대 결과를 비교하여 "통과"인지 "실패"인지를 판단해 주는 프로그램이다. 이것은 많은 이점을 제공한다. 비록 테스트 수트 구현에 시간이 걸려도(테스트 수트의 엔진의 작업량은 작다. 작업중 95퍼센트 이상은 실행 커맨드의 제공과 기대 결과를 정의하는데 사용된다.) 당신이 자리에 없는 동안 컴퓨터가 프로그램을 디버그하도록 함으로써 한 번 완성되고 나면, 대단히 많은 시간이 절약된다. 멍청하지만 비용이 많이드는 타이핑 에러들은 완전히 제거될 수 있고, 당신이 최종 출시 일자를 맞춰야 하는데 프로그램은 여전히 변경되고 버그 수정되어야 할 때, 소프트웨어 개발의 마지막 단계에서 기능적인 악화를 체크하는 도구로서 테스트 수트를 사용할 수 있다.


테스트 수트를 구현할 때 기억해야 할 중요한 한가지 사실은, 다음 테스트 케이스로 넘어갈 때 모든 데이터가 재초기화 되었는지 확인해야 한다는 것이다. 하나의 테스트 케이스가 실행되지 않았다면, 이전 케이스의 버그가 테스트 수트를 종료시켰기 때문이다. 앞부분의 버그가 이어지는 버그를 가려버릴 수 있다. 그리고 이러한 것들은 이전 버그가 완전하게 수정되지 않으면 드러나지 않을 것이다.


Collect data for quality analysis


문서화된 테스트 케이스들의 유용성을 극대화하기 위해서는 발견된 모든 결점들의 기록을 유지해야 한다. 그들의 증상, 심각성, 누가 발견했는지 그리고 언제, 어떤 테스트 케이스 ID에 의해 발견되었는지, 그것이 존재하는 모듈이 무엇인지, 언제 수정되었는지가 이에 해당된다.


마찬가지로 프로젝트 매니저는 성공적으로 수행된 테스트 케이스의 수, 발견되고 수정된 수에 대한 일일 기록을 수집해야 한다. 이것들은 일일 정보를 그래프로 그릴 수 있게 하고 그림 3과 같이 더많은 테스트 케이스들을 수행하기 위한 목표 계획을 세울수 있게 한다.


Analyze the data


그림 3과 같은 다이어그램은 소프트웨어 품질과 예상 출시일을 제어하는데 유용한 정보를 제공한다. 당신이 이러한 데이터를 어떻게 해석해야 하나?


첫째, 성공적으로 실행된 테스트 케이스들의 목표 수치와 실제 수치, 발견된 버그의 목표 수치와 실제 수치의 차이를 분석한다. 이것은 이전 디버깅 단계에서의 문제점을 집어내는데 도움을 줄 것이다. 그림 4는 그러한 4개의 다이어그램을 보여준다. 그림 4a는 제어 목표를 나타내며, 그림 4b는 소수의 테스트 케이스를 실행해서 많은 버그가 발견됨을 나타낸다. 이것은 대개 이전 프로세스로 부터 원인이 있는데, 모듈 디자인 같은 단계가 올바르게 완료되지 않았거나 테스트되지 않았음을 나타낸다. 매우 심각한 경우는 디버깅을 중단하고 이전 프로세스로 회귀해야 한다. 그림 4c는 프로그래머가 계획한대로 테스트 케이스들을 수행할 수 없음을 나타낸다. 그러므로, 아주 소수의 버그만이 발견되었다. 이런 경우 프로그래머가 디버깅을 할 수 없음을 의미하는데 이런 경우 그들이 디버깅에 친숙해질때까지 전문가에게 감독을 하라고 요청한다. 그림 4d는 두 가지 가능성이 있다. 테스트 케이스들이 적절하게 버그를 발견해 내지 못한 것이거나 소프트웨어가 많은 버그를 지니고 있지 않은 경우이다. 전자는 물론 후자보다 가능성이 많다. 개선책은 더 효과적인 테스트 케이스들을 만드는 것이다.


둘째, 만일 당신이 연속적으로 10일동안 10개의 버그를 찾았다면, 오늘이 당신이 10개의 버그를 찾은 마지막 날이 될 가능성은 없다. 버그 발생은 결코 갑자기 멈추는 법이 없고 오히려 서서히 감소한다. 버그 누적 커브로 부터, 당신은 언제 커브가 평평해지는지, 당신이 달성해야 하는 품질 목표의 일자는 언제인지 추정할 수 있다. 우리는 더 정확한 추정을 위해서 Gompertz 커브나 Logistic 커브를 사용했다 하지만 직관적인 관찰만으로도 강력한 도구가 될 수 있다.


셋째, 버그 리포트로 부터의 통계적인 데이터는, 예를 들어 가장 일반적인 버그가 무엇인지 또는 어떤 모듈이 에러 경향이 있는지를 보여줄 수 있다. 이러한 종류의 소프트웨어 메트릭은 "사실에 기반한" 품질 제어 파라메터로 작용한다.


마지막으로, 당신이 어떤 종류의 결점을 프로그래머들이 만드는 경향이 있는지 분석하게 하여 패턴을 따르는 에러들을 찾게 한다. 메모리 릭, 파일을 닫지 않은 상태로 두는 것 등과 같은 버그 유형을 말한다. 이것은 아마 프로젝트 매니저의 업무가 될 것이다. 하지만, 이것이 좀더 복잡한 문화적이고 조직적인 이슈들의 존재를 드러내게 할 수 있다.


프로젝트가 문서화된 테스트 케이스들과 미리 작성된 테스트 케이스들에 기반한 QA 접근법을 운용하지 않으면 어떤 일이 벌어질까? 1,000개의 버그 중 코드 인스펙션 동안에 단지 5퍼센트만 발견되었다고 가정하고(그림 1의 버그 분포에 기반하면 215개 버그), 머신 디버깅(631개 버그)은 발견하지 못하면(43개 버그), 개발 라이프사이클의 끝 부분에 나타나거나 더 심한 경우 고객의 사이트에서 나타날 것이다. 우리의 데이터는 이러한 결점 각각을 발견하고 수정하는데 2~3일만 요구되었다는 점을 나타낸다. 이것은 당신이 출시에 원하는 수준으로 제품 품질을 올리는데 추가적으로 86~130일을 필요로 함을 의미한다. 우리는 테스트 케이스들을 문서화하는데 2주를 사용했고, 또 다른 2주는 디버깅 단계에서 (이미 작성된) 테스트 케이스들을 수행하는데 사용했다. 결국, 4주동안의 작업이 4~6달을 절약하게 한 것이다. 이것만으로도 테스트 케이스 문서화의 유용성이 정당화된다.


REFERENCES


1. A. Onoma and T.Yamaura, "Practical Steps Toward Quality Development", IEEE Software, Sept. 1995,pp.68-77.

2. G.J.Myers, The Art of Software Testing,John Wiley & Sons, NewYork, 1979

3. T.Yamaura, "Standing Naked in the Snow", American Programmer, Vol. 5, No. 1, 1992,pp. 2-9.

4. T.Yamaura, "Why Johny Can't Test", IEEE Software, Mar./Apr. 1998, pp. 113-115


About the Author


Tsuneo Yamaura is a senior engineer at Hitachi Software Engineering. His research interests include testing methodologies, software metrics, development paradigms, software modeling, and CASE.

Yamaura received a BS in electrical engineering from Himeji Institute of Technology and was a visiting scholar at the University of California, Berkeley. He is a member of IEEE Computer Society and ACM.


Address questions about this article to Yamaura at Hitachi Software Engineering, 6-81 Onoe-cho, Naka-ku, Yokohama, 244 Japan; e-mail yamaur_t@soft.hitachi.co.jp


{끝}

TCP 는 다음과 같은 헤더 구조를 가진다. 두 호스트 사이에 전송되는 TCP 데이타 단위를 세그먼트라고 부른다. 그러므로 TCP 세그먼트는 TCP 헤더 + DATA 가 될것이다. 다음은 TCP 세그먼트의 구조이다.

그림 2. TCP 헤더 구조


2.2.1. SOURCE PORT/DESTINATION PORT

source port 는 메시지를 보내는 측에서 통신을 위해 사용하는 port 번호이며, destination port 는 목적지, 즉 메시지를 받는측의 통신 port 번호이다.

여기에 있는 port 번호와 더불어 IP 헤더에 있는 source/destination address 를 이용하면 유일하게 식별되는 통신연결을 만들수 있게 된다.

아마도 IP 의 출발지/목적지 주소와 TCP 헤더의 출발지/목적지 포트 번호가 어플리케이션간 통신을 위한 가장 핵심이라고 할수 있을것이다. 다른 정보들은 통신을 원할하도록 도와주기 위해서 부가적으로 존재하는 것이라고 볼수 있다.

이들 포트번호의 크기는 16bit 크기를 가진다. 그러므로 대략 65536 만큼의 포트를 가질수 있을것이다.


2.2.2. SEQUENCE NUMBER

TCP 세그먼트안의 데이터의 송신 바이트 흐름의 위치를 가리킨다. 다른 호스트로 전달되는 패킷은 여러개의 서로 다른 경로를 거치면서 전달되다 보니 패킷의 순서가 뒤바뀔 수 있다. 이를 수신측에서는 재 조립해야할 필요가 있는데, Sequence Number 를 이용해서 조립하게 된다.


2.2.3. ACK

acknowledgment number 라고 말한다. 다음에 받을것으로 예상되는 데이타 옥텟의 순서번호를 나타낸다.


2.2.4. HLEN

TCP 세그먼트의 길이를 정의한다.


2.2.5. RESERVED

현재는 사용하지 않지만, 나중을 위해서 예약된 필드이다.


2.2.6. (Control)CODE BITS

세그먼트의 용도와 내용을 결정하기 위해서 사용된다. URG, ACK, PSH, RST, SYN, FIN 6개의 비트가 정의되어 있다. TCP는 이러한 비트를 이용해서 패킷의 내용이 어떤 목적으로 전달될 것인지를 설정할 수 있다. 이들 비트중 SYN, ACK, RST를 주목할 필요가 있다.

SYN은 TCP연결을 만들 때, 양 호스간 sequence numbers의 동기화를 이루기 위한 목적으로 사용된다. ACK는 원격 호스트의 sequence number에 대한 응답을 위한 목적으로 사용된다. 즉 데이터를 잘 받았다는 걸 알려주기 위한 목적으로 사용되는데, 원격호스트의 sequence number의 번호에 +1을 해줘서 다시 전달하는 방법을 이용한다. SYN 비트는 특히 세번 악수 기법(three-way handshake)를 위해서 사용된다.

RST 비트가 설정되어 있을 경우 받은 호스트는 즉시 연결을 끊어 버리고 FIN 비트가 설정되어 있을 경우 여러가지 테스트를 거쳐서 연결을 끊게 된다. 일반적인 정상종료를 원한다면 FIN 비트를 설정해서 사용하게 된다. 이들 비트에 대한 자세한 내용은 2.3.3절를 참고하기 바란다.


2.2.7. OPTION & PADDING

옵션은 말그대로 옵션이다. TCP 헤더의 정보를 좀더 확장시키고자 할때 사용한다. PADDING 은 32bit 크기를 채우기 위해서 사용된다.


2.2.8. CHECKSUM

TCP 세그먼트 데이타는 중간에 훼손될수 있으며, 변조될수도 있다. 그러므로 이를 체크할수 있는 장치가 필요하다. CHECKSUM 을 만드는 방법(알고리즘)은 기회가 되면 별도로 설명하도록 하겠다.


출처 : http://teamblog.joinc.co.kr/yundream/212

'It's my study ^^ 과연' 카테고리의 다른 글

hard link와 symbolic link  (0) 2007.12.18
FAT 파일 시스템(File System)  (0) 2007.12.17
open  (0) 2007.12.15
Library 만드는 법  (0) 2007.12.14
구조체(Struct)  (0) 2007.12.13

사용법

#include <sys/types.h>

#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);


설명

open시스템호출로, 파일을 열거나 생성 할때 사용한다. 성공하면 해당파일을 지시하는 int 형의 파일지시자를 되돌려준다. path_name 은 생성하고자 하는 파일이름을 나타낸다. 보통 full path 이름을 적어주며, 단지 파일이름만 적을경우에는 현재 경로에 파일이 생성된다.

flag 는 파일을 어떠한 mode 로 열것인지를 결정하기 위해서 사용한다. "읽기전용", "쓰기전용", "읽기/쓰기" 모드로 열수 있다. 이들 모드 선택을 위해서 O_RDONLY, O_WRONLY, O_RDWR 이 존재 한다.

또한 다음중 하나이상의 mode 를 bitwise 연산시킬수도 있다.

O_CREAT

만약 pathname 파일이 존재하지 않을경우 파일을 생성한다.

O_EXCL

O_CREAT 를 이용해서 파일을 생성하고자 할때, 이미 파일이 존재한다면, 에러를 되돌려주며 파일을 생성하는데 실패한다. 이러한 특성때문에 때때로 잠금 파일을 만들기 위해 사용되기도 한다.

O_APPEND

파일이 추가모드로 열린다. 파일의 위치는 파일의 끝이된다.

O_NONBOLOCK, O_NDELAY

파일이 비봉쇄 모드로 열린다.

O_NOFOLLOW

경로명이 심볼릭 링크라면, 파일열기에 실패한다.

O_DIRECTORY

경로명이 디렉토리가 아니라면 파일열기에 실패한다.

O_SYNC

입출력 동기화 모드로 열린다. 모든 write 는 데이타가 물리적인 하드웨어에 기록될때까지 호출 프로세스를 블록시킨다.

또한 mode 를 이용해서 에 파일의 권한을 지정해 줄수도 있다.

S_IRWXU
          00700 모드로 파일 소유자에게 읽기, 쓰기, 쓰기 실행권한을 준다.

S_IRUSR

00400 으로 사용자에게 읽기 권한을 준다.

S_IWUSR

00200 으로 사용자에게 쓰기 권한을 준다.

S_IXUSR

00100 으로 사용자에게 실행 권한을 준다.

S_IRWXG

00070 으로 그룹에게 읽기, 쓰기, 실행 권한을 준다.

S_IRGRP

00040 으로 그룹에게 읽기권한을 준다.

S_IWGRP

00020 으로 그룹에게 쓰기권한을 준다.

S_IXGRP

00010 으로 그룹에게 실행권한을 준다.

S_IRWXO

00007 으로 기타 사용자 에게 읽기, 쓰기, 실행 권한을 준다.

S_IROTH

00004 으로 기타 사용자 에게 읽기 권한을 준다.

S_IWOTH

00002 으로 기타 사용자 에게 쓰기 권한을 준다.

S_IXOTH

00001 으로 기타 사용자 에게 실행 권한을 준다.


반환값

에러가 발생하면 -1 을 반환하며, 성공했을경우에는 새로운 파일 지시자를 반환한다. 에러시에는 적당한 errno 값이 설정된다.


에러

EEXIST

O_CREAT 와 O_EXECL 이 같이 사용되었을경우 발생한다. 이미 경로파일이 존재할경우 발생된다.

EACCES

파일 접근이 거부될경우이다. 주로 권한 문제 때문에 발생한다.

ENOENT

경로명의 디렉토리가 없거나, 심볼릭 링크가 깨져있을때.

ENOENT

경로명의 디렉토리가 없거나, 심볼릭 링크가 깨져있을때.

ENODEV

경로명이 장치파일을 참고하고, 일치하는 장치가 없을때.

EROFS

경로명이 read-only 파일시스템을 참조하면서, 쓰기로 열려고 할때.

EROFS

경로명이 read-only 파일시스템을 참조하면서, 쓰기로 열려고 할때.

EFAULT

경로명이 접근할수 없는 주소강간을 가르킬때

ELOOP

심볼릭 링크가 너무 많을때.


예제

// /usr/my.temp 파일을 읽기 전용으로 열고자 할때
fd = open("/usr/my.temp", O_RDONLY);
...

close(fd);

// 파일을 쓰기 전용으로 생성하며, 파일의 권한은 644 로 한다.
// 만약 이미 파일이 존재한다면 에러가 발생할것이다.
fd = open("/usr/my.temp", O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
...
close(fd);




출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/man/2/open

'It's my study ^^ 과연' 카테고리의 다른 글

FAT 파일 시스템(File System)  (0) 2007.12.17
TCP 헤더 구조  (0) 2007.12.15
Library 만드는 법  (0) 2007.12.14
구조체(Struct)  (0) 2007.12.13
이중 포인터  (0) 2007.12.13
운영체제에서 주어진 일을 하는 최소단위는 프로세스라는 것을 알고 있을 것이다. 프로세스는 프로그램의 실행된 이미지로 운영체제의 메인메모리에 위치한다.

이렇게 프로그램이 실행되어서, 프로세스가 생성되면 프로세스는 컴퓨터의 여러가지 기본자원을 사용할 수 있게 된다. 이 기본자원에 3개의 파일이 포함되어 있다. 바로 입력출력, 에러를 담당하는 3개의 파일들이다. 이것들을 표준입력, 표준출력, 표준에러라고 한다.

  • 표준입력 : 키보드로 부터 입력을 받기 위해서 사용한다.
  • 표준출력 : 모니터로 출력하기 위해서 사용된다.
  • 표준에러 : 에러도 역시 모니터를 통해서 출력된다는 점에서는 표준출력과 마찬가지다. 그러나 어떠한 구분도 없다면, 화면에 출력된 값이 정상적으로 처리된 메시지인지, 에러메시지 인지 확인할 수 없을 것이다. 때문에 표준에러라는 것을 따로 둬서 구분할 수 있게끔하고 있다.

이들 표준입/출력/에러 역시 파일의 형태로 다루어지며, 운영체제는 이를 위해서 예약된 숫자를 파일지시자로 할당한다. 표준입력은 0, 표준출력은 1, 표준에러는 2로 예약되어 있다.

간단한 예를 들어서 설명해보도록 하겠다.
#include <unistd.h> 
#include <string.h>

int main(int argc, char **argv)
{
char data[80];
char *msg = "Input Msg : ";
memset(data, 0x00, 80);

write(1, msg, strlen(msg)); // 1

read(0, data, 80); // 2
write(1, data, strlen(data)); // 3
write(2, "Error\n", 6); // 4
}
  1. "Input Msg"메시지를 모니터에 표준출력 한다.
  2. 표준입력을 통해서 데이터를 읽어들인다. 읽어들인 데이터는 data 에 복사한다.
  3. data에 복사된 내용을 data의 길이 만큼 모니터에 표준출력 한다.
  4. Error라는 메시지를 모니터에 표준에러형태로 출력한다.
이 프로그램을 실행시키면 다음과 같은 결과를 확인할 수 있을 것이다.
# ./write 
Input Msg : hello world
hello world
Error
  • write(2)
    이 함수는 파일지시자(첫번째 인자)가 가리키는 파일에 "쓰기" 위해서 사용한다.
  • read(2)
    이 함수는 파일지시자가 가리키는 파일에서 데이터를 "읽기" 위해서 사용한다.

표준입력과 표준출력을 이해하는데에는 별 어려움이 없을 것이다. 그럼 표준에러와 표준출력을 어떻게 구분할 수 있느냐 하는 문제가 남는다.

표준에러는 쉘의 재지향을 이용해서 따로 분리해서 읽을 수 있다. 재지향은 >을 쓰면 된다. - 2장 리눅스와 C언어참고 - 또한 2>와 같이 표준에러만을 분리해서 재지향 시킬 수가 있다. 여기에서 2가 바로 표준출력을 가리키는 파일지시자 번호다. 이제 다음과 같이 표준에러만 별도의 파일에 재지향 시켜보도록 하자.
# ./write 2> dump.log 
Input Msg : hello world
hello world
# cat dump.log
Error
표준에러가 모니터 화면이 아닌, dump.log 파일에 저장된걸 확인할 수 있을 것이다. 이로써, 표준에러와 표준출력이 모니터를 출력방향으로 하고 있지만, 명백히 구분되는 것임을 이해했을 것이다.

출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/CprogramingForLinuxEnv/Ch13_Input_Output

'It's IT > It's System(linux,win)' 카테고리의 다른 글

Linux 공부를 함 해볼까??????  (0) 2019.12.24
linux, unix shell script 조건문에서 사용하는 기호  (0) 2008.01.17
퍼미션, CHMODE  (0) 2007.12.14
VI명령어  (0) 2007.12.14
PING  (0) 2007.12.14
살아갈 날들을 위한 공부살아갈 날들을 위한 공부 - 10점
레프 니콜라예비치 톨스토이 지음, 이상원 옮김/조화로운삶
현재 읽고 있는 중인 책이다. 출퇴근시에 거의 비몽사몽간에 읽고 있지만 그래도 기억나는 단어는 영혼, 사랑, 침묵이다. 이 주제를 참으로 다양한 방향으로 바라보는 저자의 안목이 참으로 부러울 정도이다. 앞으로 살아가면서 참으로 많은 길잡이가 될것으로 생각한다. 머리속이 아니라 직접 행동 할 수 있는 모티브를 제공하는 책인것은 분명하다. 나의 자식들에게도 물림을 해야겠다는 생각이 드는 드문 책중의 하나 .. 강추
http://sqler.tistory.com2007-12-14T09:15:400.31010

정적라이브러리

static library라고 부르기도 한다. 이 라이브러리는 단순한 오브젝트의 모음일 뿐이다. 정적라이브러리는 ar이라는 프로그램을 통해서 만들 수 있다. 그럼 ar을 이용해서 위의 사칙연산을 위한 4개의 오브젝트를 모아서 libmycalc.a라는 이름의 정적라이브러리를 생성해보도록 하자. rc 옵션을 이용하면, 정적라이브러리를 만들 수 있다.

r은 정적라이브러리를 만들겠다는 옵션이고, c는 새로 생성을 하겠다는 옵션이다.
# ar rc libmycalc.a sum.o sub.o mul.o div.o 
libmycalc.a 라는 파일이 생성된걸 확인할 수 있을 것이다. t 옵션을 이용하면, 해당 라이브러리가 어떤 오브젝트를 포함하고 있는지도 확인할 수 있다. t 옵션을 사용하면 된다. 참고로 정적 라이브러리의 이름은 libNAME.a의 형식을 따라야 한다.
# ar t libmycalc.a 
div.o
mul.o
sum.o
sub.o

그럼 정적라이브러리를 이용해서 실행파일을 만들어 보도록 하자. 이전에는 4개의 오브젝트 파일을 모두 링크시켜줘야 했지만, 이제는 libmycalc.a 만 링크시켜주면 된다.

라이브러리의 링크방식은 오브젝트를 링크하는 것과는 약간 차이가 있다. library의 위치를 명확히 명시해 주어야 한다. -L 옵션을 이용해서 라이브러리가 있는 디렉토리의 위치를 명시해주고, -l옵션을 이용해서, 라이브러리 파일의 이름을 정해줘야 한다. 다음은 simplecalc.c 를 정적라이브러리를 이용해서 컴파일하는 방법을 보여준다.
# gcc -o simplecalc simplecalc.c -L./ -lmycalc 
-L./은 현재 디렉토리를 라이브러리 찾기 디렉토리로 하겠다는 의미가 된다. -l 옵션뒤에 붙이는 라이브러리 파일의 이름에 주목할 필요가 있다. 라이브러리 이름은 lib .a를 제외한 이름을 사용한다.

공유 라이브러리

공유 라이브러리는 함께 사용하는 라이브러리라는 의미다. 즉 정적 라이브러리 처럼 실행파일에 붙는 것이 아니고, 시스템의 특정디렉토리에 위치하면서, 다른 모든 프로그램들이 공유해서 사용할 수 있게끔 제작된 라이브러리다. 그러므로 공유 라이브러리를 사용하도록 제작된 프로그램은 실행시에 사용할 라이브러리를 호출하는 과정을 거치게 된다.

공유 라이브러리역시 오브젝트를 이용해서 만든다는 점에서는 정적라이브러리와 비슷하지만, 호출시에 링크하기 위한 부가적인 정보를 필요로 하므로, 정적라이브러리와는 전혀 다른 형태로 만들어 진다. 정적라이브러리와 이름이 헛갈릴 수 있으니, 라이브러리 이름은 mycalcso 로 하겠다.
# gcc -fPIC -c sum.c sub.c mul.c div.c 
# gcc -shared -W1,-soname,libmycalcso.so.1 -o libmycalcso.so.1.0.1 sum.o sub.o mul.o div.o

  1. 오브젝트 파일을 만들때 부터 차이가 있는데, -fPIC 옵션을 줘서 컴파일 한다.
  2. 그다음 -shared 옵션을 이용해서 공유라이브러리 파일을 생성한다.
위의 과정을 끝내고 나면, libmycalcso.so.1.0.1 이라는 파일이 생성이 된다. 이 라이브러리는 프로그램을 컴파일할때와 실행시킬때 호출이 되는데, 호출될때는 libmycalcso.so 를 찾는다. 그러므로 ln 명령을 이용해서 libmycalcso.so 링크파일을 생성하도록 하자.
# ln -s libmycalcso.so.1.0.1 libmycalcso.so 
이렇게 링크를 만들게 되면, 여러가지 버전의 라이브러리 파일을 이용할 수 있으므로 관리상 잇점을 가질 수 있다. 새로운 버전의 라이브러리가 나올 경우, 오래된 버전의 라이브러리를 쓰는 프로그램은 실행시 문제가 발생할 수 있는데, 이런 문제를 해결할 수 있기 때문이다.

이제 링크하는 과정이 남았다. 링크과정은 정적 라이브러리를 사용할때와 동일하다.
# gcc -o simplecalcso simplecalc.c -L./ -lmycalcso 

이제 프로그램을 실행시켜 보도록 하자. 아마 다음과 같은 에러메시지를 만나게 될 것이다.
# ./simplecalcso 
./simplecalcso: error while loading shared libraries: libmycalc.so:
cannot open shared object file: No such file or directory

이러한 에러가 발생하는 원인에 대해서 알아보도록 하자. 정적라이브러리는 실행파일에 라이브러리가 붙여지므로, 일단 실행파일이 만들어지면, 독자적으로 실행이 가능하다. 그러나 공유라이브러리는 라이브러리가 붙여지는 방식이 아니고, 라이브러리를 호출해서 해당 함수코드를 실행하는 방식이다. 그러므로 공유라이브러리 형식으로 작성된 프로그램의 경우 호출할 라이브러리의 위치를 알고 있어야만 한다.

위의 simplecalcso 프로그램을 실행시키면, 이 프로그램은 libmycal.so 파일을 찾을 것이다. 이때 파일을 찾는 디렉토리는 /etc/ld.so.conf에 정의 되어 있다.
# cat /etc/ld.so.conf 
/usr/lib
/usr/local/lib
만약 위에서 처럼되어 있다면, 프로그램은 /usr/lib 와 /usr/local/lib 밑에서 libmycal.so 를 찾게 될 것이다. 그런데 libmycal.so 가 없으니, 위에서와 같은 에러가 발생하는 것이다.

가장 간단한 방법은 라이브러리 파일을 ld.so.conf에 등록된 디렉토리중 하나로 복사하는 방법이 될 것이다. 혹은 환경변수를 이용해서, 새로운 라이브러리 찾기 경로를 추가할 수도 있다. 이때 사용되는 환경변수는 LD_LIBRARY_PATH 다.
# export LD_LIBRARY_PATH=./:/home/myhome/lib 
이제 프로그램을 실행시키면 LD_LIBRARY_PATH 에 등록된 디렉토리에서 먼저 검색하게 되고, 프로그램은 무사히 실행 될 것이다.

공유라이브러리와 정적라이브러리의 장단점

이들 2가지 라이브러리의 장단점에 대해서 알아보도록 하자. 장단점을 알게되면 어떤 상황에서 이들 라이브러리를 선택할 수 있을지 알 수 있을 것이다.

정적라이브러리의 장점은 간단한 배포방식에 있다. 라이브러리의 코드가 실행코드에 직접 붙어버리는 형식이기 때문에, 일단 실행파일이 만들어지면 간단하게 복사하는 정도로 다른 컴퓨터 시스템에서 실행시킬 수 있기 때문이다. 반면 동적라이브러리는 프로그램이 실행될때 호출하는 방식이므로, 라이브러리까지 함께 배포해야 한다. 라이브러리의 호출 경로등의 환경변수까지 덤으로 신경써줘야 하는 귀찮음이 따른다.

일반적으로 정적라이브러리는 동적라이브러리에 비해서 실행속도가 빠르다. 동적라이브러리 방식의 프로그램은 라이브러리를 호출하는 부가적인 과정이 필요하기 때문이다.

정적라이브러리는 실행파일 크기가 커진다는 단점이 있다. 해봐야 얼마나 되겠느냐 싶겠지만, 해당 라이브러리를 사용하는 프로그램이 많으면 많을 수록 X 프로그램수만큼 디스크 용량을 차지하게 된다. 반면 공유라이브러리를 사용할 경우, 라이브러리를 사용하는 프로그램이 10개건 100개건 간에, 하나의 라이브러리 복사본만 있으면 되기 때문에, 그만큼 시스템자원을 아끼게 된다.

마지막으로 버전 관리와 관련된 장단점이 있다. 소프트웨어 개발 세계의 불문율이라면 버그 없는 프로그램은 없다이다. 어떠한 프로그램이라도 크고작은 버그가 있을 수 있으며, 라이브러리도 예외가 아니다.

여기 산술계산을 위한 라이브러리가 있다. 그리고 정적 라이브러리 형태로 프로그램에 링크되었어서 사용되고 있다고 가정해보자. 그런데 산술계산 라이브러리에 심각한 버그가 발견되었다. 이 경우 산술계산 라이브러리를 포함한 A 프로그램을 완전히 새로 컴파일 해서 배포해야만한다. 문제는 이 라이브러리가 A 뿐만 아니라 B, C, D 등의 프로그램에 사용될 수 있다는 점이다. 결국 B, C, D 프로그램 모두를 새로 컴파일 해서 배포해야 하게 된다. 더 큰 문제는 어떤 프로그램이 버그가 있는 산술계산 라이브러리를 포함하고 있는지 알아내기가 힘들다는 점이다.

공유라이브러리 형태로 작성하게 될경우에는 라이브러리만 새로 컴파일 한다음 바꿔주면된다. 그러면 해당 라이브러리를 사용하는 프로그램이 몇개이던간에 깔끔하게 문제가 해결된다.

실제 이런 문제가 발생한 적이 있었다. zlib 라이브러리는 압축을 위한 라이브러리로 브라우저, 웹서버, 압축관리 프로그램등에 널리 사용된다. 많은 프로그램들이 이 zlib를 정적라이브러리 형태로 포함해서 배포가 되었는데, 심각한 보안문제가 발견되었다. 결국 zlib를 포함한 모든 프로그램을 새로 컴파일해서 재 설치해야 하는 번거로운 과정을 거치게 되었다. 공유라이브러리였다면 문제가 없을 것이다.

이상 정적라이브러리와 공유라이브러리를 비교 설명했다. 그렇다면 선택의 문제가 발생할 것인데, 자신의 컴퓨터나 한정된 영역에서 사용할 프로그램을 제작하지 않는한은 공유라이브러리 형태로 프로그램을 작성하길 바란다. 특히 인터넷을 통해서 배포할 목적으로 작성할 프로그램이라면, 공유라이브러리 형태로 작성하는게 정신건강학적으로나 프로그래밍 유지차원에서나 좋을 것이다.

출처  : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/CprogramingForLinuxEnv/Ch12_module

'It's my study ^^ 과연' 카테고리의 다른 글

TCP 헤더 구조  (0) 2007.12.15
open  (0) 2007.12.15
구조체(Struct)  (0) 2007.12.13
이중 포인터  (0) 2007.12.13
대입연산자  (0) 2007.12.12

 1. chmod
파일 또는 디렉토리의 접근 권한을 변경하는 명령이다.

1.1 chmod의 기본적인 사용법
chmod [-옵션] [모드] [파일명]

[옵션]
chmod 명령에는 몇가지 옵션이 존재하지만 -R 옵션 외에는 사용할 일이 없기 때문에 -R 옵션만 설명을 하겠다.
-R : 퍼미션 변경 대상이 디렉토리일 경우 그 하위 경로에 있는 모든 파일과 디렉토리의 퍼미션을 변경한다.
 
[모드(심볼릭)]
심볼릭 모드와 8진수 모드를 사용할 수 있는데 대부분의 사용자들은 심볼릭 모드 보다 8진수 모드를 선호한다. 그럼 심볼릭
모드부터 공부해 보도록 하자.
심볼릭 모드에서 "u = 소유자, g = 소유 그룹, o = other, a = all, r = 읽기, w = 쓰기, x = 실행"을 의미한다.
심볼릭 모드에서는 권한 추가에 대해서 '+' 를 사용하고 권한 박탈에 대해서는 '-' 를 사용한다. '=' 를 사용하면 현재 설정
된 권한은 제거되고 오직 '='로 설정한 권한만 부여한다.

file1에 대해 소유 그룹에게 쓰기 권한을 추가할 때
[root@rootman root]# chmod g+w file1

소유자에게 file1에 대해 쓰기 권한을 주고 소유 그룹에게는 쓰기 권한을 박탈할 할 때
[root@rootman root]# chmod u+w,g-w file1
--> 위와 같이 동시에 여러 대상에 대해 설정할 때는 각 대상을 콤마(,)로 구분하면 된다. 절대 공백이 들어가서는 안된다.

[모드(8진수)]

8진수 모드에서 4 = 읽기, 2 = 쓰기, 1 = 실행을 의미한다. 8진수 모드는 소유자와 소유그룹, other에 대해서 8진수 3자리로
표현하는데 첫째 자리수가 소유자를 의미하고 둘째 자릿수가 소유 그룹, 셋째 자릿수가 other을 의미한다.
예를 들어 751 라는 퍼미션은 소유자에게 7, 소유 그룹에게 5, other에게 1 에 해당하는 퍼미션을 설정한 것이다.
퍼미션의 계산은 주어진 권한에 해당하는 8진수 값을 모두 더해서(+) 설정된다.

소유자에게 읽기, 쓰기, 실행 권한을 소유 그룹에게는 읽기, 실행 권한을 other에게는 실행 권한만을 설정한 8진수 모드
소유자 = 4(읽기) + 2(쓰기) + 1(실행) = 7
소유그룹 = 4(읽기) + 1(실행) = 5
other = 1(실행) = 1
--> 이걸 정리하면 751 이라는 8진수 모드로 표현할 수 있다. 물론 초보자를 위한 설명이니까 덧셈까지 하면서 설명을 했지만 몇번 사용하다 보면 금방 익힐 수 있을 것이다.

file1에 대해 소유자에게 읽기, 쓰기 권한을 소유 그룹과 other에게는 읽기 권한을 갖도록 설정할 때
[root@rootman root]# chmod 644 file1

1.2 특별한 퍼미션 setuid, setgid, sticky bit

setuid, setgid
실행 퍼미션에는 setuid와 setgid라는 특별한 퍼미션이 있다. setuid는 심볼릭 모드로 's'로 표현되고 8진수 모드로는 4000
으로 표현된다. setuid 퍼미션이 설정되어 있는 실행 파일은 실행되는 동안에는 그 파일의 소유자 권한을 가지게 된다.
이러한 이유때문에 root 소유의 setuid 퍼미션이 포함되어 있는 파일은 아주 신중히 관리를 해야 된다. 저는 사용 안하는
setuid 실행 파일은 setuid 퍼미션을 제거해서 따로 보관하고 있습니다. setgid 퍼미션이 포함되어 있는 실행 파일은 실행되는 동안은 그 파일의 소유 그룹의 권한을 가지는 것 빼고는 setuid와 같다. setgid의 8진수 모드는 2000 이다.
setuid 퍼미션을 포함하고 있는 실행 파일을 ls -al 명령으로 확인해 보면 다음과 같이 소유자 실행퍼미션에 's'라고 되어
있는 것을 확인할 수 있다.
[root@rootman root]# ls -al /bin/su
-rwsr-xr-x    1 root     root        14112  1월 16  2001 /bin/su

setgid가 포함되어 있는 실행 파일을 ls -al 명령으로 확인하면 소유 그룹의 실행 퍼미션에 's'가 설정되어 있는 것을 확인
할 수 있을 것이다.
[root@rootman root]# ls -al /usr/bin/man
-rwxr-sr-x    1 root     root        14112  2월 5  2001 /usr/bin/man

file1 이라는 실행 파일에 setuid 퍼미션을 설정할 때
[root@rootman root]# chmod 4755 file1

▶ file1 이라는 실행 파일에 setgid 퍼미션을 설정할 때

[root@rootman root]# chmod 2755 file1

sticky bit
sticky bit도 특별한 퍼미션이다. other의 쓰기 권한에 대한 특별한 퍼미션인데 /tmp 디렉토리와 /var/tmp 디렉토리에의
퍼미션이 stickbit가 포함되어 있다. sticky bit는 8진수 모드로는 1000으로 설정되고 심볼릭 모드로는 't' 또는 'T'
로 설정된다. 이 sticky bit가 포함되어 있는 디렉토리에 other에 쓰기 권한이 있을 경우 other에 해당하는 사용자들은
디렉토리 안에 파일을 만들 수는 있어도 디렉토리 삭제는 할 수 없다.
sticky bit가 포함되어 있는 대포적인 디렉토리가 /tmp 디렉토리인데 분명히 /tmp 디렉토리의 퍼미에는 other에게 쓰기 권한이 주어져 있다. 그렇기 때문에 /tmp 디렉토리에는 누구나 디렉토리와 파일을 만들 수 있다. 하지만 other에 해당하는 사용자는 쓰기 권한이 있음에도 불고 하고 /tmp 디렉토리를 지울수 없는 것이다. 그 이유는 /tmp 디렉토리에는 sticky bit가 설정되어 있기 때문이다. 당연히 소유자는 sticky bit가 설정되어 있는 디렉토리를 삭제할 수 있다.
디렉토리가 아닌 파일에 sticky bit가 설정되어 있을 때는 other 에게 쓰기 퍼미션이 있어도 파일을 수정할 순 있지만 그 파일을 삭제할 수는 없다. sticky bit의 이런 특징을 이용하면 공개 서버에서는 여러모로 요기나게 사용할 수 있을 것이다.
sticky bit를 적용할려면 당연히 쓰기 권한도 주어야 되다.

sticky bit가 포함되어 있는 디렉토리의 ls -al 결과
[root@rootman root]# ls -ald /tmp

drwxrwxrwt   14 root     root         4096 Aug 30 02:05 /tmp

dir1 이라는 디렉토리에 sticky bit를 설정할 때
[root@rootman root]# chmod 1707 dir1    -->  또는 chmod 1777 dir1

sticky bit가 설정되어 있는 디렉토리를 other에 해당되는 사용자가 디렉토리 삭제 명령을 했을 때
[rootman@rootman /tmp]# rm -rf dir1
rm: cannot remove directory `dir1': Operation not permitted  

[rootman@rootman /tmp]# ls -ald dir1
drwx---rwt  2 root     root         4096 Aug 30 18:42 dir1

2. chattr, lsattr
루트도 지우지 못하는 파일을 설정할 수 있다는 말을 들어 본적이 있나요?
chattr을 이용하면 파일의 소유자라도 read-only로만 파일을 열수 있게 할수 있고 root도 chattr로 설정한 것을 해제하지
않으면 절대 chattr +i 로 설정한 파일을 지울 수 없다. 단, root만 사용 가능하다.
간혹 짖궂은 해커는 멍청한 관리자를 위해(?) 해킹한 시스템의 특정 파일에 chattr +i 를 설정해 놓고 chattr 명령을 모르는
관 리자가 파일을 수정할려고 끙끙 대는 모습을 즐기기도 한다. 어떤 관리자는 시스템의 문제라고 생각하고 포멧을 하는 관리자를 본적도 있다. 저의 경우는 rootman의 텔넷 서버의 guest 계정에 chattr을 적용한 적이 있다. .bash_profile, .bashrc 같은 파일에 chattr +i 를 설정해서 default 설정을 변경하지 못하도록 하기 위해 사용했었다. 또 chattr에는 파일의 수정을 추가 모드로만 열 수 있도록 설정하는 옵션도 있다.
lsattr 이라는 명령으로 파일의 chattr 모드를 확인할 수 있다.

chattr [옵션] [+=-모드] [파일명]

모드를 추가 할때는 '+모드' , 모드를 제거할 때는 '-모드'를 사용하면 되고 '=모드'를 사용할 경우 현재의 모드는 제거되고
오직 '=모드'로 설정된 모드만 적용된다.

[옵션]
-R : 대상이 디렉토리일 경우 그 하위 경로에 있는 파일과 디렉토리까지 모드를 적용한다.
[모드]
i : 파일을 read-olny로만 열 수 있게 설정한다. 링크도 허용하지 않고 루트만이 이 모드를 제거할 수 있다.
a : 파일의 수정을 할 때 내용을 추가할 수만 있다. 단, vi편집기로는 내용을 추가 할 수 없다.

file1에 i 모드를 추가할 때
[root@rootman /tmp]# chatr +i file1


file2에 a 모드를 추가할 때
[root@rootman /tmp]# chattr +a file2


파일의 chattr 모드 확인
[root@rootman /tmp]# lsattr file1 file2
---i-------- file1
----a------- file2


i 모드가 설정된 파일을 제거할려고 할 때 나타나는 메시지
[root@rootman /tmp]# rm -f file1
rm: cannot unlink `file1': 명령이 허용되지 않음

▶ a 모드가 설정된 file2 에 내용을 추가할 때
[root@rootman /tmp]# cat >> file2
a 모드가 설정되어 있는 파일.
내용을 추가합니다.
^D  
--> a 모드가 설정된 파일은 내용 추가만 할 수 있는데 vi편집기에서는 추가되지 않았다.  위의 예제에는 >>(출력 리다이렉션)을 사용해 내용을 추가 하였다.

▶ i, 또는 a 모드가 설정된 파일에 모드를 제거할 때는 '-모드' 를 이용한다.
[root@rootman /tmp]# chattr -i file1

이 글은 스프링노트에서 작성되었습니다.

'It's IT > It's System(linux,win)' 카테고리의 다른 글

linux, unix shell script 조건문에서 사용하는 기호  (0) 2008.01.17
표준입력, 표준출력, 표준에러  (0) 2007.12.14
VI명령어  (0) 2007.12.14
PING  (0) 2007.12.14
LINUX 자주쓰는 명령어  (0) 2007.12.14

 


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

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

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

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

검색(/후 검색할 단어입력)
n: 뒤로 검색
N: 앞으로 검색

매크로
ab aa aaaa: aa를 입력하면 aaaa로 자동변환

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

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

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

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

visual모드
윈도의 텍스트 에디터와 같이 선택부분이 반전되면서 복사,삭제등을 할 수 있다.
v로 visual모드로 집입하여 커서키를 사용해 원하는 부분을 선택한다.
복사는 y, 삭제/잘라내기는 d로 할 수 있다.

vi설정(vim설정)
자신의 홈디렉토리에 .vimrc를 생성하고 다음과 같이 할 수 있다.

set ai
set ts=4
set nu

각각 auto-indent, tab stop, numbering

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

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

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

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

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

여러줄을 주석으로 처리할때
10줄을 주석기호 #을 사용하여 주석처리하려면 다음과 같이 하면 된다.
우선, 첫째줄에 #를 붙이고, 두째줄로 넘어와 9.를 입력하면 된다.
.(period)는 마지막에 수행한 명령어를 반복하는 명령이다.


This article comes from dbakorea.pe.kr (Leave this line as is)

이 글은 스프링노트에서 작성되었습니다.

'It's IT > It's System(linux,win)' 카테고리의 다른 글

표준입력, 표준출력, 표준에러  (0) 2007.12.14
퍼미션, CHMODE  (0) 2007.12.14
PING  (0) 2007.12.14
LINUX 자주쓰는 명령어  (0) 2007.12.14
linux tar  (0) 2007.12.14

+ Recent posts