SoftWare Study/Operating System

공룡책 - 운영체제 정리3

KoTiv 2021. 11. 21. 17:06
반응형
SMALL

본 게시물은 Abraham Silberschatz의 Operating System Concepts  공룡책을 참고하며 

개인적으로 공부 및 정리한 자료입니다. 


Process

Thread 

 

Process Sysnchronization

CPU Scheduling


  • Process
    • 프로그램 : 디스크에 저장된 passive 개체
    • 프로세스 : 실행되는 active 개체 / 자기만의 주소공간을 가진 독립적인 프로그램 (self contain )
      • User가 작성한 프로그램이 OS에 의해 memory 공간을 할당받아 실행중인것 
      • Process는 자식 프로세스 ( 하위 프로세스를 시작할 수 있음 )
      • 프로그램 -> 메모리 로드 -> 프로세스
      • 부모 프로세스가 종료시 더이상 존재할수 없음 (자식 프로세스 기준)
        • 프로세스 자원은 OS에의해 제어를 받으며 실행, 대기, 중단 ,좀비상태중 한 상태로 존재함             

프로그램 -> 메모리 로드 -> 프로세스 

  1. Batch system : Jobs
  2. Time-Shared syetem : 사용자 프로그램 or Jobs
  3. Process : 실행중인 프로그램 , (순차적 실행)
  4. part
    1. Text section ( code )
    2. Program counter & processor register를 포함하는 현재 작업 
    3. Stack : 임시 데이터 포함한 데이터들이 0xffff 부터 할당됨 ( 메모리 구조에서 다시나옴 )
    4. Heap : 런타임 동안 동적으로 메모리 할당하여 0x0000부터 쌓임 . maybe
    5. Data section : 함수 parameter , 반환 주소 , 전역 지역변수 

 

더보기
  • Demon Process
    • 백그라운드로 실행되는 프로세스 -> 부팅시에 자동으로 시작.
  • Multi Process
    • 2개 이상의 process 실행
    • Program이 여러 개 띄워져있는 형식
  • Multi Tasking
    • 2개 이상의 process 실행 후 일 처리
1. single Threa process , 2. multi Process , 3 multi Thread Proecess

 


Process State & Process Control Block

특정 프로세스에 대한 중요한 정보를 저장하는 OS의 자료구조

프로그램이 메모리에 할당되어 실행될때 프로세스의 상태가 5개의 상태중 1개로 변하게됨

  • new : 프로세스 생성상태
  • running : 실행상태 
  • waiting : 이벤트 발생으로 프로세스 대기상태 
  • ready : 프로세서에 할당하기위해 프로세스 대기상태 
  • terminated  : 실행종료 

PCB에 저장되는 정보

1.프로세스 식별자 (PID):프로세스 식별정보
2.프로세스 상태 : new, ready, running, waiting, terminated
3.프로그램 카운터 : 프로세스가 다음에 실행할 명령어의 주소
4.CPU register
5.CPU 스케쥴링 정보: 프로세스 우선순위, 스케줄 큐에 대한 포인터..
6.메모리 관리 정보 : 페이지 테이블, or 세그먼트 테이블 등과 같은 정보.
7.입출력 상태 정보 : 프로세스에 할당된 입출력 장치들과 열린 파일 목록
8.어카운팅 정보 : 사용된 CPU시간, 시간제한, 계정번호 등.

** PDI : (Process identification num)

: 프로세스의 고유 번호,

 리눅스 부팅시 모든 프로세스의

최상위 프로세스인 Systemd(PID=1)

이 생성 및 모든 프로세스들은

1번 프로세스의 자식프로세스가 된다.

부모 프로세스 ; PPDI


PCB - Process Control Block 

Process state - 프로세스 상태 값 

Process counter -  다음 실행 명령어의 위치값

Cpu register - 프로세스 중심의 레지스터 내용

CPU scheduling - 우선순위 정보, 스케쥴링 큐포인터 등 .

Memory-management info - 프로세스에 할당된 메모리

Accounting info - CPU 시작이후 경과된 시간, 시간제한 정보등 

I/O status info - 프로세스에 할당된 I/O장치,  파일목록 .


/*
* Process State block 
*/
#include <stdio.h>
#define MAX 100

enum process_state
{
	STOP	= 0.
    NEW 	= 1,
    RUN 	= 2,
    WAIT	= 3,
    READY	= 4,
    EXIT	= 5,
    ABRNOMAL	= 6,
    MAX		= 7
};

