Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- doupdate
- packet flow
- rfc5508
- BOF
- epoll_wait
- REDIS
- .net core 7
- cbpf
- 풀이
- C언어
- LOB
- DOCKER-USER
- Compiler
- edge trigger
- wrefresh
- ncurses
- Docker
- ioctl
- wnourefresh
- epoll
- mvwin
- .nret core 배포
- iptables
- 취약점
- vtable
- packet filter
- architecture
- 어셈블리어
- level trigger
- NAPT
Archives
- Today
- Total
Tuuna Computer Science
[ 공유 메모리 ] 본문
[ 공유 메모리 ]
프로세스에서 사용되는 메모리 영역은 해당 프로세스만이 사용할 수 있다.
즉, 자신만의 메모리 영역을 의미한다. -> 커널에 요청한 프로세스만이 접근할 수 있다.
하지만 여러개의 프로세스가 특정 메모리 영역을 사용했으면 하는 때가 있다.
이를 공유 메모리라고 한다.
공유 메모리는 IPC중에서 가장 빠른 수행속도를 기록한다.
이 때 한번에 하나의 프로세스만이 메모[리에 접근가능을 보장해야 한다.
IPC : 프로세스간의 통신
[ 공유 메모리관련 함수 ]
#include <sys/types.h>
#include >sys/shm.h>
int shmget (key_t key, int size, int shmflg)
void* shmat (int shmid, const void* shmaddr, int shmflg)
int shmdt (const void* shmaddr)
int shmctl (int shmid, int cmd, struct shmid_ds * buf)
공유 메모리의 생성요청은 최초 공유메모리 영역을 만드는 프로세스가 커널에게 요청함으로써 이루어 지기때문에 커널에 의해 관리하게 된다.
운영체제를 리부팅하거나, 직접 공유메모리 공간을 삭제하지 않는한 계속유지하게 된다.
이러한 공유메모리공간은 shmid_ds구조체에 의해 관리된다.
헤더파일 : "shm.h"
struct shmid_ds
{
struct ipc_perm shm_perm; //퍼미션(접근 권한)
int shm_segez; //메모리 공간의 크기
time_t shm_atime; //마지막 attact 시간
time_t shm_dtime; //마지막 detach 시간
time_t shm_ctime; //마지막 변경 시간
unsigned short shm_cpid; //생성프로세스의 pid
unsigned short shm_lpid; //마지막으로 작동한 프로세스의 pid
short shm_nattch; //현재 접근한 프로세스의 수
};
현재 접근중인 프로세스의 수 :: 공유메모리에 접근을 하기 위해서는 고유의 공유메모리 key를 통해서 접근가능해진다. 이 key값을 통해 다른 공유메모리들과 구분됨.
[ shmget ]
:: 커널에 공유메모리 공간을 요청하기 위해 호출하는 시스템 호출 함수
int shmget (key_t key, int size, int shmflg)
->key_t key :: 고유의 공유메모리임을 알려주기 위해 사용
shmget함수를 통해 새로운 공유메모리를 생성 or 참조
->int size :: 공유메모리의 크기
->int shmflg :: 공유메모리의 접근 권한, 생성방식
IPC_CREAT : key를 이용하여 새로운 공유메모리 생성
IPC_EXCL : 공간이 이미 있을 시 error 반환
===========================
int shmid;
key_t keyval;
keyval = 1234;
shmid = shmget(keyval, 1024, IPC_CREAT | 0666)); //권한 설정 0666 : 파일의 기본 권한
if (shmid == -1)
{
return -1;
}
============================
[ shmat ]
:: 생성 후 공유메모리에 접근할 수 있는 int형의 "식별자" 얻게 됨.
shmat를 이용해서 이용하고자 하는 프로세스가 공유메모리를 사용가능하도록 "덧붙임"작업을 해주어야 한다
void* shmat (int shmid, const void* shmaddr, int shmflg)
-> int shmid : shmget를 이용해서 얻어낸 식별자 번호
-> const void* shmaddr : 메모리가 붙을 주소를 명시
0을 사용시 커널이 메모리가 붙을 주소 명시
-> int shmflg : 프로세스가 해당 공유메모리에 대한 "읽기 전용", "읽기/쓰기" 모드로 열 수 있다.
SHM_RDONLY : 읽기 전용
아무값도 지정 X : 읽기/쓰기 가능
[ shmdt ]
int shmdt (const void* shmaddr)
:: 프로세스가 더 이상 공유메모리를 사용할 필요가 없을 경우 프로세스와 공유메모리를 분리 하기 위해서 사용
but : 공유메모리의 내용은 그대로 남는당!
shmdt가 성공적으로 수행되면 커널은 shmid_ds의 내용을 갱신
즉, shm_dtime, shm_lpid, shm_nattch등의 내용 갱신
shm_mattch 의 값이 1씩 감소하며 0이 되면 프로세스가 X
[ shmctl ]
:: 공유 메모리 제어
int shmctl (int shmid, int cmd, struct shmid_ds *buf)
-> int cmd : 공유 메모리 제어
- IPC_STAT :: 공유메모리 공간에 관한 정보를 가져오기 위해 사용 정보는 buf에 저장
- IPC_SET :: 공유메모리 공간에 대한 사용자권한 변경을 위해 사용
- IPC_RMID :: 공유메모리 공간을 삭제하기 위해서 사용, shm_nattch가 0이 될때까지 기다렸다가 삭제
[ 공유 메모리 제어 ]
ipcs -l :: 자원의 제한 정보
ipcs -m : 현재사용중인 ipc 자원 정보
/proc/sys/kernel/shmmax : 프로세스가 생성할 수 있는 공유 메모리의 최대 크기
/proc/sys/kernel/shmall : 현재 사용중인 메모리의 크기
ex) echo 536870912 > /proc/sys/kernel/shmmax
//attach 후에 fork를 호출하니 shmget이나 shmat가 필요하지 않다!
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int shmid;
int pid;
int *cal_num;
void *shared_memory = (void *)0; //void형으로 선언
// 공유메모리 공간을 만든다.
shmid = shmget((key_t)1234, sizeof(int), 0666 | IPC_CREAT); //shmid를 반환한다
/*
int shmget (key_t key, int size, int shmflg)
shmget : 공유메모리 생성 함수
-> 1_par : key 값
-> 2_par : 크기
-> 3_par : 파일 기본 권한 | IPC_CREAT : 공유메모리 생성
return : 실패시 -1
*/
if (shmid == -1)
{
perror("shmget failed : ");
exit(0);
}
// 프로세스메모리를 공유메모리영역에 붙인다.
shared_memory = shmat(shmid, (void *)0, 0);
//shmget에서 shmflg은 복합적인 플래그로 처리되는데 0은 errorno값이 EINVAL로 리턴됩니다.
/*
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmat : 프로세스가 공유메모리를 사용할 수 있게 덧붙임
-> 1_par : 식별자번호
-> 2_par : 메모리가 붙을 주소 : 0 -> kernel이 지정
-> 3_par : SHM_RDONLY : 읽기만 || 0 : 읽기 or 쓰기
return : 실패시 -1 but 성공시 shared memory segment
*/
if (shared_memory == (void *)-1)
{
perror("shmat failed : ");
exit(0);
}
cal_num = (int *)shared_memory;
//처음 선언시 void형이였으므로 int*형으로 캐스팅함 추론 : 단지 공유메모리의 주소를 줌
pid = fork();
//자식 프로세서 생성 || 생성시 공유메모리는 자식 프로세스에게 상속된다.
//그렇기에 attach후 자식프로세스 생성 후 shmget을 할필요가 없다
if (pid == 0) //성공시
{
shmid = shmget((key_t)1234, sizeof(int), 0);
//이건 그냥 한 번더 선언함. 안해도 됨. www.joinc.com예제에선 했길래
if (shmid == -1) //shmget 실패시
{
perror("shmget failed : ");
exit(0);
}
shared_memory = shmat(shmid, (void *)0, 0666 | IPC_CREAT);
//shmat에서도 0666 | IPC_CREAT -> 권한?
if (shared_memory == (void *)-1) //shmat 실패시
{
perror("shmat failed : ");
exit(0);
}
cal_num = (int *)shared_memory; //이건 공유메모리의 주소를 넘겨주기위해성
*cal_num = 1; //주소를 넘겨받는 느낌인가 공유메모리의 주소?
while (1)
{
*cal_num = *cal_num + 1; //공유메모리의 주소에 저장된 값 연산 즉, 참조
printf("child %d\n", *cal_num);
sleep(1);
}
}
// 부모 프로세스로 공유메모리의 내용을 보여준다.
// 이미 상속받은 세그먼트를 한 번 더 attach하니까
//ipcs 상에 nattach가 3으로 나타나는 것으로 판단된다
else if (pid > 0) //pid가 양수이면 부모 프로세서 자식 프로세서의 반환값이 양수
{
while (1)
{
sleep(1);
printf("%d\n", *cal_num);
}
}
}
1.Manual에 따르면 fork시에 attach된 shared memory segment는 child 프로세스에 상속됩니다.
예제 코드는 attach 후에 fork를 호출하니 shmget이나 shmat가 필요하지 않습니다.
2.이미 상속받은 세그먼트를 한 번 더 attach하니까 ipcs 상에 nattach가 3으로 나타나는 것으로 판단됩니다.
3.shmget에서 shmflg은 복합적인 플래그로 처리되는데 0은 errorno값이 EINVAL로 리턴됩니다.
교수님한테 따로 물어본건데 암튼 그렇다넹 의문점 해결!
'System programing' 카테고리의 다른 글
리눅스 메모리에 대해 (0) | 2018.08.10 |
---|---|
system call (0) | 2018.06.11 |
[ 좀비 프로세스 ] (0) | 2018.06.09 |
[리눅스] 프로세스에 대해서 (0) | 2018.06.09 |
Comments