• AI글쓰기 2.1 업데이트
BRONZE
BRONZE 등급의 판매자 자료
non-ai
판매자가 AI를 사용하지 않은 독창적인 자료

OS Message Passing 과제

OS 과제 중 하나인 Message Passing 구현입니다. - Linux 또는 Unix OS에서 source code를 빌드시키고 동작 - C컴파일러 설치 후 동작 필요
10 페이지
압축파일
최초등록일 2016.03.26 최종저작일 2012.05
OS Message Passing 과제
  • 미리보기

    소개

    OS 과제 중 하나인 Message Passing 구현입니다.
    - Linux 또는 Unix OS에서 source code를 빌드시키고 동작
    - C컴파일러 설치 후 동작 필요

    컴파일 실행환경

    Zip archive data

    본문내용

    /* File : schedule.c */

    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    #include <setjmp.h>
    #include <malloc.h>
    #include <memory.h>
    #include <sys/time.h>
    #include "schedule.h"

    // task switching시 저장되어야 하는 정보
    struct frame {
    unsigned long flags;
    unsigned long ebp;
    unsigned long edi;
    unsigned long esi;
    unsigned long edx;
    unsigned long ecx;
    unsigned long ebx;
    unsigned long eax;
    unsigned long retaddr;
    unsigned long retaddr2;
    unsigned long data;
    };

    typedef struct sch_handle_tag {
    int child_task;

    TaskInfo running_task;
    TaskInfo root_task;
    } SchHandle;

    TaskInfo readyQueue[3]; //multilevel feedback queue(큐의 header level만 저장)
    int level = 0; //현재 실행중인 level 저장
    int timequantum = 0; //timequantum 저장

    // global schedule handler
    SchHandle gh_sch;

    // task data struct
    TaskInfo task_get_runningtask();
    void task_insert(TaskInfo taskinfo);
    void task_delete(TaskInfo taskinfo);
    void task_next();
    void scheduler();
    void parent_task();

    void task_change(TaskInfo taskinfo); //다음 queue로 넘어가는 함수 선언

    /* thread_create : task를 생성하는 함수로 taskinfo 구조체를 할당하고 구성한다 */
    TaskInfo thread_create(TaskFunc callback, void *context) {
    TaskInfo taskinfo;
    // task를 위한 공간 할당
    taskinfo = malloc(sizeof(*taskinfo));
    memset(taskinfo, 0x00, sizeof(*taskinfo));

    {
    struct frame *f = (struct frame *) &taskinfo->stack[THREAD_STACKSIZE
    - sizeof(struct frame) / 4];
    // taskinfo로 할당된 공간 중 stack 부분 뒤쪽에 frame을 위한 공간으로 할당
    // 이에 task가 수행되면서 stack공간을 활용
    int i;
    for (i = 0; i < THREAD_STACKSIZE; ++i) { // stack overflow check
    taskinfo->stack[i] = i;
    }
    memset(f, 0, sizeof(struct frame));
    f->retaddr = (unsigned long) callback;
    f->retaddr2 = (unsigned long) thread_kill;
    f->data = (unsigned long) context;
    taskinfo->sp = (unsigned long) &f->flags;
    f->ebp = (unsigned long) &f->eax;
    }
    // task 생성에 따라 gh_sch에 child task가 늘었음을 표시
    gh_sch.child_task++;
    // gh_sch.child_task 값으로 task_id 할당
    taskinfo->task_id = gh_sch.child_task;
    // task 생성시 TASK_READY로 상태를 설정함
    taskinfo->status = TASK_READY;
    // taskinfo구조체들의 linkedlist에 새 thread의 taskinfo 구조체를 삽입
    task_insert(taskinfo);

    return taskinfo;
    }

    /* thread_init : 초기화 함수로 main함수가 처음에 호출하여, */
    /* global scheduler handeler를 초기화 하고 , parent_task를 생성한다 */
    void thread_init() {

    gh_sch.root_task = NULL;
    gh_sch.running_task = NULL;

    gh_sch.child_task = 0;

    thread_create(parent_task, NULL);
    }

    /* thread_switch : 수행중이던 task가 다른 대기중인 task에게 cpu사용을 양보하게 하는 함수로 ,
    현재 cpu레지스터의 값이 수행중이던 task의 stack부분에 차례차례 저장되게 되며 ,
    다음에 수행될 것으로 선택된 task의 taskinfo의 stack정보가 레지스터로 올려진다. */
    static unsigned long spsave, sptmp;
    void thread_switch() {
    asm("pushl %eax");
    asm("pushl %ebx");
    asm("pushl %ecx");
    asm("pushl %edx");
    asm("pushl %esi");
    asm("pushl %edi");
    asm("pushl %ebp");
    asm("pushl %ebp");
    asm("movl %%esp,%0":"=r"(spsave));

    gh_sch.running_task->sp = spsave;

    // 다음에 수행될 task를 선택하는 함수
    scheduler();
    sptmp = gh_sch.running_task->sp;

    asm("movl sptmp, %esp");
    asm("popl %ebp");
    asm("popl %ebp");
    asm("popl %edi");
    asm("popl %esi");
    asm("popl %edx");
    asm("popl %ecx");
    asm("popl %ebx");
    asm("popl %eax");
    }

    // 다음 수행될 task를 선택하는 함수
    void scheduler(void) {

    //현재 작업이 부모 thread이면 다음 작업으로 넘어간다.
    if (gh_sch.running_task->task_id == 1) {
    task_next();
    }
    //queue에서의 timequantum이 다 된 경우 다음 작업 수행
    if (timequantum == 8 || timequantum == 16) {
    timequantum = 1; //timequantum 초기화
    task_next(); //다음 작업 수행
    }
    //timequantum이 남은 경우 timequantum값 증가
    else {
    timequantum++;
    }

    TaskInfo task;
    // gh_sch의 running_task가 가르키고 있는 taskinfo 받음
    task = task_get_runningtask();

    switch (task->status) {
    // task상태가 TASK_RUN이나 TASK_SLEEP이면 선택됨
    case TASK_RUN:
    case TASK_SLEEP:
    break;
    // task상태가 TASK_KILL이면 delete하고 , swiching함수 다시 호출
    case TASK_KILL:
    task_delete(task);
    scheduler();
    break;
    // task상태가 TASK_YIELD이면 상태를 TASK_RUN으로 바꾸고 선택됨
    case TASK_YIELD:
    task->status = TASK_RUN;
    break;
    // task상태가 TASK_READY이면 상태를 TASK_RUN으로 바꾸고 선택됨
    case TASK_READY:
    task->status = TASK_RUN;
    break;
    }
    }

    void thread_wait(void) {
    parent_task(NULL);
    }

    // task상태를 TASK_KILL로 설정후 , thread_yield
    void thread_kill(void) {
    TaskInfo task;
    task = task_get_runningtask();
    task->status = TASK_KILL;
    thread_switch();
    }

    void thread_uninit(void) {
    return;
    }

    // child thread가 더이상 없을때까지 thread_switch
    void parent_task(void *context) {
    // signal 처리를 위한 정보를 위한 구조체
    struct sigaction act;
    sigset_t masksets;
    pid_t pid;

    // signal set 초기화
    sigemptyset(&masksets);
    // signal handler로 thread_switch() 등록
    act.sa_handler = (void*) thread_switch;
    act.sa_mask = masksets;
    act.sa_flags = SA_NODEFER;

    // signal 수신 때 취할 action 설정
    sigaction(SIGUSR1, &act, NULL);

    if ((pid = fork()) == 0) {
    while (1) {
    sleep(1);
    kill(getppid(), SIGUSR1);
    }
    } else {
    while (1) {
    // child_task가 1개 남았을 때, 즉 , parent_task만 남았을 때
    if (gh_sch.child_task <= 1) {
    kill(pid, SIGINT);
    break;
    }
    };
    }
    }

    // linkedlist에 새로운 taskinfo 삽입
    void task_insert(TaskInfo taskinfo) {
    //level 0에서 처음 작업을 수행할 경우 0번 queue에 작업을 저장한다.
    if (level == 0 && gh_sch.root_task == NULL) {
    readyQueue[level] = taskinfo;
    }

    if (gh_sch.root_task == NULL) {
    gh_sch.root_task = taskinfo;
    gh_sch.running_task = taskinfo;
    }

    else {
    TaskInfo temp;
    temp = gh_sch.root_task;

    while (temp->next != NULL) {
    temp = temp->next;
    }
    temp->next = taskinfo;
    taskinfo->prev = temp;
    }

    }

    //현재 작업중인 queue가 종료되고 다음 queue를 설정하는 함수
    void task_change(TaskInfo taskinfo) {
    //다음 실행시킬 queue가 비어 있으면 현재 작업중인 리스트를 다음 queue에 저장
    if (readyQueue[level + 1] == NULL) {
    readyQueue[level + 1] = readyQueue[level];
    }
    //queue가 비어있지 않으면 마지막 부분에 작업 저장
    else {
    TaskInfo temp = readyQueue[level + 1];
    while (temp->next != NULL) {
    temp = temp->next;
    }
    temp->next = taskinfo;
    }
    level++;

    //level이 2보다 커지지 않게 함.
    if (level > 2)
    level = 2;

    gh_sch.root_task = readyQueue[level];
    gh_sch.running_task = readyQueue[level]; //root와 running 저장

    printf("change the %d queue\n", level); //queue변경 알림
    }

    // linkedlist에서 gh_sch.running_task가 가르키고 있는 task리턴
    TaskInfo task_get_runningtask(void) {
    return gh_sch.running_task;
    }

    // linkedlist에서 gh_sch.running_task가 가르키고 있는 task의 다음 task리턴
    void task_next(void) {
    TaskInfo temp;
    temp = gh_sch.running_task;

    //부모 thread가 수행중이면 바로 다음 작업을 running task
    if (gh_sch.running_task->task_id == 1) {
    gh_sch.running_task = temp->next;
    }

    //next가 있을 경우 다음 작업을 running task로
    if (temp->next != NULL) {
    gh_sch.running_task = temp->next;
    }
    //다음 작업이 없고 2번 level queue가 아닐경우 다음 queue로 넘어간다.
    else {
    if(level!=2)
    task_change(gh_sch.root_task);
    }

    }

    // linkedlist에서 task를 지움
    void task_delete(TaskInfo taskinfo) {
    TaskInfo temp = taskinfo->prev;
    if (gh_sch.root_task == taskinfo) {
    gh_sch.root_task = NULL;
    gh_sch.running_task = NULL;
    gh_sch.child_task = 0;
    }

    else {
    temp->next = taskinfo->next;

    if (taskinfo == gh_sch.running_task) {
    if (temp->next != NULL) {
    (taskinfo->next)->prev = temp;
    gh_sch.running_task = temp->next;
    } else
    gh_sch.running_task = temp;
    }
    gh_sch.child_task--;
    }
    free(taskinfo);

    }

    참고자료

    · 없음
  • 자료후기

      Ai 리뷰
      지식판매자가 등록한 자료는 내용이 풍부하고 깊이 있는 분석이 돋보입니다. 과제에 바로 활용할 수 있는 내용이 많아 매우 만족합니다. 감사드립니다.
    • 자주묻는질문의 답변을 확인해 주세요

      해피캠퍼스 FAQ 더보기

      꼭 알아주세요

      • 자료의 정보 및 내용의 진실성에 대하여 해피캠퍼스는 보증하지 않으며, 해당 정보 및 게시물 저작권과 기타 법적 책임은 자료 등록자에게 있습니다.
        자료 및 게시물 내용의 불법적 이용, 무단 전재∙배포는 금지되어 있습니다.
        저작권침해, 명예훼손 등 분쟁 요소 발견 시 고객센터의 저작권침해 신고센터를 이용해 주시기 바랍니다.
      • 해피캠퍼스는 구매자와 판매자 모두가 만족하는 서비스가 되도록 노력하고 있으며, 아래의 4가지 자료환불 조건을 꼭 확인해주시기 바랍니다.
        파일오류 중복자료 저작권 없음 설명과 실제 내용 불일치
        파일의 다운로드가 제대로 되지 않거나 파일형식에 맞는 프로그램으로 정상 작동하지 않는 경우 다른 자료와 70% 이상 내용이 일치하는 경우 (중복임을 확인할 수 있는 근거 필요함) 인터넷의 다른 사이트, 연구기관, 학교, 서적 등의 자료를 도용한 경우 자료의 설명과 실제 자료의 내용이 일치하지 않는 경우

    찾으시던 자료가 아닌가요?

    지금 보는 자료와 연관되어 있어요!
    왼쪽 화살표
    오른쪽 화살표
    문서 초안을 생성해주는 EasyAI
    안녕하세요 해피캠퍼스의 20년의 운영 노하우를 이용하여 당신만의 초안을 만들어주는 EasyAI 입니다.
    저는 아래와 같이 작업을 도와드립니다.
    - 주제만 입력하면 AI가 방대한 정보를 재가공하여, 최적의 목차와 내용을 자동으로 만들어 드립니다.
    - 장문의 콘텐츠를 쉽고 빠르게 작성해 드립니다.
    - 스토어에서 무료 이용권를 계정별로 1회 발급 받을 수 있습니다. 지금 바로 체험해 보세요!
    이런 주제들을 입력해 보세요.
    - 유아에게 적합한 문학작품의 기준과 특성
    - 한국인의 가치관 중에서 정신적 가치관을 이루는 것들을 문화적 문법으로 정리하고, 현대한국사회에서 일어나는 사건과 사고를 비교하여 자신의 의견으로 기술하세요
    - 작별인사 독후감
    해캠 AI 챗봇과 대화하기
    챗봇으로 간편하게 상담해보세요.
    2025년 12월 29일 월요일
    AI 챗봇
    안녕하세요. 해피캠퍼스 AI 챗봇입니다. 무엇이 궁금하신가요?
    1:30 오후