Adbanced C 강의 2일차

이승현·2021년 6월 29일
0

Advanced C 강의

목록 보기
2/5

1. 프로세스와 커널

1) 유닉스 커널 구조

C 프로그램에서 printf()함수를 호출하면 user level의 printf()함수는 System Call Interface를 통해 최종적으로 커널층에 있는 write()함수를 호출하게 되는데 이 때 printf()함수는 user level에서 동작하는 user library 함수라 하고, write()함수를 커널 level에서 동작하는 시스템 함수라 한다.

프로세스 상태 전

2) 프로세스의 상태

하나의 프로세스가 시스템 내에 존재하는 동안 그 프로세스는 위와 같이 일련의 서로 다른 상태를 가지게 된다. 프로세스의 준비, 실행, 대기 는 다음과 같은 상태를 의미한다.

하나의 작업, 즉 프로세스가 컴퓨터 시스템에 생성되어 완료되기까지는 위에서 설명한 준비(Ready) 상태, 실행(Running) 상태, 대기(Waiting) 상태를 반복적으로 거치게 되는데, 이를 프로세스의 상태천이라고 하며 다음과 같이 분류할 수 있다.

디스패치(Dispaltch : 준비 → 실행)

준비 상태의 큐(Queue)에 대기하고 있던 프로세스 중 우선순위가 높은 프로세스가 CPU를 취하여 실행 상태로 바뀌는 것을 말한다.

타이머 런 아웃(Timer Run Out : 실행 → 준비)

어떤 프로세스가 CPU를 계속 독점하여 사용하는 것을 막기 위하여 주어진 시간 내에 작업이 끝나지 않으며 운영체제가 CPU의 제어권을 해당 프로세스로부터 강제로 회수하여 프로세스의 상태가 준비 상태로 바뀌는 것을 말한다.

블록 (Block : 실행 → 대기)

실행 상태의 프로세스가 지정된 시간 이전에 입출력이나 기타 다른 수행을 필요로 하는 경우, 그 프로세스는 스스로 CPU를 양보하게 됩니다. 즉, 프로세스가 스스로 실행 상태에서 대기 상태로 바뀌는 것을 말한다.

웨이크 업 (Wake Up : 대기 → 준비)

입출력 작업을 실행하기 위해 스스로 대기 상태로 바뀌었던 프로세스가 작업이 완료되어 대기 상태에서 준비 상태로 바뀌는 것을 말한다

3) 프로세스 제어 블록(PCB : Process Control Block)

PCB는 운영체제가 프로세스에 대한 중요한 정보를 저장해 놓은 저장소를 의미한다. 운영체제가 CPU의 제어를 다른 프로세스에게 넘겨줄 때 현재 실행 중인 프로세스의 정보를 해당 PCB에 저장한 후 제어를 넘겨준다. 제어가 다시 이전 프로세스에게 넘겨질 때 운영체제는 해당 PCB에 있는 정보를 이용해서 실행한다.
PCB는 프로세스 생성시 만들어지며, 모든 프로세스는 각각 고유한 PCB를 가지게 된다. 그리고 프로세스의 수행이 완료되면 해당 PCB도 함께 삭제된다. PCB 내용은 프로세스 상태 변화가 일어난 후 변경된다.

운영체제에서 프로세스를 스케줄링 하는 기법은 크게 선점(Preemption) 스케줄링 기법과 비 선점(Non-Preemption) 스케줄링 기법으로 나눌 수 있다. 만일 한 프로세스가 CPU를 차지했을 때 다른 프로세스가 그 CPU를 빼앗을 수 없다면 이 스케줄링은 비 선점이며, 그 반대의 경우는 선점이다. 대다수의 운영체제는 선점형 스케줄링 방식을 사용한다.

선점 스케줄링

: 선점 스케줄링은 높은 우선 순위의 프로세스들이 긴급한 경우에 유용하다. 예를 들어, 실시간 시스템에서 인터럽트가 받아들여지지 않는 경우 결과는 예측할 수 없다. 대화식 시분할 시스템에서도 선점 스케줄링은 빠른 응답 시간을 유지하는 데 필요하다. 그러나 선점 방식은 그만큼 경비가 들고 오버헤드까지 초래한다. 또한, 선점 스케줄링 기법의 설계 시 우선순위를 깊이 고려해야 하며, 우선순위가 의미 없이 배당되면 선점방식의 효과가 없다.

4) 프로세스

