프로세스
- 프로세스
- 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램
- 프로그램을 구동하여 프로그램 자체와 프로그램의 상태가 메모리 상에서 실행되는 작업의 단위
- 메모리에 적재된 프로그램의 명령어를 CPU가 실행함으로써 동작됨
- 한 프로세스는 하나의 프로그램 수행에 대응됨
- 하나의 프로그램을 여러번 구동하면, 여러 개의 프로세스가 실행됨
- 하나의 프로그램을 여러번 구동하면, 여러 개의 프로세스가 실행됨
- 프로그램
- 컴퓨터에서 실행될때 특정 작업을 수행하는 일련의 명령어들의 모음을 말함
- 하드 디스크 등에 저장되어 있는 실행 코드
프로세스의 상태
- 커널 내에는 준비 큐, 대기 큐, 실행 큐 등의 자료구조가 있으며, 커널은 이것을 이용하여 프로세스의 상태를 관리함
- 프로세스의 상태
- 생성(create)
- 프로세스가 생성되는 상태
- 준비(Ready)
- 프로세스가 CPU를 사용하고 있지는 않지만, 언제든지 사용할 수 있는 상태
- 대기(Waiting)
- 프로세스가 입출력 완료, 시그널 수신 등 어떤 사건을 기다리고 있는 상태
- 보류(block)라고 부르기도 함
- 완료(Terminated)
- 프로세스의 실행이 종료된 상태
- 프로세스의 실행이 종료된 상태
- 생성(create)
시분할
- 시분할
- 각 프로세스에 CPU의 시간 자원을 할당하고, 교대로 반복 실행하는 것
- 시간 슬라이스
- 프로세스가 선점 다중 작업 시스템에서 실행할 수 있는 시간대
- 퀀텀이라고도 함
- 병렬처리로 작동하는 것과 같은 착각을 주지만, 실제로는 작은 시간 슬라이스에 의해 전환되며 처리됨
- 프로세서가 여러 사용자의 프로그램을 처리하지만, 사용자는 자신의 프로그램만을 처리하는 것처럼 느낌
컨텍스트 스위치
- 컨텍스트 스위치
- CPU가 기존의 프로세스에서 다음 프로세스를 수행하도록 새로운 프로세스의 상태 또는 레지스터를 교체하는 작업
- CPU가 기존의 프로세스에서 다음 프로세스를 수행하도록 새로운 프로세스의 상태 또는 레지스터를 교체하는 작업
- 프로세스 컨텍스트
- 컨텍스트 스위치로 인해 실행이 중단된 이후, 스케쥴러에 의해 다시 실행될 때 필요한 프로세스와 그에 대한 정보
- 컨텍스트에는 다음정보가 포함됨
- 프로세스 상태
- 프로그램 카운터
- 레지스터
- 프로세스 번호
- 컨텍스트는 프로세스의 PCB에 저장됨
프로세스 함수
프로세스 번호
- 프로세스 번호 PID
- UNIX 계열의 운영체제는 각 프로세스에 부여하는 음이 아닌 정수
- 각 프로세스는 고유한 프로세스번호를 가지고 있음
- 실제로는 특수한 프로세스를 위하여 0과 1은 부여되지 않음
- 0번 프로세스 : 스와퍼 프로세스
- 1번 프로세스 : 초기화 프로세스
- 프로세스가 종료되면 해당 프로세스 번호는 재사용이 가능함
getpid() 함수
#include <unistd.h>
pid_t getpid(void);
- 설명
- 현재 프로세스의 PID를 반환
- 인자
- 없음
- 반환
- 현재 프로세스의 PID
- 오류가 발생하는 경우 없음
getppid() 함수
#include <unistd.h>
pid_t getppid(void);
- 설명
- 현재 프로세스의 부모 프로세스의 PID를 반환
- 인자
- 없음
- 반환
- 부모 프로세스의 PID
- 오류가 발생하는 경우 없음
exit() 함수
#include <stdlib.h>
void exit(int status);
- 설명
- 현재 프로세스를 정상적으로 종료함
- status & 0377 값을 부모 프로세스에 전달함
- 인자
- status : 프로세스의 종료 상태 (0과 255 사이의 정수)
- 반환
- 없음
fork() 함수
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void)
- 설명
- 현재 프로세스와 거의 동일한 자식 프로세스를 생성함
- 현재 프로세스의 메모리 이미지를 새로운 메모리 영역에 복사함으로써, 자식 프로세스는 부모프로세스의 메모리 공간 복사본을 가짐
- 인자
- 없음
- 반환
- 성공
- 부모 프로세스에게 자식 프로세스의 PID
- 자식 프로세스에게 0
- 오류시 -1
- 성공
wait() 함수
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int * status);
- 설명
- 자식 프로세스가 종료할 때까지 대기함
- 부모 프로세스가 자식 프로세스 보다 먼저 종료되는 것을 방지하기 위함
- 인자
- status : 자식 프로세스의 종료상태를 저장할 메모리 공간에 대한 포인터
- 종료 상태에 따라 다른 값이 저장됨
상위 1바이트 (8비트) 최하위 1바이트(8비트) 정상 종료된 경우 프로세스 종료 상태 비정상 종료된 경우 프로세스를 종료한 시그널 번호 - 비트 연산을 통해 프로세스 종료 상태 또는 반환값을 확인할 수 있음
- 미래에 시스템 또는 컴파일러가 변경될 경우, 비트 연산은 문제가 될 수 있음
- 종료 상태에 따라 다른 값이 저장됨
- 따라서, 프로세스 종료 상태를 확인하는 매크로를 제공함
- status : 자식 프로세스의 종료상태를 저장할 메모리 공간에 대한 포인터
- 반환
- 성공 시 종료한 자식 프로세스의 PID
- 오류시 -1
상위 1바이트(8비트)
waitpid() 함수
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int * status, int options);
- 설명
- 특정 자식 프로세스가 종료할 때까지 기다림
- 인자
- pid : 자식 프로세스의 PID
- status : 자식 프로세스의 종료상태를 저장할 때 메모리 공간에 대한 포인터
- options : 함수의 동작을 제어하는 옵션
- sys/wait.h 헤더파일에 정의된 다음의 플래그를 OR비트 연산자와 함께 사용할 수 있음
- WNOHANG : 자식 프로세스가 종료되지 않더라도, 즉시 반환
- WUNTRACED : 멈추거나 상태가 보고되지 않은 자식들을 위해 반환
- 위의 제어가 필요하지 않은 경우에는 0을 사용
- sys/wait.h 헤더파일에 정의된 다음의 플래그를 OR비트 연산자와 함께 사용할 수 있음
- 반환
- 성공 시 종료한 자식의 프로세스 PID
- 오류시 -1
wait()과 waitpid() 함수 예시
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
int val = 10;
pid_t pid = 0;
int status = 0;
printf("Hello My PID is %d\n", getpid());
pid = fork();
if (pid == -1) {
perror("fork() error");
exit(-1);
} else if (pid == 0) {
printf("I'm a child. My PID is %d\n", getpid());
printf("I'm child. My parent PID is %d\n", getppid());
val += 1;
} else {
printf("I'm parent. My child PID is %d\n", pid);
wait(&status);
printf("I'm parent. My child PID is exited\n");
}
printf("My PID is %d, val is %d\n", getpid(), val);
return 0;
}
프로세스 종료 상태 매크로
- 프로세스 종료 상태를 확인하는 매크로
프로세스 종료 상태 매크로 예시
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t pid = 0;
int status = 0;
printf("Hello My PID is %d\n", getpid());
pid = fork();
if (pid == -1) {
perror("fork() error");
exit(-1);
} else if (pid == 0) {
printf("I'm a child. My PID is %d\n", getpid());
exit(1);
} else {
wait(&status);
**if ((status == 0) || (status > 255))**
printf("child PID is exited with %d\n", **status >> 8**);
else {
printf("child PID is exited with %d\n", status);
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t pid = 0;
int status = 0;
printf("Hello My PID is %d\n", getpid());
pid = fork();
if (pid == -1) {
perror("fork() error");
exit(-1);
} else if (pid == 0) {
printf("I'm a child. My PID is %d\n", getpid());
exit(1);
} else {
wait(&status);
**if (WIFEXITED(status))**
printf("child PID is exited with %d\n", **WEXITSTATUS(status)**);
else {
printf("child PID is exited with %d\n", status);
}
}
return 0;
}
프로그램 실행 함수
execl() 함수
#include <unisd.h>
int execl(const char * path, const char * arg, ...);
- 설명
- 현재 프로세스의 이미지를 새로운 프로세스 이미지로 덮어씀
- 실행 가능한 파일을 실행함
- 인자
- path : 실행 가능한 파일의 경로
- arg, … : 실행할 파일의 명령형 인자(가변 인자)
- 마지막 인자는 항상 NULL
- 반환
- 오류시 -1
execl() 함수 예시
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t pid = 0;
int status = 0;
pid = fork();
switch (pid) {
case -1:
perror("fork() error");
exit(-1);
case 0:
execl("/bin/ls", "ls", "-a", "-l", NULL);
break;
}
if (pid > 0) {
wait(&status);
}
return 0;
}
execv() 함수
#include <unistd.h>
int execv(const char * path, char const *argv[]);
- 설명
- 현재 프로세스의 이미지를 새로운 프로세스 이미지로 덮어씀
- 실행 가능한 파일을 실행함
- 인자
- path : 실행 가능한 파일의 경로
- argv : 실행할 파일의 명령행 인자를 저장할 배열
- 배열의 마지막 요소는 항상 NULL
- 반환
- 오류시 -1
execv() 함수 예시
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t pid = 0;
int status = 0;
char *args[] = {"ls", "-a", "-l", NULL};
pid = fork();
switch (pid) {
case -1:
perror("fork() error");
exit(-1);
case 0:
execv("/bin/ls", args);
break;
}
if (pid > 0) {
wait(&status);
}
return 0;
}
execve() 함수
#include <unistd.h>
int execve(const char * path, char const * argv[], char const * envp[]);
- 설명
- 현재 프로세스의 이미지를 새로운 프로세스 이미지로 덮어씀
- 실행 가능한 파일을 실행함
- 인자
- path : 실행 가능한 파일의 경로
- argv : 실행할 파일의 명령행 인자를 저장할 배열
- 배열의 마지막 요소는 항상 NULL
- envp : 환경변수를 저장할 배열
- 배열의 마지막 요소는 항상 NULL
- 반환
- 오류시 -1
execve() 함수 예시
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t pid = 0;
int status = 0;
char *args[] = {"ls", "-a", "-l", NULL};
char *envp[] = {"USER=sohee", "HOME=/home/sohee/", NULL};
pid = fork();
switch (pid) {
case -1:
perror("fork() error");
exit(-1);
case 0:
execve("/bin/ls", args, envp);
break;
}
if (pid > 0) {
wait(&status);
}
return 0;
}
execvp() 함수
#include <unistd.h>
int execvp(const char * name, char const * argv[]);
- 설명
- 현재 프로세스의 이미지를 새로운 프로세스 이미지로 덮어씀
- 환경 변수에 등록된 실행가능한 파일을 실행함
- 인자
- name : 실행 가능한 파일의 이름
- argv : 실행할 파일의 명령행 인자를 저장할 배열
- 반환
- 오류시 -1
execvp() 함수 예시
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
pid_t pid = 0;
int status = 0;
char *args[] = {"ls", "-a", "-l", NULL};
pid = fork();
switch (pid) {
case -1:
perror("fork() error");
exit(-1);
case 0:
execvp("ls", args);
break;
}
if (pid > 0) {
wait(&status);
}
return 0;
}
'시스템 소프트웨어' 카테고리의 다른 글
연결 리스트 (Linked list) (0) | 2023.03.08 |
---|---|
배열과 문자열 (Array and String) (0) | 2023.03.07 |
시그널 (Signal) (0) | 2023.03.07 |
파일과 디렉토리 (File and Directory) (0) | 2023.02.05 |
파일 입출력 (File Input Output) (0) | 2023.02.04 |