typdef struct _cpu_sche
{
	int priority;
    queue q[MAX];
}CPU_SCH;

typedef struct
{
	char *key;
    char *value;
}Hash;

tydef struct _mem_info
{
	Hash *hash;
    size_t size;
    size_t capacity;
}MEM_info, IOstate;

typedef struct _process_control_block
{
	ptrhead_t pid;
	int p_state; // STOP = 0, NEW = 1, RUN 2 WAIT 3
    int* p_counter;
    char* cpu_reg;
    CPU_SCH  cpu_sche[1];
    MEM_info mem_info[1];
    IOstate io_state[1];
}PCB;

void main()
{
	PCB pcb;
	int a;
    a =pcb.p_state;
    pcb.p_state = STOP;
    
    
    // job create thread create 
    pcb.p_state = NEW;
    
    //job start
    pcb.p_state = RUN;
    while(1)
    {
    /*
    * job running (thread )
    */
    	if(exit)
    	{
    		pcb.pstate = EXIT; break;
		}
    }
}

대충짜본 C 코드다 대충 이런흐름이 지않을까

 

Mobile System in Process

모바일 시스템은 하나의 프로세스만 실행하도록 허용함

- 물리적 한계 ( 화면공간의 물리적 한계로 사용자 인터페이스에 제한이 걸리는것 때문 ) 

<1> Multiple Back ground process 

 메모리 상에서 실행중 이나 , 디프플레이되지 않으며 싱글 , 짧은 작업, 장기 실행 작업, 이벤트 알림, 오디오재생등 제한적인 프로세스.

 

<2> Context Switch

 CPU가 다른 프로세스로 전환시 시스템은 이전의 프로세스 상태를 저장후 PCB에 표현된 프로세스의 Context switch를 통해 새 프로세스에 대해 저장된 상태를 로드해야함.

 

CONTEXT Switch 전환시간 : 전환하는동안 작업을 하지않음 . 

1. OS & PCB 복잡할수록 전환시간이 길어짐 .

2. 하드웨어 지원에 따른 시간 -> 여러 register가 한번에 로드될때 시간이 지연됨 .

 

 

  • <1> 프로세스 생성 

부모 프로세스(상위 프로세스) 는 자식 프로세스(하위 프로세스) 를 생성하며 프로세스 트리를 형성함 

- tree 프로세스 형태.

프로세스를 관리 하기위해서 PID를 통하여 식별 및 관리하게됨.

공유자원 옵션

1. 부모(상위)프로세스와 자식(하위)프로세스는 Resource 를 공유함.

2. 자식 프로세스(하위)프로세스는 부모(상위)프로세스의 자원의 한부분을 공유함.

3. 부모 프로세스와 자식프로세느는 리소스를 모두 공유하지 않음. ( ???? )

 

실행 옵션

-상위 하위 프로세스는 동시 실행이 안됨 

-부모프로세스는 자식프로세스가 종료시까지 대기중임.

 

주소공간

 - 하위 프로세스는 상위 프로세스를 복제함.

 - 자식 프로세스는 프로그램을 로딩함 (??? 조사후에 다시 ... ) 

Unix 에서는 fork() 를 써서 새로운 프로세스를 생성함 , fork후에 exec()를 실행하여 메모리공간에 할당.


  • <2> 프로세스 종료

exit() 시스템 호출을 사용하여 프로세스 삭제 요청 .

wit() 함수를 통해 하위 프로세스에서 상위프로세스로 상태 데이터 전송

프로세스 리소스는 OS에의해 할당 해제함.

abort()를 통해 상위프로세스에서 하위 프로세스의 실행을 종료 할수도있음 .

 1. 하위 프로세스의 할당 리소스 초과한경우 abort()사용 

 2. 상위 프로세스로부터 하위프로세스의 작업이 더이상 필요치 않을때 종료 

 3. 상위 프로세스가 종료시 - Tree 구조로 인하여 상위 프로세스가 종료시 하위 프로세스 모두 종료됨.

 3.1 OS에의하여 종료가 시작됨  -> wait()시스템 호출후 하위프로세스의 종료를 대기 및 하위 프로세스의 상태정보 및 pid값을 반환받음 . 

  ** 대기 중인 상위 프로세스가 없이 하위프로세스가 있다면 좀비프로세스임 . 

 



  • Thread

위의 코드를 봐도 while(1){} 구문으로 메인 함수를 계속 실행하고있다 . 

만약 특정 이벤트 혹은 단어가 들어오면 pcb state값을 exit로 변형하고 루프문을 종료후 프로세스가 꺼질것이다.

