반응형

 

fork() 함수는 현재 실행 중인 프로세스를 복사하여 다른 프로세스를 생성한다.
이때 fork() 함수를 호출하는 프로세스를 부모 프로세스라 하고, 새로 생성된 프로세스를 자식 프로세스라고 한다.

이러한 fork() 함수를 사용하여 마지막 값과 생성할 프로세스 수가 주어지면 범위를 프로세스수만큼 균등하게 분배하여 범위 내의 합 연산을 구하는 프로그램을 만들어 보려고 한다.

 

int main (int argc, char *argv[])

코딩을 하다보면 메인 함수의 인스턴스로 int argc, char *argv []를 종종 볼 수 있는데, 각각의 의미는 다음과 같다.

argc : 메인 함수로 전달받은 인자의 개수
argv : 전달받는 인자 즉 문자열

 

즉, 리눅스 환경에서 "파일명 인수1 인수2" 이런 식으로 입력을 하게 된다면

argc = 2
argv[0] = "a.out"
argv[1] = 1
argv[2] = 2

이런 식으로 값들이 저장되고 이를 이용하여 먼저
시작 숫자와 끝 숫자가 주어지면 해당하는 범위의 값들의 합을 구하는 c파일을 만든다.

 

<range.c 코드>

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main(int argc, char* argv[])
{
    int sum = 0;

    if (argc =! 3) // 만약 인수의 갯수가 3개가 아니라면(#./range 1 100 형태가 아니라면)
    {
        fprintf(stderr, "usage %s processes\n", argv[0]);
        return -1;
    }

    int start = atoi(argv[1]); // atoi()함수 : 문자열을 int형으로 변환시켜주는 함수
    int finish = atoi(argv[2]);
    for(int i = start ; i <= finish ;i++)
    {
        sum += i;
    }
    printf("[%ld] sum (%d ~ %d) = %d\n",(long)getpid(),start,finish,sum); // getpid()현재 프로세스의 ID값
    return 0;
}

range파일은 "gcc range.c -o range" 명령어를 통해  range.c를 컴파일한 파일이며,
터미널에 "함수명 시작 값 끝 값"이 주어지면 시작 값~끝 값까지의 합을 구하는 프로그램이다.
그리고 getpid() 함수를 통해 현재의 프로세스 ID값도 출력되게 하였다.


범위를 내 합을 구하는 프로그램을 만들었으니 자식 프로세스는 위에서 만든 range 프로그램을 execl() 함수를 통해 실행하여 자신이 담당한 범위의 숫자의 합을 구하여 결과를 출력한다.
(예: execl 100 3으로 실행 시 3개의 자식 프로세스가 담당하는 범위는 각각 1~33, 34~66, 67~100이 된다.)

 

 

<execl.c 코드>

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main(int argc, char* argv[])
{
    pid_t childpid = 0;
    int i, n, status;

    if (argc < 2) {
        fprintf(stderr, "usage %s processes\n", argv[0]);
        return -1;
    }

    n = atoi(argv[2]); //argv[2]는 생성할 자식프로세스의 수
    for (i = 1; i <= n; i++)
        if ((childpid = fork()) <= 0) // 자식프로세스 오류시 break
            break;

    int num = atoi(argv[1]);
    int SS = num / n * (i - 1) + 1; //시작값
    int EE = num / n * i; //마지막값

    char ss[9];               // 변환한 문자열을 저장할 배열
    char ee[9];
    sprintf(ss, "%d", SS);   // %d를 지정하여 정수를 문자열로 저장
    sprintf(ee, "%d", EE);   // %d를 지정하여 정수를 문자열로 저장

    if (childpid == 0) // 자식프로세스의 리턴값이 0(정상종료)일때 range 프로그램 호출
    {
        execl("range","range",ss,ee, NULL); // ss,ee는 시작값(SS)과 마지막 값(EE)을 문자열로 변환한 것, 프로그램에 전달되는 인수들이다. 
        return 1;
    }
    else
    {
        sleep(1); // 1초 sleep
        wait(&status); // 자식프로세스가 모두 종료하기까지 부모프로세스는 대기
        fprintf(stderr, "[%ld] completed all tasks.\n", (long)getpid());  // 현재 프로세스의 ID값 출력
    }
    return 0;
}

 

터미널에 "execl 1000 3" 입력 시 마지막 값은 1000이며 생성하는 자식 프로세스의 개수는 3이다.
따라서 부모 프로세스[4810]는 자식 프로세스[4811], [4812], [4813] 3개를 생성하고 각각의 자식 프로세스는 execl() 함수를 통해 range 프로그램에 ss(문자열로 변환된 시작 값), ee(문자열로 변환된 끝 값) 인수 2개를 전달하면서 각자 담당하는 범위 내의 연산의 합을 출력할 수 있도록 하였다. sprintf() 함수는 정수를 문자열로 바꾸기 이해 사용하였다.
그리고 부모 프로세스가 자식 프로세스의 task가 끝날 때까지 기다리게 하기 위해 wait(&status) 함수를 사용하였다. 

 

+ 입력값이 "10000 1" / "10000 2" / "10000 3" / "10000 4" 일 때의 결과!

 

반응형

+ Recent posts