프로그램의 실행과정은 다음과 같다.

  • 프로세스란 메모리에서 실행중인 프로그램을 의미하며, 메모리는 'XX번지'라고 표현되는 주소개념이 있다. 위 그램은 프로그램이 실행되는, 즉 프로세스의 메모리 주소 공간을 표현한 것이다.

  • 메모리에 적재되는 내용을 살펴보면 다음과 같다.
    코드 세그먼트 : 프로그램의 실행코드와 함수들이 저장된다.
    데이터 세그먼트 : 전역변수와 정적변수가 저장된다.
    힙 세그먼트 : 동적메모리 할당을 요쳥시 사용되는 공간이다.
    스택 세그먼트 : 지역변수가 저장된다.(임시데이터 저장공간)

  • 메모리를 할당 받을 때, 모두 메모리에 올라가는 것이 아닌 가상메모리에 나눠서 올라간다. 가상메모리에 있는 내용이 메모리에 들어가는 것을 swap in, 반대를 swap out이라 한다. 이러한 행위를 swapping이라 한다.

  • 운영체제는 메모리를 주소로 관리한다.

2. 포인터

포인터 : 실행중인 프로세스의 임의의 주소

  • C언어는 할당 받은 메모리 공간의 주소를 확인하고 제어할 수 있는 포인터 자료형이 있다.

포인터 변수 : 다른객체(변수)의 메모리 주소를 저장하는 변수

  • 포인터 변수의 크기는 선언되는 자료형과 무관하며 운영체제 플랫폼에서 결정한다.
    (32bit => 4바이트, 64bit => 8바이트)
    -참조-
    32bit O/S -> APP(4GB), 포인터 4바이트)
    64bit O/S -> APP(이론상 2^64 16엑사바이트, 실제 2^48 256TB, 포인터 8바이트)
  • 포인터 변수의 자료형은 참조할 데이터의 자료형과 같아야한다.

3. 배열과 포인터

1) 배열

메모리의 연속된 공간에 할당된 동일한 자료형의 데이터 모음

  • 첨자가 없는 배열변수는 그 배열이 할당된 메모리의 시작주소를 갖는 포인터 상수이다.

배열의 포인터 연산 예시

int num[5] = {100, 200, 300, 400 ,500}, i;
int *p1;
p1 = num;

일때, num + i = p1 + i = &num[i] = &p1[i]
*(num + i) = *(p1 + i) = num[i] = p1[i] 이다.

※ 배열변수는 포인터 상수 이기 때문에, 포인터 연산은 불가능하다! (num++ x)

함수 인자로 포인터 입력시 int num[n] == int *num 이다.

2) 다차원 배열

배열의 요소 자체가 또 다른 배열이 되는 경우(Array of Array)를 말한다. 2차원 이상을 다차원 배열이라 한다.

선언 예시

type var-name[row-size][column-size];

사용 예시

int count[4][3] = {};

에서 count[0] = &count[0][0] , count[1] = &count[1][0] ... 이다.

3) 배열 포인터

다차원 배열의 시작 주소를 저장하여 데이터로 사용하는 포인터 변수를 의미한다. 다차원 배열은 2차원 이상의 배열이다.

선언 예시

자료형 (* 변수명)[배열크기];

사용 예시

int * ptr1;
int (* ptr2)[3];
int (* ptr3)[2][3];

※ 포인터변수 : 변수의 시작주소이거나 또는 1차원 배열의 시작주소가 대상.

배열 포인터 변수

n차원 정수형 배열 중 열의 크기가 m열인 배열의 시작주소가 대상

  • sizeof()로 찍어보면 포인터의 크기가 나온다(32bit = 4 64bit = 8)
  • 포인터의 값으로 한번 들어가서 찍어보면 배열에서 찍은것처럼 값이나온다.

4. 포인터 배열

포인터 배열은 주소 값들을 저장하는 배열이다. 즉, 메모리의 주소들을 연속된 공간에 모아 놓은 구조를 포인터 배열이라 한다.

선언 예시

자료형 *변수명[크기];

사용 예시

int count[3][2] = {1,2,3,4,5,6};
int (* ptr)[2];
int * temp[3];
printf("%d,%d,%d \n",sizeof(count),sizeof(ptr),sizeof(temp));
  • 포인터 배열은 크기없이 선언해도 되는데 이를 이용해서 문자열 처럼 사용한다. ( 마지막 항목에 NULL을 넣어준다 )
  • 포인터 배열은 결국 배열이기 때문에 SIZE를 찍어보면 8*크기가 나온다. ( 배열의 포인터의 경우 8 )

※ 배열과 포인터는 엄연히 다르다. ( 포인터는 주소라서 항상 크기가 8이다. ) ( 배열은 크기를 포함한 정보를 가지고 있다. )

profile
노른노른

0개의 댓글