마찬가지로 본다면 모든 APP 프로세스는 싱클 스레드기반으로 실행을한다 . 

 

** 프로세스의 생성은 무겁고 스레드 생성은 가볍다 

-부모 프로세스로부터 프로세스의 모든정보를 가져온다는 점에서 생성이 무겁다 말하는것같다 . 

- 스레드는 프로세스안에서 자원을 제외한 정보를 생성하는점에서 가볍다.

- 커널은 대체로 다중 스레드 기반이다.

더보기
  • 프로세스의 실행 단위.
    • 한 프로세스 내에서 동작되는 여러 실행 흐름.
    • 프로세스 내의 주소 공간 혹은 자원을 공유.
  • 멀티 스레드
    • 하나의 프로세스를 다수의 실행 단위로 구분
      • 자원을 공유, 자원 생성, 관리 및 중복성 최소화.
      • 각각의 스레드는 독립적인 작업을 수행
        • 각자의 스택과 pc레지스터 값을 가진다.
  •  
    • 스택 메모리 공간 (독립) -> 독립 함수 호출가능 -> 독립적 실행 흐름 추가의 최소조건 = 독립 스택 할당.
  • 스택을 스레드마다 독립적으로 할당하는 이유

스택 : 함수 호출 시 전달되는 인자, return address,

함수 내에서 선언하는 변수 등을 저장하기 위해 사용하는 메모리 공간.

  • PC register를 스레드마다 독립적으로 할당하는 이유
    • 명령어의 수행과정을 보여줌.
    • 명령어가 어느부분까지 수행하는지 기억할 필요가 있음

 

Multi Thread

 

 

 


1개의 프로세스가 multiple program counter를 고려한다면 .

<1> 여러 위치의 프로그램을 한 번에 실행할 수 있다. 즉 스레드를 활용하여 멀티스레드를 제어할수 있다.

<2> 즉 PCB 블록에 PROGRAM COUNTER정보 및 THREAD에 대한 detail한 정보를 저장해서 가지고있어야한다.


 

typedef struat _Task_struct
{
	pid t_pid; /* process id */
    long state; /* state */
    unsigned int time_slice /* scheduling info */
    struct task_struct *parent; // parent procee 
    struct list_head children; //child struct
    struct files_struct *files; // file list info
    struct mm_struct *mm; // address info
 }

 


Thread Concept

더보기

<1> 멀티 스레드 기반 서버 구조 

<2> Multicore Programming 

Dividing activities / Balacne (큐에 쌓인 데이터와 함께 부하와 관련있던것으로 기억함) /

Data splitting / Data dependency / Testing and debugging /  


<2.1> Concurrency & Parallelism 

Concurrency : 하나 이상의 작업 진행을 지원함&amp;amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;amp;nbsp;
Parallism : 시스템이 동시에 둘 이상의 작업을 수행할 수 있도록 함.

Parallelism type  

          1. Data Parallelism : 동일한 데이터의 하위 집합을 여러 코어에 분산하여 각 코어에서 동일한 작업 시행

          2. Task Parallelism :  각 스레드가 고유작업을 수행하는 코어 전체에 스레드를 분산함 .

<2.2> Single & Multi Thread Process 

# 스레드 수가 증가하면 스레드에 대한 아키텍쳐의 지원도 증가하게됨 . 

** CPU = CORE + H/W + THREAD를 가지고 있음 .


  • Amdahl's Law  ( 성능 향상 식별 방법 계산)
더보기

Speed up <= 1/ S+{ (1-S) /N }

 

S : serial portion

N : Processing cores 

만약 N is infinite -> speed up approximation 1/S  

 

** Serial portion 은 core 추가에 있어 불균형적인 효과를 낼수도 있음 .


  • User & Kernel Thread 
더보기
  • User Thread
    • 유저레벨 스레드 라이브러리로 운영됨 
      • POSIX Pthreads lib / POSIX standard IEEE 1003.1c 
      • Windows Threads lib
      • Java Threads
  • Kernel Thread
    • Kernel에서 운영됨
      • OS 
      • POSIX /POSIX standard IEEE 1003.1c 

  • Multi Threading Model
더보기
  • Many to One

1개의 kernel 스레드에 다수의 사용자 스레드가 매핑됨.

kernel스레드를 끊어버리면 사용자스레드 모두 끊김.

한 번에 하나의 스레드만 커널에 있을수 있음 ( 멀티 코어에서 병렬로 실행이 안될거임 ) 

  • One to One

