CS/운영체제

[운영체제 OS] PROCESS API IN POSIX

두루두루두 2025. 3. 17. 17:59

목차

  • 프로세스 관련 시스템 호출
    • fork(), wait(), exec(), kill, ...

❑ 프로세스 생성 : fork()

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]){
	printf("hello world (pid:%d)\n", (int) getpid());
	int rc = fork();
	if (rc < 0) { // fork failed; exit
		fprintf(stderr, "fork failed\n");
		exit(1);
	} else if (rc == 0) { // child (new process)
		printf("hello, I am child (pid:%d)\n", (int) getpid());
	} else { // parent goes down this path (main)
		printf("hello, I am parent of %d (pid:%d)\n", rc, (int) getpid());
	}
	return 0;
}

 

▪ 자기 자신의 주소 공간, 레지스터 등을 복사한 새 프로세스 생성

▪ 실행 결과 – non-deterministic (같은 입력을 주어도 실행할 때마다 다른 결과가 나올 수 있음)

prompt> gcc -g -Wall -o p1 p1.c
prompt> ./p1
hello world (pid:17908)
hello, I am parent of 12276 (pid:17908)
hello, I am child (pid:12276)
prompt>
prompt> ./p1
hello world (pid:14660)
hello, I am child (pid:18584)
hello, I am parent of 18584 (pid:14660)
prompt>

 

❑ 종료 대기: wait()

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

int main(int argc, char *argv[]){
	printf("hello world (pid:%d)\n", (int) getpid());
	int rc = fork();
	if (rc < 0) { // fork failed; exit
		fprintf(stderr, "fork failed\n");
		exit(1);
	} else if (rc == 0) { // child (new process)
		printf("hello, I am child (pid:%d)\n", (int) getpid());
	} else { // parent goes down this path (main)
		int wc = wait(NULL);
		printf("hello, I am parent of %d (wc:%d) (pid:%d)\n",
			rc, wc, (int) getpid());
	}
	return 0;
}

 

▪ 실행 결과 - deterministic

prompt> ./p2
hello world (pid:29266)
hello, I am child (pid:29267)
hello, I am parent of 29267 (wc:29267) (pid:29266)
prompt>

 

❑ 프로그램 실행: exec()

 

▪ 확보된 주소 공간에 새 프로그램 적재하여 실행

▪ execl, execv, execlp, execvp, execle, execve

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

int main(int argc, char *argv[]){
	printf("hello world (pid:%d)\n", (int) getpid());
	int rc = Fork();
	if (rc == 0) { // child (new process)
		printf("hello, I am child (pid:%d)\n", (int) getpid());
		char *myargs[3];
		myargs[0] = strdup("wc"); // program: "wc" (word count)
		myargs[1] = strdup("p3.c"); // argument: file to count
		myargs[2] = NULL; // marks end of array
		execvp(myargs[0], myargs); // runs word count
		printf("this shouldn’t print out");
	} else { // parent goes down this path (main)
		int wc = wait(NULL);
		printf("hello, I am parent of %d (wc:%d) (pid:%d)\n",
			rc, wc, (int) getpid());
	}
	return 0;
}

 

▪ 실행 결과

prompt> ./p3
hello world (pid:29383)
hello, I am child (pid:29384)
29 107 1030 p3.c
hello, I am parent of 29384 (wc:29384) (pid:29383)
prompt>

 

❑ 입출력 재지정 (Redirection)

prompt> wc p3.c
	29 107 1030 p3.c
prompt> wc p3.c > newfile.txt
prompt> cat newfile.txt
	29 107 1030 p3.c
prompt> cat p3.c | wc
	29 107 1030

▪ 표준 입출력도 파일로 취급 → 파일을 변경하는 효과

 

❑ 프로그램 내 재지정 구현

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

int main(int argc, char *argv[]){
	int rc = fork();
	if (rc < 0) { // fork failed; exit
		fprintf(stderr, "fork failed\n");
		exit(1);
	} else if (rc == 0) { // child: redirect standard output to a file
		close(STDOUT_FILENO);
		open("./p4.output", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
		// now exec "wc"...
		char *myargs[3];
		myargs[0] = strdup("wc"); // program: "wc" (word count)
		myargs[1] = strdup("p4.c"); // argument: file to count
		myargs[2] = NULL; // marks end of array
		execvp(myargs[0], myargs); // runs word count
	} else { // parent goes down this path (main)
        int wc = wait(NULL);
	}
	return 0;
}

 

▪ 실행 결과

prompt> ./p4
prompt> cat p4.output
32 109 846 p4.c
prompt>

 

❑ 기타 APIs

    ▪ getpid(), getppid(), …

    ▪ 프로세스 그룹과 세션

    ▪ 시그널 처리: sigaction(), sigprocmask(), kill(), raise(), …

❑ Shell과 프로세스 제어

    ▪ 외부 명령 (kill)으로 특정 시그널 전달: SIGINT, SIGTSTP, ..

    ▪ 명령어로 프로세스 제어: fg, bg, jobs, kill, …

❑ 사용자 (user)

    ▪ 자원의 사용 권한 제어

    ▪ 일반 사용자 vs. 관리자 (superuser)