1. 필요성

 

 보통 운영체제에서는 커널모드와 유저모드 두가지 프로세서 접근모드를 지원한다. 그 이유는 유저 어플리케이션이 함부로 운영체제의 치명적인 데이터를 수정하거나 삭제하지 못하게 하기 위해서 이다. 커널모드는 모든 시스템과 메모리에 접근이 허가된 프로세스 실행 모드이다. 유저모드보다 커널모드에 더 높은 권한을 줌으로써 유저모드에서 에러가 발생했을 때 시스템 전체의 안전성을 보장해 준다.



2. 구조


.

 .커널모드와 유저모드의 구조는 위와 같다. 사용자가 직접적으로 하드웨어 장치를 제어한다면 큰 문제 발생할 수 있기 때문에 사용자 애플리케이션은 System Call 을 통해 직접적인 하드웨어 요청이나 중요한 시스템 요청을 한다. 요청을 하면 유저 애플리케이션은 유저모드에서 커널모드로 잠시 전환 되었다가 커널모드에서 작업을 실행한뒤 응답을 유저 애플리케이션에 반환하면서 다시 유저모드로 되돌아가게 된다.





 

이러한 구조를 갖춤으로써 사용자 프로세스가 운영체제와 데이터를 함부로 들여다보거나 변경하지 못하게 보호한다.



3. 특징


유저모드

1. 사용자 애플리케이션의 코드가 실행 됨.

2. 시스템 데이터에 제한된 접근만이 허용, 하드웨어 직접 접근 불가.

3. 시스템 서비스 호출 시 유저모드에서 커널모드로 잠시 전환됨.

4. 스레드는 자신만의 유저모드 스택을 가짐.


커널모드

1. 모든 시스템 메모리에 접근할 수 있고 모든 CPU명령 실행 가능.

2. 운영체제 코드나 디바이스 드라이버 같은 커널모드 코드를 실행한다.



참고 : 

http://lapislazull.tistory.com/

http://www.scitech.co.kr/upload/book_image/s_402/ESDP-Ch06.PDF




WRITTEN BY
Who1sth1s

,

1. 연결리스트(Linked List)란?


 연결 리스트의 사전적 의미는

연결 리스트링크드 리스트(linked list)는 각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 방식으로 데이터를 저장하는 자료 구조이다. 이름에서 말하듯이 데이터를 담고 있는 노드들이 연결되어 있는데, 노드의 포인터가 다음이나 이전의 노드와의 연결을 담당하게 된다.

 연결리스트란 각 노드에 데이터와 링크를 가지고 마치 비엔나 소세지 처럼 한줄로 연결되어 있는 데이터 저장 방식이다.




2. 연결리스트의 쓰임(용도)


배열과 연결리스트의 차이점

-배열의 특성은 메모리공간에서 연속이라는 점이다. 그래서 첨자연산으로 빠른 속도가 보장되지만, 메모리가 연속이어야하기 때문에, 삽입과 삭제가 번거롭다. 하지만 연결리스트는 메모리상에 연속이지 않아도 된다. 왜냐하면 다음데이터에 대한 링크정보를 지니고 있기 때문이다.


연결리스트의 장점과 단점

-장점 : 배열과는 다르게 맨처음 선언시 데이터의 길이를 몰라도 사용이 가능하고 노드(자료)의 추가, 삽입, 삭제가 매우 용이하다. 노드가 추가될 때 마다 메모리 동적할당을 함으로써 메모리공간을 낭비하지 않는다.


-단점 : 배열과 달리 각 노드에 Index가 주어지지 않아서 탐색할때 처음(head)부터 탐색해야 됨으로 속도가 느리다. 따라서 특정 위치의 요소접근이 힘들다.


용도(사용처)

-조회는 드물고 추가, 삽입, 삭제가 잦은곳에서 자주 사용 된다.

ex) 반 아이들의 정보를 출석번호로 나열(추가, 삭제)




3. 연결리스트의 구조 및 구현


-구조





[그림 7-12] 연결 리스트의 예

[네이버 지식백과]연결 리스트 (컴퓨터 개론, 2013.3.10, 한빛아카데미(주))