커널스레드와 사용자 스레드가 1:1로 매핑됨 , 

사용자 스레드 생성시 커널이 생성됨 , N:1 model보다 동시성에 강함 . 

프로세스당 스레드수로 제한되는 이슈가 존재함 (overhead ) 

  • Many to Many

사용자 스레드와 커널스레드에 매핑가능 . 

  • Two level 
커널 스레드를 사용자스레드와 묶을수 있음

Thread implementation <1> classfication lib

더보기

<1> User lv (user)

  • Pthread
    • POSIX Pthreads lib / POSIX standard IEEE 1003.1c 
  • Windows Multi thread C
  • Java Thread

<2> Os lv (kernel)

  • Pthread
    • POSIX Pthreads lib / POSIX standard IEEE 1003.1c 

Thread implementaion in c <header file 분석>

더보기

- 스레드를 이요하여 소스파일을 컴파일 하기 위해서는 
- 소스파일에서 _REENTRANT 매크로 정의.

- 헤더파일 pthread.h 포함
- -lpthread 지정하여 라이브러리 링크 필수.

 

1. _REENTRANT 매크로 설정 이유.

  -include 함수들의 버퍼 한개를 사용하는데 겹치는 수가 생기기 때문.

ex) fput -> 단일 저녁 메모리 공간 사용.
-> 양쪽 모두 fput사용하는경우 메모리 공간상 어느 스레드가 쓰는지 예츨할 수 없는 경우 발생.
-> errno  변수 역시 어느 스레드에서 데이터가 들어온지 구분할수 없음.
-->re-entrant 루틴을 사용을 위해 _REENTRANT 추가.
-> 지역 변수만을 사용,  

-1.  일부 함수들이 재진입에 안전한 버젼으로 대체, 함수 이름에 _r을 붙인다.
-2.  보통 매크로로 구현되는 stdio.h는 일부 함수들이 적절한 안전 함수로 대체.
-3. errno.h errno 변수가 다중 스레드에 안전한 방식으로 오류 정보를 ㄷ로려주는 다른 함수의 호출로 변경.

 

 

<sys/type.h> -data types 정의

SYNOPSIS

#include <sys/types.h>

blkcnt_t Used for file block counts

blksize_tUsed for block sizes

clock_tUsed for system times in clock ticks or CLOCKS_PER_SEC (see <time.h>).

clockid_tUsed for clock ID type in the clock and timer functions

dev_tUsed for device IDs.

fsblkcnt_tUsed for file system block counts

fsfilcnt_tUsed for file system file counts

gid_tUsed for group IDs

id_tUsed as a general identifier; can be used to contain at least a

pid_t, uid_t or a gid_t.ino_tUsed for file serial numbers

key_tUsed for interprocess communication

mode_tUsed for some file attributes

nlink_tUsed for link counts

off_tUsed for file sizes

pid_tUsed for process IDs and process group IDs

pthread_attr_tUsed to identify a thread attribute object

pthread_cond_tUsed for condition variables

pthread_condattr_tUsed to identify a condition attribute object.

pthread_key_tUsed for thread-specific data keys.

pthread_mutex_tUsed for mutexes.

pthread_mutexattr_tUsed to identify a mutex attribute object.

pthread_once_tUsed for dynamic package initialisation.

pthread_rwlock_tUsed for read-write locks.

pthread_rwlockattr_tUsed for read-write lock attributes.

pthread_tUsed to identify a thread.

size_tUsed for sizes of objects.

ssize_tUsed for a count of bytes or an error indication.

suseconds_tUsed for time in microseconds

time_tUsed for time in seconds.

timer_tUsed for timer ID returned by timer_create().

uid_tUsed for user IDs.

useconds_tUsed for time in microseconds.

 

<Pthread.h> - 스레드 함수 정의

symbol

PTHREAD_CANCEL_ASYNCHRONOUS
PTHREAD_CANCEL_ENABLE
PTHREAD_CANCEL_DEFERRED
PTHREAD_CANCEL_DISABLE
PTHREAD_CANCELED
PTHREAD_COND_INITIALIZER
PTHREAD_CREATE_DETACHED
PTHREAD_CREATE_JOINABLE
PTHREAD_EXPLICIT_SCHED
PTHREAD_INHERIT_SCHED
PTHREAD_MUTEX_DEFAULT
PTHREAD_MUTEX_ERRORCHECK
PTHREAD_MUTEX_NORMAL
PTHREAD_MUTEX_INITIALIZER
PTHREAD_MUTEX_RECURSIVE
PTHREAD_ONCE_INIT
PTHREAD_PRIO_INHERIT
PTHREAD_PRIO_NONE
PTHREAD_PRIO_PROTECT
PTHREAD_PROCESS_SHARED
PTHREAD_PROCESS_PRIVATE
PTHREAD_RWLOCK_INITIALIZER
PTHREAD_SCOPE_PROCESS
PTHREAD_SCOPE_SYSTEM

