[운영체제] execve 함수와 race condition

2020. 4. 21. 09:36

1. fork() 함수와 process

 

 

위와 같은 코드를 작성했다. 부모 프로세스와 자식 프로세스 중 무엇이 먼저 출력되는지를 확인해보기 위해서 컴파일 후에 파일을 실행해보았다. 실행 결과로 부모 프로세스와 자식 프로세스의 glob 값과 var 값은 아래와 같다.

 

코드를 보면, child에서 glob를 증가시켰고, pid0이기 때문에 처음에 나온 것이 child의 것임을 알 수 있다. 또한 parent의 경우 sleep(2)을 하였기 때문에 자식 프로세스보다 다음에 순차적으로 결과가 나오는 것을 볼 수 있다. 이 과정에 대해서 자세히 설명을 해보자면, Fork() 함수 호출 이전에는 메모리의 stack 영역과 data 영역에 각각 var = 88, glob = 6의 값을 가지고 있었다.(프로세스 A) 그런데 Fork() 함수가 호출되면서 프로세스 A’ 이 영역을 그대로 복사하게 된다. 이러한 과정을 거치면 이 과정에서 항상 모든 메모리를 복사해야하기 때문에 느리고, waste space가 생길 수 있기 때문에 좋지 않다. 대신에, 메모리 공유 방법을 사용하면 read only인 상태인데 이 상태에서 process A’ 즉 자식이 glob++var++을 만나면, 메모리 안에 있는 값을 접근해서 사용해야 하므로 메모리 사용시 복사하는 방법, COW(Copy on Write)방법을 사용하여 메모리를 복사하고 그 복사한 영역의 변수를 증가시키게 된다. 그래서 그 결과로 var89의 값이 나오고, glob7의 값이 결과 값으로 나오게 된다. 이것이 Fork()를 하였을 때 좋은 방법이다.

 

2. execve() 함수 실행

 

Execve()를 이용하여 프로그램 실행코드를 작성하였다. 이 프로그램은 ls al을 실행하는 프로그램이다. 각각의 변수는 파일을 실행할 경로, 파일 실행 시 필요한 인자, 환결설정에 대한 값인데, 이것을 execve 함수에 넣어주고 있는 모습이다. 이 파일을 실행하면, 아래와 같이 ls al의 명령어를 실행하게 되는데, 밑에 넣었던 printf 문에 관한 모습은 보이지 않는다.

이 이유는 실행가능한 파일인 path의 실행코드를 현재 프로세스에 적재하고, 기존의 실행코드와 교체하여 새로운 프로그램으로 실행을 하기 때문에 현재 실행되는 프로그램의 기능(printf”hello!”와 같은) 기능들은 없어지고 path의 프로그램을 메모리에 로딩하여 처음부터 실행하기 때문이다.

 

해당 p2 파일을 컴파일하고 실행하자 Ls al 명령어에 대한 것이 실행되는 것을 확인할 수 있었다.

3. thread와 race condition

 

 

이렇게 실습 3의 코드를 작성하였다. 작성한 코드의 내용은 아래와 같은 기준으로 작성하였다.

-        전역 변수: int glob = 2로 선언

-        Minus 함수: 지역변수 var와 전역 변수 glob 1씩 감소시킴

-        Plus 함수: 지역변수 var와 전역 변수 glob1씩 증가시킴

이 파일을 컴파일 하고 난 뒤에 실행을 시킨 결과는 아래와 같다.

 

[-]가 다 동작하고 나서 [+]가 동작하는 모습을 볼 수 있다. 쓰레드를 사용하지 않고 함수를 순차적으로 호출했기 때문에 pid tid는 동일하고, glob var의 변수 값은 순차적으로 증감하는 것을 볼 수 있었다. 쓰레드가 하나이기 때문에 쓰레드간의 경쟁이나 이런 모습은 볼 수 없었다.

 

 

실습 3에서 작성했던 코드를 cp 명령어를 이용하여 복사하였다. 복사 후 메인 함수를 다음과 같이 수정하였다. 수정하여 쓰레드를 생성하고 호출하는 코드를 추가해주었다.

 

 

Main 부분을 수정하여 각각의 스레드를 생성하고 생성된 스레드를 작동시키는 스레드를 작성한다.

Gcc thread2.c o thread lpthread 명령어를 사용하여 해당 파일을 컴파일하고 실행시켜보았다. 아래와 같은 결과가 나왔다. 이전의 스레드를 생성하지 않은 결과와 다르게 pid는 같지만 tid는 다른 모습을 볼 수 있는데, 두 개의 tid가 초반에 번갈아 바뀌어가며 결과를 내는 모습을 볼 수 있다. Globvar 변수의 값을 보면, 32를 번갈아서 나오다가, 한 개의 쓰레드가 두 번을 동작하게 되니 원하지 않는 결과 glob 변수의 값이 2가 아니라 1이 나오게 되자 그 이후로 원하지 않는 결과가 나오게 되었다.

 

이와 같은 동작은 globglob 변수의 값이 만약에 4라면 3으로 만들고나서, context switch가 일어나면 glob++동작을 해서 이전에 만들어진 3의 값을 다시 4로 돌려놓는 동작을 해야 하는데, 이 과정에서 34로 처리되기 전에 glob를 가져가서 예상치 못한 결과값을 가져가게 된다.

 

 

이러한 상태를 rece condition(경쟁상태)라고 하며, 이러한 경쟁 상태는 하나의 자원에 여러 개의 프로세스 혹은 스레드가 동시에 접근할 때, 접근 타이밍에 따라 결과 값에 영향을 줄 수 있는 상태가 되는 것을 말하며 위의 실행 결과처럼 자료의 일관성을 해치게 되는 문제가 발생한다.

BELATED ARTICLES

more