-구현예제




-결과




+) 스택 리스트





-결과






WRITTEN BY
Who1sth1s

,

ㅇㅇㅇㅇㅇ


WRITTEN BY
Who1sth1s

,

1. 구조체란?


 구조체란 연관성이 있는 서로 다른 자료형을 하나의 집합으로 묶어 새롭게 정의한 사용자 정의 료형이다. 


2. 구조체는 언제, 왜 필요할까?

  구조체는 성적 자료와 같이 학번, 이름, 점수 등 과 같이 다른 자료형을 하나의 집합으로 만드는 상황에서 매우 유용하다. 구조체를 사용하지 않는다면 다음과 같이 선언 하게 된다 


int hakbun;

char  name[10];

int   kor, eng, mat, total;

float  avg;


위와 같이 선언 할텐데 막약에 학생이 1명이 아니라 여러명일 경우 어떻게 선언해야 할까? 


int hakbun1;

char  name1[10];

int   kor1, eng1;


int hakbun2;

char  name2[10];

int   kor2, eng2;


물론 위와 같이 선언할 수도 있다 하지만 너무 비효율적이지 않은가 하지만 구조체를 사용하면 굉장히 실플하고 간단하게 선언해줄 수있다.


3. 구조체의 사용방법


-구조체의 형식은 다음과같다.


struct  구조체이름{     

    자료형  멤버명_1;

    자료형  멤버명_2;

     

    자료형  멤버명_n;

}; //구조체선언에서는 마지막에 꼭 세미콜론(;)을 써야한다.



-위를 참고해서 성적자료를 선언하면 다음과 같다.


struct   sungjuk{

       int hakbun;

      char  name[10];

       int   kor, eng;

};





-그렇다면 구조체를 선언했으니 구조체 변수선언 방법을 알아보자.


형식

struct   구조체이름  변수명_1, 변수명_2, …;

     또는

struct  구조체이름{     

    자료형  멤버명_n;

}변수명_1, 변수명_2; 


성적자료 선언

struct   sungjuk  student1, student2, …;

    또는

struct  sungjuk{     

    자료형  멤버명_n;

}student1, student2; 



-이제 구조체변수 선언도 했으니 구조체를 초기화 해보자

구조체변수의 멤버 값을 참조할때는 ' . ' 점을 사용한다.


student1.hakbun = 1;

student1.name= "홍길동";

student1.kor = 92;

student1.eng = 96;


student2.hakbun = 2;

student2.name= "심청이";

student2.kor = 75;

student2.eng = 100;


또는

struct  sungjuk  student1={1, "홍길동", 92, 96};

struct  sungjuk  student2={2, "심청이", 75, 100};

또는

struct  sungjuk  student[2]={{1, "홍길동", 92, 96},

  {2, "심청이", 75, 100}};


-위 예제를 간단하게 합치면 다음과 같다.

struct   sungjuk{

       int hakbun;

      char  name[10];

       int   koreng;

}student1={1, "홍길동", 92, 96}, student2={2, "심청이", 75, 100};






WRITTEN BY
Who1sth1s

,

함수호출-값에 의한 호출(Call-by-Value)


 일반적인 함수호출의 예를들면 다음과 같다.

  결과 : 


 input1과 input2를 add함수의 a, b에 전달하고 실행시키는 과정을 함수의 호출이라고 한다. 

 위와같이 그냥 input이라는 값만 함수에 전달하는 방법을 값에 의한 호출(Call-by-Value)라고 한다.

값에 의한 호출(Call-by-Value)이라는 호출방식은 일반적으로 쓰인다. 하지만 다음과 같은 소스에서는 적합하지 않다.


-값에 의한 호출(Call-by-Value)의 한계

  결과 : 


위 소스는 print할때 input의 값을 서로 바꾸어 출력하기 위해 만든 소스이다. 하지만 결과 값은 이상하게도 input이 서로 바뀌지 않았다.