SYNOPSIS

...함수가 너무많다 ... 필요한것만 골라봐야겠다....

 #include <pthread.h>

int   pthread_attr_destroy(pthread_attr_t *);
int   pthread_attr_getdetachstate(const pthread_attr_t *, int *);
int   pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
int   pthread_attr_getinheritsched(const pthread_attr_t *, int *);
int   pthread_attr_getschedparam(const pthread_attr_t *,struct sched_param *);
int   pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
int   pthread_attr_getscope(const pthread_attr_t *, int *);
int   pthread_attr_getstackaddr(const pthread_attr_t *, void **);
int   pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
int   pthread_attr_init(pthread_attr_t *);
int   pthread_attr_setdetachstate(pthread_attr_t *, int);
int   pthread_attr_setguardsize(pthread_attr_t *, size_t);
int   pthread_attr_setinheritsched(pthread_attr_t *, int);
int   pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
int   pthread_attr_setschedpolicy(pthread_attr_t *, int);
int   pthread_attr_setscope(pthread_attr_t *, int);
int   pthread_attr_setstackaddr(pthread_attr_t *, void *);
int   pthread_attr_setstacksize(pthread_attr_t *, size_t);
int   pthread_cancel(pthread_t);
void  pthread_cleanup_push(void*), void *);
void  pthread_cleanup_pop(int);
int   pthread_cond_broadcast(pthread_cond_t *);
int   pthread_cond_destroy(pthread_cond_t *);
int   pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
int   pthread_cond_signal(pthread_cond_t *);
int   pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
int   pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int   pthread_condattr_destroy(pthread_condattr_t *);
int   pthread_condattr_getpshared(const pthread_condattr_t *, int *);
int   pthread_condattr_init(pthread_condattr_t *);
int   pthread_condattr_setpshared(pthread_condattr_t *, int);
int   pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
int   pthread_detach(pthread_t);
int   pthread_equal(pthread_t, pthread_t);
void  pthread_exit(void *);
int   pthread_getconcurrency(void);
int   pthread_getschedparam(pthread_t, int *, struct sched_param *);
void *pthread_getspecific(pthread_key_t);
int   pthread_join(pthread_t, void **);
int   pthread_key_create(pthread_key_t *, void (*)(void *));
int   pthread_key_delete(pthread_key_t);
int   pthread_mutex_destroy(pthread_mutex_t *);
int   pthread_mutex_getprioceiling(const pthread_mutex_t *, int *);
int   pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int   pthread_mutex_lock(pthread_mutex_t *);
int   pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
int   pthread_mutex_trylock(pthread_mutex_t *);
int   pthread_mutex_unlock(pthread_mutex_t *);
int   pthread_mutexattr_destroy(pthread_mutexattr_t *);
int   pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *,int *);
int   pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
int   pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
int   pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
int   pthread_mutexattr_init(pthread_mutexattr_t *);
int   pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
int   pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
int   pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int   pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int   pthread_once(pthread_once_t *, void (*)(void));
int   pthread_rwlock_destroy(pthread_rwlock_t *);
int   pthread_rwlock_init(pthread_rwlock_t *,const pthread_rwlockattr_t *);
int   pthread_rwlock_rdlock(pthread_rwlock_t *);
int   pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int   pthread_rwlock_trywrlock(pthread_rwlock_t *);
int   pthread_rwlock_unlock(pthread_rwlock_t *);
int   pthread_rwlock_wrlock(pthread_rwlock_t *);
int   pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
int   pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *,int *);
int   pthread_rwlockattr_init(pthread_rwlockattr_t *);
int   pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);

pthread_t
      pthread_self(void);
int   pthread_setcancelstate(int, int *);
int   pthread_setcanceltype(int, int *);
int   pthread_setconcurrency(int);
int   pthread_setschedparam(pthread_t, int , const struct sched_param *);
int   pthread_setspecific(pthread_key_t, const void *);
void  pthread_testcancel(void);

<sched.h> scheduling (REALTIME) - 스레드 스케쥴링 관련 정의

