임베디드 전체 중간고사 파일

권나영·2020년 10월 13일

임베디드 시스템

목록 보기
1/2

6. More Process Management

Creation, Suspension, Resumption, Termination 개념


1. Creation
text, data, bss, stack area 만들어짐 (initial context)
: process가 실행할 수 있는 환경 만들어 주는 것

  1. Suspension
    : 실행 불가능 상태

🤔 suspend 되는 경우 3가지?

  • Create하면 무조건 suspend!
  • Current가 본인을 suspend (어떤 event를 기다릴 때. 물론, I/O 시에는 Current가 I/O wait Q에 들어가지)
  • ready list에 있는 거 suspend

✔ resumption을 해줘야 풀림

  1. Resumption
    ready-list로 불러들여서 실행 가능한 상태로 만들어 주는 것

  2. Termination
    다 끝난 것
    현재 process가 차지하고 있는 resouce를 free시켜줌 (proc 엔트리 등등)

System Calls

user가 부를 수 있는 kernal function

  • suspend(currpid) 대신에, suspend(getpid())를 통해, 직접 currpid에 접근하기보다는, getpid()처럼 간접적으로 얻어서 사용

: information hiding! user가 복잡한 구조를 알 필요가 없다!

syscall function_name(args) {

intmask mask; /* 현재 인터럽트가 enable인지, disable인지 구분해 주는 bit */
mask = disable( ); /* 여러 개의 user가 하나의 kernal을 공유하므로, 한 user가 API 사용할거면, 이런식으로 인터럽트 diable을 걸어서, 자기가 다 사용한 다음에 다른 user에게 kernal 사용권을 넘겨줘야 = kernal protection */

/* 에러났어 */
if ( args are incorrect ) {
restore(mask); /* 인터럽트 어떤 상태인지 저장부터 */
return(SYSERR);
}

...other processing...

if ( an error occurs ) {
restore(mask);
return(SYSERR);
}
... more processing...

/* 마지막 */
restore(mask); /* return 하기 전에 인터럽트 어떤 상태인지 저장부터 */
return( appropriate value );
}

c 라이브러리 안의 TRAP이나 SWI등과 같은 machine instruction을 execution 할 때

  1. interrupt disable ➡ kernal mode로 바꿔줌
  2. kernal stack에 stack pointer, program counter을 저장해주고 exception entry point의 내가 원하는 function(machine instruction)의 address를 가져다가 program counter에 넣어주면, function이 execution 됨
  3. function의 마지막 줄인 return from exception에 도달하면 다시 main program으로 돌아옴 (즉, main문 코드 안에서 machine instruction (= function)의 바로 다음 줄 실행), return from exception하기 바로 전에서 꼭 interrupt enable해줘서 main아래 다른 instruction들도 실행 가능하도록 만들기!

syscall 안에서 resched가 일어나는 경우

ex) file read syscall()
어떤 block data를 가져오라고 명령하면 3ms 정도 걸림
➡ 자기 자신을 I/O wait Q 안에 집어 넣음
➡ 이 사이 쯤에서 만약 global data를 수정했다면, 수정한거는 다 끝내고 다음 step 밟기
➡ resched()
➡ 다른 process가 run

Creation

7. Coordination Of Concurrent Processes

Concurrent Process들이 global data structure를 수정할 때, 어떤 문제가 발생할 수 있을까?

🤞 1. 초기 n=0. prod2를 통해 n을 1로 증가시키고, cons2로 가서 n출력, prod2를 통해 n을 2로 증가시키고, 다시 cons2로 가서 n출력 ... 2000번 반복이 목적인 코드

#include <xinu.h>
void prod2(sid32, sid32), cons2(sid32, sid32);
int32 n = 0; /* n 0으로 전역에 설정 */

/*------------------------------------------------------------------------
* main -- producer and consumer processes synchronized with semaphores
*------------------------------------------------------------------------
*/
void main(void)
{
sid32 produced, consumed;
consumed = semcreate(0);
produced = semcreate(1);
/* create(process, stksize, priority, process이름, ...) */
resume( create(cons2, 1024, 20, "cons", 2, consumed, produced) ); /* 소비하는 process */
resume( create(prod2, 1024, 20, "prod", 2, consumed, produced) );
} /* 무언가를 생성하는 process */

/*------------------------------------------------------------------------
* prod2 -- increment n 2000 times, waiting for it to be consumed
*------------------------------------------------------------------------
*/
void prod2(
sid32 consumed,
sid32 produced
)
{
int32 i;
for( i=1 ; i<=2000 ; i++ ) {
wait(consumed);
n++;
signal(produced);
}
}
/*------------------------------------------------------------------------
* cons2 -- print n 2000 times, waiting for it to be produced
*------------------------------------------------------------------------
*/
void cons2(
sid32 consumed,
sid32 produced
)
{
int32 i;
for( i=1 ; i<=2000 ; i++ ) {
wait(produced);
printf("n is %d \n", n);
signal(consumed);
}
}

