26
Linux System Linux System Programming Programming Lecture #11 – 공공공공공 (Shared Memory)

Linux System Programming

  • Upload
    clara

  • View
    69

  • Download
    2

Embed Size (px)

DESCRIPTION

Linux System Programming. Lecture #11 – 공유메모리 (Shared Memory). 공유메모리 (Shared Memory) (1). 공유메모리 정의 : 두 개이상의 프로세스가 실제 메모리의 일부를 공유하여 통신할 수 있는 IPC 도구 통신하려는 프로세스는 우선 공유 메모리를 할당받는다 프로세스는 할당된 공유 메모리를 자신의 가상주소공간 일부에 붙여 (attach) 메모리에 데이터를 읽고 쓰는 것가 동일한 방법으로 필요한 데이터를 읽거나 전송하려는 데이터를 기록하여 상호 통신한다 - PowerPoint PPT Presentation

Citation preview

Page 1: Linux System Programming

Linux System Linux System ProgrammingProgramming

Lecture #11 – 공유메모리 (Shared Memory)

Page 2: Linux System Programming

Linux System Programming 2

공유메모리 (Shared Memory) (1)공유메모리 (Shared Memory) (1)

공유메모리 정의 : 두 개이상의 프로세스가 실제 메모리의 일부를 공유하여 통신할

수 있는 IPC 도구 통신하려는 프로세스는 우선 공유 메모리를 할당받는다 프로세스는 할당된 공유 메모리를 자신의 가상주소공간 일부에 붙여(attach) 메모리에 데이터를 읽고 쓰는 것가 동일한 방법으로 필요한 데이터를 읽거나 전송하려는 데이터를 기록하여 상호 통신한다

프로세스간의 통신이 종료되면 공유 메모리를 가상주소공간에서 떼어내고 (detach) 공유 메모리를 해제한다

IPC 도구 중에서 가장 효율적 시스템 간의 이식성이 낮음

프로세스간의 메모리 공유를 위해 별도의 하드웨어 지원이 필요 공유 메모리를 사용한 프로그램을 하드웨어 지원이 없는 시스템에서는 사용불가

Page 3: Linux System Programming

Linux System Programming 3

공유메모리 (Shared Memory) (2)공유메모리 (Shared Memory) (2)

공유 메모리 시스템 호출 : shmget – 공유 메모리를 새롭게 할당하거나 할당된 공유

메모리의 핸들을 반환한다 shmctl – 공유 메모리와 관련된 상태 변수값을 변경하거나 공유

메모리를 제거한다 shmat – 공유 메모리를 프로세스의 가상주소공간에 논리적으로

부착 (attach) 한다 shmdt – 프로세스의 가상주소공간으로부터 공유 메모리를

분리한다

Page 4: Linux System Programming

Linux System Programming 4

공유메모리 (Shared Memory) (3)공유메모리 (Shared Memory) (3)

공유 메모리 시스템 호출 :

프로세스 P2프로세스 P1

가상주소 :10000

shmat()

shmdt()가상주소 :20000

shmat()

shmdt()

공유메모리

shmget()

shmctl()

Page 5: Linux System Programming

Linux System Programming 5

공유메모리 (Shared Memory) (4)공유메모리 (Shared Memory) (4)

공유 메모리의 생성 : shmget()

Page 6: Linux System Programming

Linux System Programming 6

공유메모리 (Shared Memory) (5)공유메모리 (Shared Memory) (5)

공유 메모리의 생성 : shmget() 공유 메모리 구조체

Page 7: Linux System Programming

Linux System Programming 7

공유메모리 (Shared Memory) (6)공유메모리 (Shared Memory) (6)

공유 메모리의 생성 : shmget() 공유 메모리 구조체의 초기화

Page 8: Linux System Programming

Linux System Programming 8

공유메모리 (Shared Memory) (7)공유메모리 (Shared Memory) (7)

공유 메모리의 제어 : shmctl()

Page 9: Linux System Programming

Linux System Programming 9

공유메모리 (Shared Memory) (8)공유메모리 (Shared Memory) (8)

공유 메모리의 제어 : shmctl() shmctl 시스템 호출의 명령어

Page 10: Linux System Programming

Linux System Programming 10

공유메모리 (Shared Memory) (9)공유메모리 (Shared Memory) (9)

공유 메모리의 연산 : shmat()/shmdt()

Page 11: Linux System Programming

Linux System Programming 11

예제 프로그램 (1)예제 프로그램 (1)

예제 11-1 학원 강좌 예약 시스템 프로그램 부모 프로세스는 강좌 예약 정보를 갖는 공유 메모리을

할당하고 , 공유 메모리에 대한 상호배제를 위한 세마포어를 생성한다

자식 프로세스을 생성하여 강좌 예약을 수행하는데 , 자식 프로세스는 주기적으로 강좌 예약을 수행하도록 시뮬레이션하며 , 더 이상 예약할 좌석 (seat) 가 없으면 종료한다