int    sched_priority    process execution scheduling priority

SCHED_FIFO 	//First in-first out (FIFO) scheduling policy.
SCHED_RR 	//Round robin scheduling policy.
SCHED_OTHER //Another scheduling policy.


int    sched_get_priority_max(int);
int    sched_get_priority_min(int);
int    sched_getparam(pid_t, struct sched_param *);
int    sched_getscheduler(pid_t);
int    sched_rr_get_interval(pid_t, struct timespec *);
int    sched_setparam(pid_t, const struct sched_param *);
int    sched_setscheduler(pid_t, int, const struct sched_param *);
int    sched_yield(void);

 <time.h>-  time types 정의 tm structure 로 선언되어있음

int    tm_sec   seconds [0,61]
int    tm_min   minutes [0,59]
int    tm_hour  hour [0,23]
int    tm_mday  day of month [1,31]
int    tm_mon   month of year [0,11]
int    tm_year  years since 1900
int    tm_wday  day of week [0,6] (Sunday = 0)
int    tm_yday  day of year [0,365]
int    tm_isdst daylight savings flag

time_t  tv_sec    seconds
long    tv_nsec   nanoseconds

NULL //Null pointer constant.
CLK_TCK //Number of clock ticks per second returned by the times() function (LEGACY).
CLOCKS_PER_SEC //A number used to convert the value returned by the clock() function into seconds.

//timespec
time_t  tv_sec    seconds
long    tv_nsec   nanoseconds

//itimerspec
struct timespec  it_interval  timer period
struct timespec  it_value     timer expiration

CLOCK_REALTIME //The identifier of the systemwide realtime clock.
TIMER_ABSTIME //Flag indicating time is absolute with respect to the clock associated with a timer.

char      *asctime(const struct tm *);
char      *asctime_r(const struct tm *, char *);
clock_t    clock(void);
int        clock_getres(clockid_t, struct timespec *);
int        clock_gettime(clockid_t, struct timespec *);
int        clock_settime(clockid_t, const struct timespec *);
char      *ctime(const time_t *);
char      *ctime_r(const time_t *, char *);
double     difftime(time_t, time_t);
struct tm *getdate(const char *);
struct tm *gmtime(const time_t *);
struct tm *gmtime_r(const time_t *, struct tm *);
struct tm *localtime(const time_t *);
struct tm *localtime_r(const time_t *, struct tm *);
time_t     mktime(struct tm *);
int        nanosleep(const struct timespec *, struct timespec *);
size_t     strftime(char *, size_t, const char *, const struct tm *);
char      *strptime(const char *, const char *, struct tm *);
time_t     time(time_t *);
int        timer_create(clockid_t, struct sigevent *, timer_t *);
int        timer_delete(timer_t);
int        timer_gettime(timer_t, struct itimerspec *);
int        timer_getoverrun(timer_t);
int        timer_settime(timer_t, int, const struct itimerspec *, struct itimerspec *);
void       tzset(void);


extern int       daylight;
extern long int  timezone;
extern char     *tzname[];

thread function in c

더보기

#include <pthread.h>


스레드 생성시 사용하는 함수 
int pthread_create( pthread_t *restrict thread, const pthread_attr_t *restrict attr,
                    void* (*start_routine)(void*), void *restrict arg);                 
    --> return : 성공 시 0, 실패 시 0 이외의 값 반환

 

-pthread_t *thread : pthread_t 를 가리키는 포인터, 스레드 생성후 메모리에 스레드 식별자 기록.(ID 부여 )


-pthread_attr_r *attr : 스레드 특성을 가리키는 포인터, 일반적으로 NULL지정.

 

-void *(start_routine)(void *) : 스레드 실행시 실행하는 함수 .void를 가리키는 포인터를 받고 void를 가리키는 포인터를 돌려주는 함수의 주소 지정.


- void *arg : 스레드 함수에 넘겨지는 인자값.

 

스레드 종료시 사용하는 함수 

void pthread_exit(void *retval)

- 일반 프로세스를 종료할때, 사용하는 exit와 같은 역할을 하는 함수로 다중 스레드를 사용하는 중 생성된 스레드를 종료 할때 사용

- void *retval = 임의의 형식의 객체를 가리키는 포인터.

-retval에 스레드 함수의 지역변수를 가리키는 포인터를 사용 x
- 스레드가 종료되면 그 지역변수도 사라지기 때문에 버그 생성 발생 

 