🤞 2. 100개 길이짜리 배열 만들어서 절반은 한 process담고, 절반은 다른 process담아서 순차적으로 process가 일어나게 만들자

  • critical section : global 변수를 수정하는 부분
void main(void){
		resume(create(additem, 1024, 20, "A", 1, 777));
        resume(create(additem, 1024, 20, "B", 1, 333));
}

#include <xinu.h>

sid32 mutex;
int32 shared[100]; /* an array shared by many processes */
int32 n = 0; /* count of items in the array */
/*------------------------------------------------------------------------
* additem -- obtain exclusive access to array ary and add an item to it
*------------------------------------------------------------------------
*/
void additem(
int32 item /* item to add to array ary */
)
{
wait(mutex);
shared[n++] = item;
signal(mutex);
}

wait/signal semaphore system calls를 통한 상태 변환

  • CS (critical section)에는 1개의 process만 실행 : wait, signal API이용
  1. wait : critical section에 process넣고 semaphore 닫아주는
  2. signal : semaphore 열어주는

세마포어 data 구조

🤞🤞 1. semaphore.h

  • semtab 안에 semaphore table entry 정의. 그 entry안에 3개의 필드가 있는 것(sstate, scount, squeue)
  • 새롭게 세마포어를 할당하고 싶다면, sstate가 S_FREE인 세마포어를 만들어주면 됨
#ifndef NSEM
#define NSEM 45 /* number of semaphores, if not defined */
#endif

/* Semaphore state definitions */
#define S_FREE 0 /* semaphore table entry is available */
#define S_USED 1 /* semaphore table entry is in use */

/* Semaphore table entry */
struct sentry {
byte sstate; /* 세마포어가 사용되고 있는지 아닌지 S_FREE or S_USED */
int32 scount; /* 😍차단기 역할. 현재 바로 critical section 사용 가능한 세마포어 개수😍 */
qid16 squeue; /* Q에서 기다리고 있는 process 개수 */
};

extern struct sentry semtab[];

/* s는 semtab안에 할당 되는 세마포어 id */
#define isbadsem(s) ((int32)(s) < 0 || (s) >= NSEM)

세마포어 System Calls

🤞🤞 1. wait

#include <xinu.h>

syscall wait(
sid32 sem /* semaphore on which to wait */
)
{
intmask mask;
struct procent *prptr; /* ptr to process’ table entry */
struct sentry *semptr; /* ptr to sempahore table entry */

mask = disable(); /* 인터럽트 disable (이 뒤부터 user가 사용하는 API라는 뜻) */
if (isbadsem(sem)) { /* 제대로 된 세마포어 num이 아닐 때 에러❗ */
restore(mask);
return SYSERR;
}

semptr = &semtab[sem];

if (semptr->sstate == S_FREE) { /* 아무도 사용하지 않는 세마포어일때 에러❗ */
restore(mask);
return SYSERR;
}

if (--(semptr->scount) < 0) { /* 😍scount는 기본적으로 1. 하나 줄였더니 0보다 작더라 = 원래 1보다 작았다 = 이미 critical section에 누가 들어와 있어서 바로 세마포어 사용 불가능하다😍 */
prptr = &proctab[currpid];
prptr->prstate = PR_WAIT; /* wait하도록 만들어줌 */
prptr->prsem = sem; /* semaphore ID 기록 */
enqueue(currpid,semptr->squeue);/* semaphore의 FIFO Q에 enqueue */
resched(); /* 😍reschedule - 반드시 콘텍스트 스위치 불러서 current가 outgoing context됨😍 */
}

restore(mask);
return OK;
}

🤞🤞 2. signal

#include <xinu.h>

syscall signal(
sid32 sem /* signal할 semaphore ID */
)
{
intmask mask;
struct sentry *semptr; /* ptr to sempahore table entry */

mask = disable(); /* 인터럽트 disable */

if (isbadsem(sem)) {	/* 제대로 된 세마포어 num이 아닐 때 에러❗ */
restore(mask);
return SYSERR;
}

semptr= &semtab[sem];

if (semptr->sstate == S_FREE) {	/* 아무도 사용하지 않는 세마포어일때 에러❗ */
restore(mask);
return SYSERR;
}

if ((semptr->scount++) < 0) { /* 우선 scount가 0보다 작다 */
ready(dequeue(semptr->squeue), RESCHED_YES);
}

restore(mask);
return OK;
}
profile
나영

0개의 댓글