그 이유는 당연하다. 왜냐하면 input의 값만 함수에 전달했기 때문에 실제 input의 값이 바뀌는 것이 아니고 change라는 함수안의 input의 값만 바뀌었기 때문이다. 따라서 이런 경우에 원하는 대로 출력을 시킬려면 값에 의한 호출(Call-by-Reference) 이라는 방법을 사용해야 한다.

이 방법을 써서 다시 소스를 고쳐짜면 다음과 같다.



함수호출-참조에 의한 호출(Call-by-Reference)


 결과 : 


빨간색 밑줄친 부분을 추가했더니 원하는 대로 값이 서로 바뀌어 나오는 것을 볼 수가 있다.

 위에 추가한 빨간색 밑줄을 설명하자면 함수를 호출할때 input이라는 값만 주는것이 아니라 input자체의 주소를 전달함으로서 input의 실제 값을 참조할 수 있게 되는 것이다.

 다시 말하자면 change라는 함수를 호출할때 input의 주소값을 전달하고 change함수에서 전달받은 주소값 앞에다가 *(포인터)를 붙임으로서 input의 실제 값을 참조할 수 있게 되는 것이다.

이와 같은 방법을 값에 의한 호출, 즉 Call-by-Reference라고 불린다. 




소스




WRITTEN BY
Who1sth1s

,

동적할당이란?


 우선 c언어에서는 메모리 할당 방식의 종류가 2가지로 나뉘는데 한가지는 정적인 방식과 동적인 방식으로 나뉜다.

정적인 방식 : 프로그램 실행 전 변수의 저장공간을 먼저 할당 후 프로그램 종료시 해제.

Ex) int a[10] = 0;


동적인 방식 : 프로그램 실행 중 필요한만큼의 메모리를 할당 후 원할때 해제.


동적할당은 언제, 왜 필요할까?

  동적할당은 상당이 많은 상황에서 꼭 필요합니다. 예를 들어 영어이름을 저장하는 char배열을 만든다고 가정할때 char 배열의 크기를 얼마나 크게 잡아야 할까? 대충 15글자로 정했다고 하면 아래와 같이 배열을 만들것이다.

char name[15];


             □ 


그렇다면 만약에 name에다가Hong Gil dong 이라는 이름을 넣으면 name

 이라는 배열에 총 13글자가 들어간다. 


■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ □ 


하지만 이 배열의 크기는 15인데 13만들어가면 2라는 크기의 메모리가 낭비된다.


그리고 만약에 Hong Myeong seong 이라는 이름을 넣으면 이 배열에

17글자가 들어간다. 즉 15라는 배열의 크기를 초과했다.


■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■   ■ 


이처럼 오버플로우 위험 또한 생긴다.


그래서 이럴때 사용하는 것이 동적할당이다.



동적할당의 사용방법


 malloc 함수로 동적할당함. (C 언어의 표준 라이브러리로 stdlib.h에 정의)



malloc함수


예를 들어 malloc(4)를 하면 4byte 만큼의 메모리를 할당받는다.

사용의 예를 들어보자면 다음과 같다.


Ex) int *i = (int*) malloc (sizeof(int));




위와 같이 i라는 포인터 변수를 선언하고 i값에다가 메모리를 할당하는 것이다.

sizeof(int)는 4와 같으니 malloc함수에 4byte의 메모리를 할당 받고 int 형으로 바꾸어 주는 것이다.

만약에 malloc(sizeof(int))는 그대로 하고 앞에 int*을 int형이 아니라 short형으로 바꾼다면 i라는 변수는 short형의크기의 배열 2개가 선언됩니다.


예를들어 input을 받아 input 만큼 배열의 크기를 할당받고 싶다면

int *arr = (int*) malloc(sizeof(int)*input);

이런식으로 하면 된다.


free함수


할당된 메모리를 해제하는 함수이다.

메모리를 할당 받고 메모리가 해제되지 않으면 할당받은 메모리는 사용이 끝났음에도 불구하고 컴퓨터가 종료되기 전까직 해당 메모리를 차지하게 된다.

따라서 메모리를 할당만 하고 해제를 안하면 언젠가는 메모리가 부족해지는 현상이 발생하게된다. 때문에 동적할당 후 더 사용할 이상 필요가 없다면 꼭 free함수로 메모리를 해제 시켜주어야 한다.


