[Linux, OS] Process creation, Thread, Multithreading

pos++·2023년 11월 5일
0

Operating System

목록 보기
2/2
post-thumbnail

2023.10.31 TIL2

Process creation

fork()

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

int main()
{
	int pid;

	pid = fork();
	if (pid == 0)
		/* child */
		printf("Child of %d is %d\n", getppid(), getpid());
	else
		/* parent */
		printf("I am %d. My child is %d\n", getpid(), pid);
}

Process includes…

  • address space (code, data)
  • OS resources, accounting information
  • Hardware execution state (PC, SP, registers, etc.)

→ Heavy-weight

  • Process Creation is costly
  • Inter-process communication is costly
    • System call, Data copy overhead

Web server example

  • Parallel request handling을 위한 fork()
    • Space : PCB, Page tables, etc.
    • Time : OS structure creation, fork(), Address space copying, etc.

Process → Parent vs Child

What’s similar

  • Code, data (addres space)
  • 권한
  • Resources (files, sockets, etc.)

What’s different

  • Hardware execution state (PC, registers, SP, stack)

→ Process 개념을 Execution state에서 분리하자!

Execution state

→ Thread (= Lightweight process)

Thread

꼭 따로 가져야 하는 것들만 TCB로

  • PC
  • Registers
  • Stack → local variables, return addresses
  • State

Thread끼리 공유하는 것들

  • Process instructions
  • Data (most of them)
  • OS state of a process (most of them)


Multithreading

Benefits

  • Creating concurrency is cheap (Time, Memory)
  • Improves program structure
  • Higher throughput
  • Better responsiveness
  • Better resource sharing
    • All see the same address space

Process와의 공통점

  • 각자 logical control flow 가짐
  • 다른 애들과 동시에 실행 가능
  • 각자 독립적으로 context switched

Process와의 차이점

  • Thread는 code와 일부 data를 공유
  • Thread는 비용이 더 적다
    • Linux의 경우 Process create and reap : ~20K cycles / Thread create and reap ~10K cycles

Threads Interface : pthreads

  • POSIX-style thread
  • 표준으로 가장 많이 쓰임
  • #include <pthread.h>

pthreads “Hello World!” program

#include <stdio.h>
#include <pthread.h>

void *threadfunc(void *vargp);

/* thread routine */
void *threadfunc(void *data) {
	sleep(1);
	int *count = (int *)data;
	printf("Hello World! &d\n", *count);
	return NULL;
}

int main() {
	pthread_t tid;  // int값이라고 생각해도 된다
	int k = 100;

	pthread_create(&tid, NULL, threadfunc, (void *)&k);  // (tid, 환경변수, thread가 생성되면 실형되어야 하는 함수, threadfunc의 parameter)
	/* 이제 main함수과 threadfunc함수가 동시에 동작한다 */
	printf("main\n");
	pthread_join(tid, NULL);  // thread가 끝날때까지 대기. fork()의 wait과 비슷
	printf("main2\n");
	sleep(2);
	
	return 0;
}

Multithreading Example1

명령행인자로 자연수 N을 입력받는다.
main은 두 개의 thread를 생성하고, 하나는 0~N의 합, 하나는 N 팩토리얼을 계산해 출력한다.
main thread는 두 개의 thread가 계산을 마치면 sum과 factorial의 합을
출력한다.

sumfact.c

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

int sum = 0;  // global variable
int fac = 1;  // global variable

void *threadSum(void *data) {
	int n = *((int *)data));

	for(int i = 1; i <= n; i++) {
		sum += i;
	}
	printf("sum = %d\n", sum);
	sf += sum;

	return NULL;
}

void *threadFac(void *data) {	
	int n = *((int *)data));

	for(int i = n; i > 0; i--) {
		fac *= i;
	}
	printf("fac = %d\n", fac);
	sf += fac;
	return NULL;
}

int main(int argc, char **argv) {
	pthread_t tid_sum, tid_fac;

	int n = atoi(argv[1]);
	
	pthread_create(&tid_sum, NULL, threadSum, &n);
	pthread_create(&tid_fac, NULL, threadFac, &n);

	pthread_join(tid_sum, NULL);
	pthread_join(tid_fac, NULL);

	printf("sum + fac = %d\n", sum+fac);
	return 0;
}

Multithreading Example2

구구단을 출력하는 프로그램 작성.
9개의 thread를 생성하여, 하나의 thread가 하나의 단을 출력한다.
9개의 thread는 병렬로 수행되므로 출력순서가 섞일 수 있다.

99.c

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

void *threadfunc(void *data) {
	int n = *((int *)data);

	for(int j = 1; j <= 9; j++) {
		printf("%d * %d = %d\n", n, j, n*j);
	}

	return NULL;
}

int main() {
	pthread_t tid[9] = {0,};
	
	int i = 0;

	for(i = 1; i <= 9; i++) {
		pthread_create(&tid[i - 1], NULL, threadfunc, (void *)&i);
	}

	for(i = 1; i <= 9; i++) {
		pthread_join(tid[i - 1], NULL);
	}

	return 0;
}
profile
밀린 TIL 업로드 조금씩 정리중...

0개의 댓글