부모 프로세스는 모든 자식 프로세스가 종료할 때까지 기다렸다가 세마포어와 공유 메모리를 제거하고 종료한다

Page 12: Linux System Programming

Linux System Programming 12

예제 프로그램 (2)예제 프로그램 (2) // // file name: ex11-1.h //

struct CLASS {char class_number[6];char date[6];char title[50];int seats_left;

} typedef struct CLASS class_t;

Page 13: Linux System Programming

Linux System Programming 13

예제 프로그램 (3)예제 프로그램 (3)

// file name: ex11-1a.c//#include <stdio.h>#include <memory.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include "ex11-1.h"

class_t class = { "1001", "120186", "C Language for Programmers", 15 };

#define NCHILD 3int child[NCHILD];

char *shm_ptr, *shmat();int semid, shmid;char ascsemid[10], ascshmid[10];char pname[14];void rpterror();

int main(int argc, char *argv[]){

int i;

Page 14: Linux System Programming

Linux System Programming 14

예제 프로그램 (4)예제 프로그램 (4)

strcpy(pname, argv[0]);shm_init(); sem_init();for(i=0; i < NCHILD; i++) { child[i] = fork(); switch(child[i]) { case -1: rpterror("fork-failure");

exit(1); case 0: sprintf(pname,"ex11-1b%d",i+1);

execl("ex11-1b", pname, ascshmid, ascsemid, (char *) 0); perror("execl faild"); exit(2);

}}wait_and_wrap_up();

}

shm_init(){

shmid=shmget(IPC_PRIVATE, sizeof(class), 0600|IPC_CREAT);if(shmid == -1) {

perror("shmget failed"); exit(3);}shm_ptr = shmat(shmid, (char *) 0, 0);if(shm_ptr == (char *) -1) {

perror("shmat failed"); exit(4);}memcpy(shm_ptr,(char *) &class, sizeof(class));sprintf(ascshmid,"%d", shmid);

}

Page 15: Linux System Programming

Linux System Programming 15

예제 프로그램 (5)예제 프로그램 (5)

sem_init() {if((semid=semget(IPC_PRIVATE, 1, 0600| IPC_CREAT)) == -1) {

perror("semget failed"); exit(5);}if((semctl(semid, 0, SETVAL,1)) == -1) {

printf("parent: semctl, SETVAL failed\n"); exit(6);}sprintf(ascsemid,"%d",semid);

}

wait_and_wrap_up() {int wait_rtn, w, ch_active = NCHILD;while(ch_active > 0) { wait_rtn = wait((int *) 0); for(w=0; w < NCHILD; w++)

if(child[w] == wait_rtn) {ch_active--;break;

}}printf("Parent removing shm and sem\n");shmdt(shm_ptr);shmctl(shmid, IPC_RMID);semctl(semid, 0, IPC_RMID, 0);exit(0);

}

Page 16: Linux System Programming

Linux System Programming 16

예제 프로그램 (6)예제 프로그램 (6)

void rpterror(string)char *string;{

char errline[50];sprintf(errline,"%s %s",string, pname);perror(errline);

}

Page 17: Linux System Programming

Linux System Programming 17

예제 프로그램 (7)예제 프로그램 (7)

// file name: ex11-1b.c//#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#include "ex11-1.h"

class_t *class_ptr;char *memptr, *shmat(), *pname;int semid, shmid, ret;struct sembuf lock = { 0, -1, 0};struct sembuf unlock = { 0, 1, 0};void rpterror();

int main(int argc, char *argv[]){

if(argc < 3) {fprintf(stderr, "Usage: %s shmid semid\n", argv[0]);exit(1);

}pname = argv[0];sscanf(argv[1],"%d", &shmid);memptr = shmat(shmid, (char *) 0, 0);

Page 18: Linux System Programming

Linux System Programming 18

예제 프로그램 (8)예제 프로그램 (8)

if(memptr == (char *) -1) {rpterror("shmat failed");exit(2);

}class_ptr = (class_t *) memptr;sscanf(argv[2], "%d", &semid);

sell_seats();

ret = shmdt(memptr);exit(0);

}

sell_seats() {int all_out = 0;srand((unsigned) getpid());while(! all_out) { /* loop to sell all seats */

if(semop(semid, &lock, 1) == -1) {rpterror("semop lock failed");exit(4);

}if(class_ptr -> seats_left > 0) {

class_ptr -> seats_left--;printf("%s SOLD SEAT -- %2d left\n", pname,

class_ptr->seats_left);}

Page 19: Linux System Programming

Linux System Programming 19

예제 프로그램 (9)예제 프로그램 (9)

else {all_out++;printf("%s sees no seats left\n", pname);

}ret = semop(semid, &unlock, 1);if(ret ==-1) {

rpterror("semop unlock failed");exit(4);

}sleep((unsigned) rand() %10 +1);

}}

void rpterror(string)char *string;{

char errline[50];sprintf(errline,"%s %s",string, pname);perror(errline);

}

