본문 바로가기

23년 1학기 학교공부/운영체제및실습

[OS] Address Binding과 Relocation

목차

    728x90
    반응형
    SMALL

    Address Binding

    logical address를 physical address로 변환하는 작업이 필요한데, 이를 address translation, address binding이라고 한다.

    instruction을 실행하려면 어떤 변수 값을 가져와서 연산할 필요가 생기는데, 즉 변수가 몇번 주소에 있는지를 찾아야 한다. 혹은 점프해야할 주소가 instruction안에 있는 경우도 있다.

    이처럼 instruction 안에 들어있는 주소들은 모두 logical address이다.
    그래서 실제로 실행할때는 logical address에 해당되는 실제 메인 메모리의 주소를 알아내야한다.

     

    address binding을 언제 하느냐에 따라서 세 가지 종류의 binding이 있다.
    일반적으로 프로그램을 짠 다음 소스 프로그램을 메인메모리에 넣기까지 거쳐야하는 작업을 도식적으로 나타내면 위와 같다.
    소스프로그램을 컴파일해서 바이너리 프로그램으로 된 object module을 만들고, 라이브러리를 사용한다면 object module을 라이브러리와 연결해서 실행가능한 형태로 나오면 이것을 메모리에 loader를 통해 집어넣고 cpu가 실행한다.

    1. Compile time binding

    소스코드를 바이너리코드로 변환하는 컴파일때 binding을 한다.
    프로그램을 작성한 후 컴파일단계에서 이 프로그램이 메인메모리 몇번지에 들어가서 실행될것인지를 알고 컴파일러에게 알려준다. 그러면 컴파일러가 logical address를 만들때 logical address가 들어갈 자리에 physical address와 동일한 주소를 집어넣는다.
    따라서 instruction에 등장하는 logical address의 실제값은 반도체의 physical address와 같다는 특징이 있다.

    위 그림과 같은 소스코드가 있다고 가정하자.
    변수 I가 있는데, 여기에 10을 더한 후 label2로 점프한다.
    소스프로그램을 컴파일하면, 컴파일러는 소스 프로그램을 쭉 스캔하면서 변수가 선언될 때 마다 변수를 변수 테이블에 기록한다.
    logical address 0번부터 코드를 쭉 읽어오기 때문에 virtual address space에서 코드 영역의 크기와, 각 변수들의 상대적인 주소값도 알게 된다.
    컴파일 할 때 사람이 컴파일러에 프로그램의 시작 주소를 인자로 전달한다.
    위 그림에서는 시작 주소를 base address라고 하고 $BA라고 표현하며 여기서는 100번지이다.
    그러면 컴파일러가 컴파일 할때 변수 I가 base address로부터 406byte만큼 떨어진 곳에 등장함을 아는데, 시작주소로 100번지를 받았으므로 변수 I의 주소가 100 + 406 = 506번지라는 것을 컴파일시에 미리 결정해두는 것이다.

    또 label2 점프같은 경우 컴파일러가 프로그램을 스캔하면서 label 2가 프로그램 코드 내에서 몇 번지인지를 알게되는데, 이는 상대적인 위치이다.
    label 2가 프로그램 시작으로부터 20번지 떨어진 곳에 위치한다고 가정했을때, base address를 100이라고 줬으므로 physical address를 120번지라고 결정해서 컴파일한다.
    이후 컴파일이 끝난 프로그램을 메모리에 로딩하는데, 이때 컴파일러가 base address라고 전달했던 100번지 위치에 로드되어야 한다.

    이처럼 컴파일 하는 과정에서 프로그램이 메인메모리 몇번지에 들어갈지를 미리 알고 컴파일러에게 전달하면 logical address자리에 physical address 값을 집어넣는 것이 compile time binding이다.

    이 방법에는 프로세스 시작지점이 바뀌면 안된다는 문제점이 있다. 즉 relocation이 불가능하다.
    때문에 요즘은 사용되지 않는 방법이다.



    2. Load time binding

    compile time binding 방법이 개선되어 나온 방법이다.

    메모리에 집어넣을때 binding을 한다.
    load란 프로세스를 메모리에 넣어주는 작업을 말한다. 
    컴파일할때는 모르지만 나중에 실제로 메인메모리에 넣을 때 logical address를 physical address로 다 바꿔서 넣는 방법이다.

    컴파일때는 그냥 프로그램 시작부터 얼마나 떨어진 위치에 변수가 등장했는지, 점프할 주소가 등장했는지 등 상대적인 주소로 계산해서 컴파일한다.
    이후 $BA가 미지수로 남은 상태에서 운영체제가 메모리에 로드하는데, 이때 운영체제가 메인 메모리의 상태를 보고 빈 메모리를 찾아서 넣을것이다. 이때 들어가는 프로그램의 시작 주소를 알아내므로 이때 physical address를 계산하고, 이렇게 계산된 주소값을 가진 프로그램을 로더가 메모리에 넣는것이다.

    이 방법도 compile time binding과 같은 문제점이 있다.

     

     

    3. Execution time binding

    실행할 때 binding을 한다.
    컴파일이나 로드할때는 relative address인 logical address를 그대로 넣었다가 나중에 instruction을 실행할때 그 logical address에 해당되는 physical address를 계산해서 알아내는 방법이다.

    compile time binding과 load time binding은 cpu가 메모리에 들어온 instruction 안에 있는 주소를 바라보는데 이 주소는 logical address이지만 실제로 메모리 하드웨어가 바라보는 주소인 physical address와 같은 값이라는 특징이 있따.

    execution time binding은 컴파일할때도 $BA라고 표현된 시작 주소를 미지수로 남겨두고, load할때도 미지수값이 있는 상태로 프로그램을 집어넣는다.
    운영체제는 프로그램을 집어넣을 때 시작 주소를 레지스터에 기록해두고, cpu가 instruction을 실행할 때 레지스터값을 사용해서 logical address에 해당되는 physical address를 계산해서 알아내고 실행한다.

    위 그림의 프로그램 instruction에는 $BA + 406처럼 시작주소 미지수가 함께 저장되는 것처럼 표현되어있는데, 실제로 $BA값은 하드웨어에 따로 저장되는것이고 실제 instruction에는 406만 저장된다.
    즉 cpu가 읽는 instruction 안의 logical address는 406이 되고, 나중에 계산된 physical address는 506이 된다.

    이와 같이 logical address와 physical address가 서로 같지 않는 특징이 있다.

    이 방식은 instruction 실행 때 주소 변환까지 수행해야한다. 때문에 instruction 실행 시간이 약간 길어진다는 단점이 있지만, relocation이 가능하다는 장점이 있다.

    예를 들어 프로세스가 swaping되어서 잠시 보조기억장치로 나갔다가 다시 들어올 때 메인 메모리에 들어오는 주소가 바뀔 수 있다.
    compile time binding이나 load time binding때는 꼭 나간 자리 그대로 들어와야 정상적으로 동작하지만,
    execution time binding은 cpu가 instruction을 실행할 때 레지스터에 들어있는 시작주소를 가져와서 계산하기 때문에 시작 주소가 바뀌어도 상관없다.


    Relocation에 대해 알아보자.
    relocation은 swaping이나 compaction할 때 필요하다.
    relocation이 가능하려면 프로세스 코드 내에 physical address가 등장하면 안된다.

    그래서 실행 시점에 physical address를 계산하는 execution time binding에서 relocation이 가능한것인데, 대신 주소 값을 계산하는 작업을 instruction 실행할때 해야하므로 시간이 지연될 수 있다.
    이 시간 지연을 최소화하기 위해서 하드웨어적으로 계산하는 방법이 있고, 이를 위해 base register와 bound register(limit register)가 필요하다

     

    그림을 보면, base register에 프로그램이 어디에 로드됐는지 시작주소를 저장하고, bound register에는 프로세스의 끝 주소를 저장한다.
    instruction을 실행하다가 physical address를 계산할 일이 생기면, 해당 instruction에 등장한 logical address와 base register에 저장된 값을 하드웨어적, 즉 adder 로직에 의해 더한다.
    이후 physical address 값이 나오면 이곳으로 바로 이동하는 것이 아니라 Comparator에서 이 주소가 엑세스해도 되는 주소인지, 허용된 범위 안의 주소인지 비교하는데, 이때 bound register값을 사용해서 이 값보다 작은 주소인지 확인한다.
    만약 bound register값보다 작으면 메모리에 엑세스하고,
    bound register 값보다 크면 범위를 벗어났으므로 운영체제에게 interrupt를 걸어서 프로그램 중단 요청을 한다.
    즉 cpu가 거는 interrupt이므로 trap이다.
    이후 운영체제는 세그멘테이션 폴트이므로 주소 오류를 낸 프로세스를 kill하여 종료시킨다.

    728x90
    반응형
    LIST