*프로세스 생성
1. UNIX , LINUX 및 Windows 와 같은 대부분의 현대 운영체제들은 유일한 프로세스 식별자(pid)를 사용하 여 프로세스를 구분하는데 이 식별자는 보통 정수이다. pid는 각 프로세스에 고유의 값을 가지게 한다.
2. 프로세스 트리
3. 프로세스들의 목록 명령어 : ps -el
4. 일반적으로 프로세스가 자식 프로세스를 생성할 때, 그 자식 프로세스는 자신의 임무를 달성하기 위하여 어떤 자원(CPU 시간, 메모리, 파일, 입출력 장치)이 필요하다.
* 프로세스가 새로운 프로세스를 생성할 때, 두 프로세스를 실행시키는 데 두가지 가능 방법.
첫번째.
1. 부모는 자식과 병행하게 실행을 계속한다.
2. 부모는 일부 또는 모든 자식이 실행을 종료할 때까지 기다린다.
두번째.
1. 자식 프로세스는 부모 프로세스의 복사본이다. ( 자식 프로세스는 부모와 똑같은 프로 그램과 데이터를 가진다.)
2. 자식 프로세스가 자신에게 적재될 새로운 프로그램을 갖고 있다.
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int pid;
/* new process create (fork) */
pid = fork();
if(pid < 0) {
fprintf(stderr, “Fork Failed”);
return 1;
}
else if(pid == 0) {
execlp(“/bin/ls”, “ls”, NULL);
}
else {
/* parent process waiting for child process */
wait(NULL);
printf(“Child Complete”);
}
return 0;
}
*부모 프로세스 에서 자식 프로세스들 중 하나의 실행을 다음과 같은 이유로 종료시킨다.
1. 자식이 자신에게 할당된 자원을 초과하여 사용할 때, 이때는 부모가 자식들의 상태를 검사할 수 있는 방편이 주어져야 한다.
2. 자식에게 할당된 테스크(Task)가 더이상 필요 없을 때
3. 부모가 exit를 하는데, 운영체제는 부모가 exit한 후에 자식이 실행을 계속는것을 허용하지 않는 경우
*좀비 프로세스 : 프로세스 종료 상태가 저장되는 프로세스 테이블의 해당 항목은 부모 프로세스가 wait()를 호출할 때까지 남아있게 되는데, 종료되었지만 부모프로세스가 아직 wait() 호출을 하지 않은 프로세스
*고아 프로세스 : 부모 프로세스가 wait()를 호출하는 대신 종료하고 남은 자식 프로세스
*공유 메모리 시스템
- 공유 메모리를 사용하는 프로세스간 통신에서는 통신하는 프로세스들이 공유 메모리 영역을 구축해야 하 고, 공유 메모리 영역은 공유 메모리 세그먼트를 생성하는 프로세스의 주소 공간에 위치한다.
※일반적으로 운영체제는 한 프로세스가 다른 프로세스의 메모리를 접근하는것을 금지해야 함!
공유 메모리는 둘 이상의 프로세스가 일반적으로 한 프로세스가 다른 프로세스의 메모리에 접근 금지 해야 한다는 이 제약을 제거하는 것에 동의하는것이 필요하다. 그런 후에 프로세스들은 공유 영역에 읽고 씀으로 써 정보를 교환할 수 있다. 데이터의 형식과 으ㅟ치는 이들 프로세스들에 의해 결정되며, 운영체제의 소관 이 아니다 또한 프로세스들은 동시에 동일한 위치에 쓰지 않도록 책임져야 한다.
*생성자 프로세스 : 프로세스 정보 생성
*소비자 프로세스 : 프로세스 정보 소비
*다중코어 프로그래밍
-코어가 여러 CPU 칩 형태를 따거나 칩안에 여러개가 존대하든지 이러한 시스템을 다중코어 또는 다중처리 기 시스템이라고 불린다.
Amdahl’s Law (암달의 법칙)
단일코어 시스템 병행실행 과 다중코어 시스템 병행실행
*다중코어 시스템 프로그래밍
1. 테스크 인식 (Identifying Task) : 응용을 분석하여 독립된 병행가능 테스크로 나눌 수 있는 영역을 찾는 작업이 필요하며, 테스크는 서로 독립적이고, 개별 코어에서 병렬 실행 될 수 있어야 한다.
2. 균형 (Balance) : 전체 작업에 균등한 기여도를 가지도록 테스크를 나누는 것은 매우 중요하다
3. 데이터 분리 (Data Spliting) : 테스크가 접근하고 조작하는 데이터는 개별 코어에서 사용 할 수 있도록 나누어져야 한다.
4. 데이터 종속성 (Data Dependency) : 테스크가 접근하는 데이터는 둘 이상의 테스크 사이에 종속성이 없 는지 검토되어야 한다.
5. 시험 및 디버깅 (Testing and Debugging) : 프로그램이 다중코어에서 병렬로 실행될 때 다양한 실행 경 로가 존재 할 수 있어야 한다.
다중 스레드 모델
*다대일 모델 (Many-to-One Model)
- 많은 사용자 수준 스레드를 하나의 커널 스레드로 사상한다.
*일대일 모델 (One-to-One Model)
- 각 사용자 스레드를 각각 하나의 커널 스레드로 사상한다.
*다대다 모델 (Many-to-Many Model)
- 다대다 모델은 여러개의 사용자 수준 스레드를 그보다 작은 수 혹은 같은수 커널 스레드로 멀티 플렉스 한다.
#include <pthread.h>
#include <stdio.h>
int sum;
void * runner(void *param);
int main(int argc, char *argv[]) {
pthread_t tid; /* the thread identifier */
pthread_attr_t attr; /* set of attributes for the thread */
if(argc != 2) {
fprintf(stderr, “usage : a.out <interger value>\n”);
return -1;
}
if(atoi(argv[1] < 0) {
fprintf(stderr, “%d must be >= 0\n”, atoi(argv[1]));
return -1;
}
/* get the default attributes */
pthread_attr_init(&attr);
/* create the thread */
pthread_create(&tid, &attr, runner, argv[1]);
/* now wait for the thread to exit */
pthread_join(tid,NULL);
printf(“ sum = %d\n”, sum);
}
void *runner(void *param) {
int i, upper = atoi(param);
sum = 0;
for(i = 1; i<=upper; i++) {
sum+=1;
}
pthread_exit(0);
}
Pthread를 이용한 멀티스레드 구현
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void *t_function(void *data) {
int id;
int i = 0;
id = *((int *)data);
while(1) {
printf("(%lu) %d : %d\n",pthread_self(), id, i);
i++;
if(i==5) {
return (void *)i;
sleep(1);
}
}
}
int main(void) {
pthread_t p_thread[2];
int thr_id;
int status;
int a = 1;
int b = 2;
thr_id = pthread_create(&p_thread[0],NULL,t_function,(void *)&a);
if(thr_id <0) {
perror("thread create error: ");
exit(0);
}
thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
if(thr_id < 0) {
perror("thread create error : ");
exit(0);
}
pthread_join(p_thread[0], (void **)&status);
printf("return thread 0 %d\n",status);
pthread_join(p_thread[1], (void **)&status);
printf("return thread 1 %d\n",status);
return 0;
}
*Window 스레드
1. 각 스레드를 유일하게 지목하는 스레드 ID
2. 처리기의 상태를 나타내는 레지스터 집합
3. 사용자 모드에서 실행될 때 필요한 사용자 스택, 커널 모드에서 실행될 때 필요한 커널 스택
4. 실행 시간 라이브러리와 동적 링크 라이브러리(DLL) 등이 사용하는 개별 데이터 저장영역
*리눅스 스레드
-프로세스를 복제하는 기능을 가진 fork() 시스템 호출을 제공하고, clone() 시스템 호출을 이용하여 스레드 를 생성할 수 있는 기능도 제공한다. 그러나 리눅스는 프로세스와 스레드를 구별하지 않는다. (프로세스 나 스레드 보단 테스크 라는 용어를 사용)