다음 같이 메모리를 할당을 해주었으면 


int *arr = (int*) malloc(sizeof(int)*input);



마지막에는 꼭 다음과 같이 메모리를 꼭 해제 시켜 주어야 한다.

 free(arr_2); 







동적할당의 장점과 단점


-장점 상황에 따라 원하는 크기만큼의 메모리가 할당되므로 경제적이며, 이미 할당된 메모리라도 언제든지 크기를 조절할 수 있다.


-단점 : 더 이상 사용하지 않을 때 명시적으로 메모리를 해제해 주어야 한다.




WRITTEN BY
Who1sth1s

,

2차원 배열이란?

 2차원 배열은 이전에 배웠던 배열의 확장이다.

이전에 배웠던 배열이 

int arr[1]; 

이라면 오늘 배울 2차원 배열은 위 배열에서 아래와 같이조금 확장한 것이다.

int arr[1][2];

이처럼 이전에 배운 배열은 1차원 배열이라고 하고 오늘 배울 배열은 2차원 배열이라고 한다.

차이점은 index가 하나 늘어난것과 저장공간이 많아졌다는것 뿐이다. 아래의 사진을 보면 이해가 쉬울것이다.


[그림 7-5] 2차원 배열의 표현

[그림 7-5] 2차원 배열의 표현

 

 

 

[네이버 지식백과]다차원 배열 (컴퓨터 개론, 2013.3.10, 한빛아카데미(주))





2차원 배열의 선언과 저장


자료형 변수명[열][행]

예)int arr1[2][2]; char arr2[4][3];

     0  1 2              0 1  2  3  4 

  0 □ □ □          0 □ □ □ □ 

  □ □ □          1 □ □ □ □ 

  2 □ □ □          2 □ □ □ □ 

arr1              arr2 


위와 같이 각 배열에 행(가로 한줄)과 열(세로 한줄)이 생긴다. 



2차원 배열의 값 대입

배열이 

int arr[1][2]; 와 같을때 아래의 그림처럼 나온다


[그림 7-5] 2차원 배열의 표현






[네이버 지식백과] 다차원 배열 (컴퓨터 개론, 2013.3.10, 한빛아카데미(주))

그렇다면 값을 어떻게 대입 시켜줄까? 

a[0][0] = 5;

a[0][1] = 5;

a[1][0] = 5;

a[1][1] = 5;

a[2][0] = 5;

a[2][1] = 5;


이렇게 하드코딩을 할수도 있지만 다음과 같이 for문을 쓰면 쉽게 선언을 할수있다.

for(i=0; i<3;i++) {

     for(j=0; j<2; j++){

   a[i] = 5;

}

 또한 이 방법 말고도 다음과 같이처음에 선언할때도 값을 대입할 수있다.

예)int arr1[1][2]= { {5, 4}, {3, 2}, {7, 8} };

         0   1  

     0  ⑤  ④  

     1  ③  ② 

     2     


2차 배열의 활용도

2차 배열을 사용함으로써 데이터의 관리를 쉽게 할수 있으며 맵(map)과같이 자료 값을 일일히 대입하기 어려운 상황에서 쓰면 좋다.



 



WRITTEN BY
Who1sth1s

,


배열이란 간단하게 말하면 변수들을 


한 데 묶어 둔것이다. 



▶그렇다면 배열이란 것을   사용 할까?

그 이유는 배열이 없다면 변수를 선언할때  

int a1, a2, a3, a4, a5, a6, a7, … 

이런식으로 매우 귀찮아지죠. 하지만 배열을 사용하면

예) int a[10];

이렇게 데이터마다 변수 이름을 따로 두지 않으므로 처리가 훨씬 수월하며. 또한 활용도도 아주 높다는 장점이 있다.



▶배열의 선언은 어떻게 할까?

자료형 변수명[갯수]

예)int arr1[100]; char arr2[10]; 



▶배열은 어떻게 저장 될까?

배열의 저장을 비유하자면 연속적으로 놓여있는 빈 박스와 비슷하다.