3. int pthread_join(pthread_t th, void **thread_return);
- wait 함수와 같은 역할을 하는 함수로 생성된 스레드가 종료되기를 기다리는 함수.
-한개의 스레드가 다중 스레드가 되었다가 다시 합쳐진다는 의미.

-pthread_t th - 앞의 create에서 얻어진 식별자 값을 입력,  해당 thread를 대기.
     -> 해당 스레드의 반환값을 가리키는포인터.

-void **thread_return -   더블포인터는 스레드의 반환값을 가리키는 포인터.
pthread_exit에 의해 리턴된 값을 받는 역할을 한다.

-성공시 0을 리턴 실패시 오류코드 리턴.


더보기

프로세스 (주소영역 독립적으로 가짐)
1. fork() ; 새로운 프로세스 생성 시 5가지구성요소 가 복사됨. 
멀티 프로세서에서 사용하는 함수
5가지 구성요소 .
1. code, data, stack, file io , signal table 5가지 구성요소로 구성.
 자원 효율 성에서 문제점.-> 복사가 일어나고  자원관점에서 비용이 소비가 많음.
대게 프로세스를 새로 생성시킬때 발생하는 성능저하 문제.
웹서비스처럼 대량의 접근이 발생하는 영역에서 문제 발생.

2. thread (주소 영역 공유)
- 특정 문맥만 병렬로 실행 할 수 있도록 허용.
- 새로운 프로세스를 생성시키며 자원을 아낄수 있다.

 

1. Multi thread.

-  하나의 스레드에서 발생한 문제가 전체 프로세스에 영향을 미치게된다.

- 쓰레드 하나가 다른 프로세스의 메모리 영역을 침범할 경우 프로세스 자체가 죽어버림으로써,
 프로세스에 생성된 다른 모든 쓰레드도 프로세스와 함께 죽어버리게 된다.

- (시그널을 잘활용하면 문제 해결가능)

-pthread.
-리눅스 운영체제에서 제공하는 thread 를 제어하기 위한 함수들을 모아 놓은 C 라이브러리

1. 쓰레드 생성과 종료 관련 함수 
2. 쓰레드 동기화 관련 함수


-> 쓰레드-> 데이터 공유 -> 동기화 문제를 해결 할 필요 존재. -> 쓰레드 시그널 제어 함수



-thread 생성 (pthread_create() ) - thread- wait (pthread_join)

-pthread_join에서 문제 
1. 스레드가 종료할 때 까지 블럭되기 때문에 스레드를 두개이상 생성하지 못하는 문제가 발생한다. 
2. 또한 메모리 누수? 가 발생 .


-> solution.

1. 자식 쓰레드를 부모 쓰레드로 분리하기.

 pthread_detach를 이용 

-자식 스레드를 부모쓰레드와 완전히 분리하는 방법.
-자식 스레드가 종료되면 모든 자원이 즉시 반환.
-문제 1. 자식 스레드의 종료상태를 체크할수 없다.


-----------------------------------------↑↑↑↑↑↑ 다중 스레드 프로그램 . 
->>>> 스레드 동기화 ( 시간을 맞추는 의미)




1. 접근제어
다중쓰레드 프로그램에서 접근제어를 이용

; pthread는 mutex의 잠금 메커니즘을 제공

- Mutex 잠금..


동시에 여러개의 스레드가 하나의 자원에 접근하려고 할때 발생하는 문제를 pthread에서 임계영역으로 두는것으로 해결.

  임계영역
thread1---l----> ㅣ 임계영역 안에 접근하고자 하는 자원이 있음.
ㅣ 자원   ㅣ 하나의 스레드만 영역안으로 진입가능.
thread >  l ㅣ pthread에서는 mutex를 제공
wait  mutex는 자체가 가지는 잠금의특성으로 mutex잠금이라고 말함



----------
mutex의 사용 
mutex를 사용하기 위해서는 다음의 4가지 함수가 필요하다

mutex 잠금객체을 만드는 함수 
•mutex 잠금을 얻는 함수 
•mutex 잠금을 되돌려주는 함수 
•mutex 잠금객체를 제거하는 함수 



1. pthread mutex init function


mutex 사용시 pthread mutex init 함수로 mutex 객체 생성.

***************
pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr *attr);
***************
pthread함수는 두개의 인자를 필요로 한다.

1. mutex: mutex 잠금해제.

2. mutex_attr : mutex는 fast, 'recursive, error checking 3종류가 있다. 3종류의 값을 이용해서 mutex의 타입을 결정.
NULL일 경우 fast로 설정.