Page 20: Linux System Programming

Linux System Programming 20

예제 프로그램 (10)예제 프로그램 (10)

예제 11-2 세마포어와 공유 메모리를 이용하여 버퍼의 자료를 생산하고

소비하는 생산자 /소비자 (producer/consumer) 프로그램 생산자는 공유 메모리를 할당하여 버퍼를 설정한다 생산자와 소비자 사이에 버퍼 접근을 위한 동기화를 위해 2

개의 세마포어를 생성하여 사용한다 버퍼 쓰기 동기화 (consumed 동기화 ) - 생산자는 소비자가 버퍼의 자료를 읽고 간 후에 새로운 자료를 버퍼에 쓴다

버퍼 읽기 동기화 (produced 동기화 ) - 소비자는 생산자가 버퍼에 새로운 자료를 쓴 후에 자료를 읽어간다

Page 21: Linux System Programming

Linux System Programming 21

예제 프로그램 (11)예제 프로그램 (11)

// file name: ex11-2a.c///* producer program: producer program sets up a buffer to be read by a consumer. semaphore are used to ensure taht producer dosen't overwrite an unread buffer and consumer dosen't read the same data more than once.*/

#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>

#define MSG_SIZE 30#define MAX 5

main(){ char *getenv(); key_t ftok(); char *shmat(); key_t key; void perror(), exit();

Page 22: Linux System Programming

Linux System Programming 22

예제 프로그램 (12)예제 프로그램 (12)

/* two semaphores in a set index 0 - incremented when producer has reset buffer - tested and decremented by consumer to check if buffer has been reset index 1 - incremented when consumer has read buffer - tested and decremented by producer to check if consumer is done.*/

static struct sembuf wait_consumed = { 1, -1, 0}; static struct sembuf signal_produced = { 0, 1, 0}; int semid, shmid; char *message; int i;

if((key = ftok(getenv("HOME"), 'u')) == (key_t) -1) { fprintf(stderr,"ftok key formation error\n"); exit(1); }

semid = semget(key, 2, IPC_CREAT | 0660); if(semid == -1) { perror("producer semget():"); exit(2); }

Page 23: Linux System Programming

Linux System Programming 23

예제 프로그램 (13)예제 프로그램 (13)

shmid = shmget(key, MSG_SIZE, IPC_CREAT | 0660); if(semid == -1) { perror("producer shmget():"); exit(3); }

message = shmat(shmid, (char *) 0, 0);

for(i=1; i < MAX; i++) { /* producer has to go first */ if(i>1) semop(semid, &wait_consumed, 1); sprintf(message, "message %d", i); semop(semid, &signal_produced, 1); } shmdt(message);

sleep(5); /* allow consumer to digest last message */

/* alternatively a DELIMITER string could be placed in shared memory when seen by the consumer, it would exit. the producer would do shmctl (..., IPC_STAT, ....) and when shm_attach == 1, it would remove the two IPC facilities */

shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0); shmctl(shmid, 0, IPC_RMID);}

Page 24: Linux System Programming

Linux System Programming 24

예제 프로그램 (14)예제 프로그램 (14)

// file name: ex11-2b.c///* consumer program: producer program sets up a buffer to be read by a consumer. semaphore are used to ensure taht producer dosen't overwrite an unread buffer and consumer dosen't read the same data more than once.*/

#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#define MSG_SIZE 30

int main(int argc, char *argv[]){/* two semaphores in a set index 0 - incremented when producer has reset buffer - tested and decremented by consumer to check if buffer has been reset index 1 - incremented when consumer has read buffer - tested and decremented by producer to check if consumer is done.*/

Page 25: Linux System Programming

Linux System Programming 25

예제 프로그램 (15)예제 프로그램 (15)

key_t key; static struct sembuf wait_produced = { 0, -1, 0}; static struct sembuf signal_consumed = { 1, 1, 0}; int semid, shmid; char *message; int rtn;

if((key = ftok(getenv("HOME"), 'u')) == (key_t) -1) { fprintf(stderr,"ftok key formation error\n"); exit(1); }

/* either producer or consumer might be the creator but producer will be the remover of IPC resources. producer and consumer's effective uid must be the same. */

semid = semget(key, 2, IPC_CREAT | 0660); if(semid == -1) { perror("producer semget():"); exit(2); }

Page 26: Linux System Programming

Linux System Programming 26

예제 프로그램 (16)예제 프로그램 (16)

shmid = shmget(key, MSG_SIZE, IPC_CREAT | 0660); if(semid == -1) { perror("producer shmget():"); exit(3); } message = shmat(shmid, (char *) 0, SHM_RDONLY);

while(1) { rtn = semop(semid, &wait_produced, 1); /* when producer is done semid will be IPC_RMID forcing break */ if(rtn == -1) { perror("consumer - semop on wait_consumed"); break; } printf("%s recevied: %s\n", argv[0], message); semop(semid, &signal_consumed, 1); } shmdt(message);}