다음과 같이 배열을 선언하면

int a[10]; 

□ □ □ □ □ □ □ □ □ 

0  1  2  3  4  5  6  7  8  9


다음과 같은 a라는 빈 박스 10개가 뙇 하고 생기는 것과 같다.

박스 아래에 있는 번호는 Index라고 하는데 이는 몇번째 박스인지 나타내는 번호와 같다. 

이는 Index가 0번째 부터 시작 해서 9까직 총 10개의 빈 박스가 있는것이다.(1부터 시작하는게 아니란건 주의해야한다.)


예를 들면 a[2] 는 a라는 박스들중 3번째 박스를 가르킨다.


이제 어떻게 저장되는지 알았다면 이제 이 박스 안에다가 값을 넣어보자. 


▶배열에다가 값을 어떻게 넣을까?

int a[10]; 

□ □ □ □ □ □ □ □ □ 

0  1  2  3  4  5  6  7  8  9

여기서 만약에 내가 3번째 박스에다가 5라는 값을 넣고 싶으면 a[3] = 5; 만 해주면 된다. 

그럼 모든 박스에 값을 다 넣어주자.

a[0] = 5;

a[1] = 5;

a[2] = 5;

a[3] = 5;

a[4] = 5;

… 

그렇다 미친짓이다. 그렇다면 이짓을 어떻게 쉽고 간단하게 할 수있을까?

바로  for문이다

for(i=0; i<10;i++) {

a[i] = 5;

이렇게 for문으로 i값을 증가시켜주고 a배열의 인덱스에 i값을 넣어주면 상당히 효율적으로 배열에다가 값을 넣을 수가 있다.

또한 처음에 배열을 선언할때도 다음과 같이 값을 넣을 수 있다.

예)int arr1[5]= {9, 4, 5, 7, 1};


           ⑨  ④  ⑤  ⑦  ①

 0   1   2   3   4



그러므로 이 짱짱 좋은 배열을 효과적으로 잘 사용해보자.


WRITTEN BY
Who1sth1s

,


포인터란?

포인터는 포인터 변수를 줄여서 말하는 걸로 영어 단어(pointer)그대로 무엇을 가르킨다는 뜻입니다

포인터 변수란 일반적인 변수를 저장하는 것이 아니라 해당변수가 들어있는 주소의 값을 저장 하는 것을 말한다.예를 들어 일반변수는 a라는 이름으로 100을 저장한다고 하는 반면 포인터 변수는 a라는 변수가 메모리에 위치하는 주소를 알려주는 것이다.


포인터의 선언방법

포인터의 선언은 간단하다. 선언 할 때 변수이름 앞에 기호를 넣어 주는게 전부이다.


-인반 변수 : 타임 변수의 이름

-포인터 변수 : 타입 *포인터의 이름


)일반변수 : int a; , 포인터 변수 : int *input;

 

포인터를 선언하기만 하면 그 안에는 아무의미도 없는 쓰레기 값이 들어가게 된다

그래서 포인터 변수에다가 변수의 주소를 지정 해주어야한다변수의 주소를 지정 하는 방법은 지정할 변수 앞에다가 기호를 넣어주면 된다.


포인터 변수에 값 넣기 : 포인터 변수 = &변수


)input = &a;



백문이 불여일견 이라고 그림으로 나타내면 이러하다.


-a의 값 : 3

-a의 주소 값 : 4832

-*p의 값 : 3

-p의 값 : 4832




 

포인터를 쓰는이유& 활용도

포인터를 사용함으로써 복사본을 만들지 않고 주소만 알려줌으로써 용량 및 처리시간에서 이득을 볼 수 있습니다.

그래서 메모리가 한정적이거나 처리시간이 중요한 시스템에서 사용할 경우 도움이 됩니다.


-예를들어 배열을 선언할때 배열이 a[100000]와 같이 거대한 량의 자료를 저장할때 포인터를 사용 하여 필요한 만큼의 배열의 량을 받아서 메모리를 비효율적으로 안써도 되게 합니다.



 

 


WRITTEN BY
Who1sth1s

,