fast :  하나의 스레드가 하나의 잠금만을 얻을수 있는 일반적인 형태
 PTHREAD_MUTEX_INITIALIZER 
recursive : 잠금을 얻은 스레드가 다시 잠금을 얻을수 있고 잠금에 대한 카운트가 증가하는형태
PTHREAD_RECURSIVE_MUTEX_INITIALIZER 
error checking :
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 


2. pthread_mutex_lock
mutex 잠금을 얻기 위한 함수 - mutex 잠금을 요청한다라는 표현이 더 정확
******************
int pthread_mutex_lock(pthread_mu);
*******************

-만약 mutex 잠금을 선점한 쓰레드가 있다면, 선점한 쓰레드가 mutex 잠금을 되돌려주기 전까지 이 코드에서 대기

 잠금을 얻을 수 있는지만 체크하고 대기(블럭)되지 않은 상태로 다음 코드로 넘어가야할 필요가 있을 수 있을경우
-int pthread_mutex_trylock(pthread_mutex_t *mutex); 함수 사용.


3. pthread_mutex_unlock 
mutex 잠금을 되돌려주는 함수

-int pthread_mutex_unlock(pthread_mutex_t *mutex);



Thread issue

더보기

<1> fork() , exec()

<2> Signal Handling 

  • Signal 은 이벤트임 .
  • Signal 은 프로세스에 통해서 전송됨
  • Signal 은 사용자 레벨에서 정의되는 신호와 기본적으로 커널이 실행하는 신호가 존재함

<2.1> Synchronous & asynchronous

<3> Thread cancellation of target Thread

<4> Thread-local storage

<5> Scheduler Activations 

- process간 시간이 미묘하게 어긋나거나 잘못된 변수를 공유하는 경우 문제가 발생.


Singal Handling

더보기

특정 이벤트가 발생할때 신호를 보내서 알려주는것 

ctrl+c , ctrl+z 역시 인터럽트를 발생하여 이벤트 신호를 생성하는것 . 

 

man 7 signal 로 linux상의 시그널 확인가능 .

 

 


 

Code

/*미완성 코드 */
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>

/*
******************************
****** variable *************
*/
enum process_state
{
        STOP    = 0.
        NEW     = 1,
        RUN     = 2,
        WAIT    = 3,
        READY   = 4,
        EXIT    = 5,
        ABRNOMAL= 6,
        MAX     = 7
};

enum _return_value
{
        N_SUCCESS =1;
        N_FAILURE =-1;
}

typedef struct _pro_control_block
{
		pid_t pid;
        pthread_t pthread[2];
        int thd_id;
        int p_state;
}PCB;

/*
********************************
****process fucntion block******
********************************
*/
int init_pcb();
void signal_hdr(int);
int thread_function();
void *p_function(void *data)

/*
********************************
****global variable block*******
********************************
*/
PCB *pcb = NULL;

int main()
{

char p1[] = "th1";
char p2[] = "Th2";
char p3[] = "th3";

/*
* 1. make pcb
*/
        init_pcb();
		
        signal_hdr();
        
        thread_f(pcb)
        
}

int init_pcb()
{
        pcb = (PCB*)malloc(sizeof(PCB));
        memset((void*)pcb , 0x00 , sizeof(PCB));
        pcb->p_state = NEW;

        return N_SUCCESS;
}

int signal_hdr()
{
        signal(SIGHUP, SIG_IGN);
        signal(SIGPIPE, SIG_IGN);
        
}
int thread_f(PCB*pcb)
{
	pcb->thd_id = pthread_create(&(pcb->pthread[0]), NULL, p_function, (void *)p1);
    if(pcb->thd_id < 0)
    {
    	perror("pthread create error");
        exit();
     }
     pcb->thd_id = pthread_create(&(pcb->pthread[1]), NULL, p_function, (void *)p1);
     if(pcb->thd_id < 0)
     {
    	perror("pthread create error");
        exit();
     }
     
     p_function((void *)p3);
     
     pthread_join(pthread[0], (void **)&(pcb->p_state));
     pthread_join(pthread[1], (void **)&(pcb->p_state));
}
void *p_function(void *data)
{
	pid_t pid;
    pthread_t tid;
    pid = getpid();
    tid = pthread_self();
    
    char * thread_name= (char *)data;
    
    while(i<3)
    {
    	printf("thread name: %d , tid :%x. pid %u\n", thread_name, (unsigned int)tid, (unsigned int)pid);
        i++;
        sleep(1);
    }
}

 

반응형
LIST