memory & data management. linux system programming contents 동적 메모리 관리 memory...
TRANSCRIPT
Memory & DataManagement
Linux System Programming
Contents
동적 메모리 관리 Memory Allocation Memory De-allocation
파일 잠금 협조형 잠금 공유파일 구역 잠금 교착상태 (deadlock) 회피하기
Kongju national University
Linux System Programming
1. Memory Management in C
C 언어 에서 main memory 할당하기 특정 물리적인 주기억 공간을 직접 할당하지
않음 각 프로세스는 할당된 data 영역의 기억공간을
사용 구조체 (struct) 로 선언된 데이터는 memory
할당을 한 뒤 사용해야 함 최대 할당 크기는 4GB, 32bit pointer 사용 Flat 32 bit memory Model
Kongju national University
Linux System Programming
malloc()
#include <stdlib.h>
void *malloc(size_t size);
- size_t : unsigned int
- 결과는 pointer 로 반환 한다
- 메모리 할당은 커널 (kernel) 에서 담당
- 물리적 메모리 한계를 넘는 요구시 , swap 공간 (swap space) 를 사용
- Unix 에서 swapping 은 4096 bytes page 단위로 동작
- virtual memory management 의 Paging 기법
- 최대 할당할 수 있는 크기는 주기억공간 + swap 공간 보다 작다
- malloc() 의 size 를 넘어서는 메모리 사용시 error(segmentation fault !)
Kongju national University
Linux System Programming
malloc() : 간단한 메모리 할당
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define A_MEGABYTE (1024 * 1024)
main() {
char *some_memory;
int megabyte = A_MEGABYTE;
some_memory = (char *)malloc(megabyte);
if (some_memory != NULL) {
sprintf(some_memory, "Hello World\n");
printf("%s", some_memory);
}
}
Kongju national University
Linux System Programming
malloc() 관련 reference codes
memory1.c : 간단한 memory allocation memory2.c : 모든 physical memory
allocation memory3.c : 최대 할당 가능한 memory
크기 시험 ( 동시에 여러 프로세스가 동작 때 이상 발생 )
memory4.c : memory 한번 남용해 보기
Kongju national University
Linux System Programming
memory1.c 간단한 메모리 할당
#include <unistd.h>#include <stdlib.h>#include <stdio.h>
#define A_MEGABYTE (1024 * 1024)
main() { char *some_memory; int megabyte = A_MEGABYTE; some_memory = (char *)malloc(megabyte); if (some_memory != NULL) { sprintf(some_memory, "Hello World\n"); printf("%s", some_memory); } }
Kongju national University
Kongju national University
Linux System Programming
memory2.c 모든 물리 메모리 할당
#include <unistd.h>#include <stdlib.h>#include <stdio.h>
#define A_MEGABYTE (1024 * 1024)
main() { char *some_memory; size_t size_to_allocate = A_MEGABYTE; int megs_obtained = 0;
while (megs_obtained < 2048) { some_memory = (char *)malloc(size_to_allocate); if (some_memory != NULL) { megs_obtained++; sprintf(some_memory, "Hello World"); printf("%s - now allocated %d Megabytes\n", some_memory, megs_obtained); } else { printf(“\n Memory allocation failure\n”); } }}
Kongju national University
Linux System Programming
memory3.c 유효한 메모리 크기 측정
#include <unistd.h> #include <stdlib.h> #include <stdio.h>
#define ONE_K (1024)
main() { char *some_memory; int size_to_allocate = ONE_K; int megs_obtained = 0; int ks_obtained = 0;
while (1) { for (ks_obtained = 0; ks_obtained < 1024; ks_obtained++) { some_memory = (char *)malloc(size_to_allocate); if (some_memory == NULL) printf(“allocation failure\n”); sprintf(some_memory, "Hello World"); } megs_obtained++; printf("Now allocated %d Megabytes\n", megs_obtained); } printf(“allocation success\n”); }
Kongju national University
Linux System Programming
memory4.c 메모리 남용해 보기
#include <unistd.h> #include <stdlib.h>
#define ONE_K (1024)
main() { char *some_memory; char *scan_ptr; some_memory = (char *)malloc(ONE_K); if (some_memory == NULL) printf(“allocation failure\n”);
scan_ptr = some_memory; while(1) { *scan_ptr = '\0'; scan_ptr++; } printf(“allocation success\n”); }
Kongju national University
Linux System Programming
Null Pointer 접근
memory 공간에 자리 잡지 않은 ( 즉 할당이 안된 ) 데이터
Unix/Linux 에서는 허용하지 않음#include <unistd.h>#include <stdlib.h>#include <stdio.h>
main() { char *some_memory = (char *)0;
printf("A read from null %s\n", some_memory); sprintf(some_memory, "A write to null\n"); }
결과 :A read from null (null) : GNU C library 에서는 null 문자 제공segmentation fault(core dumped) : null string 에 쓰기는 error
Kongju national University
Linux System Programming
또 다른 null pointer 접근 예#include <unistd.h>#include <stdlib.h>#include <stdio.h>
main() { char z = *(const char *)0; printf("I read from location zero\n");
}결과 :
segmentation fault(core dumped) : memory 위치 0 로 부터 직접 읽기 , 이는 허용되지 않음
Kongju national University
Linux System Programming
free() : 할당된 메모리 해제
#include <stdlib.h>
void free(void *ptr_to memory);
- 이전에 할당된 메모리를 pointer 를 통하여 접근
- 접근 한 뒤 release
- 한번 해제 한 memory 공간은 그 프로세스에 다시 할당된다는 보장이 없음( 다른 프로세스에서 사용 가능성이 있음 )
- 따라서 free() 를 시행한 memory pointer 는 다시 접근 불가
Kongju national University
Linux System Programming
free() 의 예
#include <stdlib.h>
#define ONE_K (1024)
main()
{
char *some_memory;
some_memory = (char *)malloc(ONE_K);
if (some_memory != NULL) {
free(some_memory);
}
}
Kongju national University
Linux System Programming
그외 memory 관리 함수
#include <stdlib.h>
void *calloc(size_t no_of_element, size_t element_size);
void *realloc(void *existing_memory, size_t new_size);
- calloc() 은 malloc() 과 유사하나 동일 data 형식에 대하여 array 형태로 memory allocation 시행 (0 으로 채움 )
- 연속된 memory 를 할당한다는 보장이 없음 ( 주의 !!)
- realloc() 은 이미 할당된 메모리 블록의 크기를 확장
- 이미 할당된 영역에서 연장할 수 없다면 다른 빈 공간으로 이동
- 따라서 반드시 새로 return 되는 pointer 를 사용해야 함
Kongju national University
Linux System Programming
2. File Locking
Linux 는 다중 사용자 / 다중 프로세스 환경 특정 파일이나 특정 device 를 일시 독점적
사용이 필요 예
lpr process 에 의한 특정 프린터 출력 시 충돌 방지 필요 /dev/modem 의 사용 시 특정 프로세스에서 독점 사용 필요
File locking 은 Linux 의 중요 기능 Locking method
파일 전체 잠금 : atomic way 파일 부분 잠금 : 파일 내용중 특정 부분만
Kongju national University
Linux System Programming
잠금 표식 파일 생성
Printer daemon 에 의한 다수 출력물 충돌 방지 /usr/spool/lpr/lock file 을 일시 생성 , 프린트 완료 후 제거 위 파일을 잠금 표식 파일 (Locking Indicator file)
일종의 binary Semaphore 파일의 생성은 low level system call 사용
open(), read(), write(), close()
Kongju national University
Linux System Programming
Locking file creation
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <errno.h>
main(){ int file_desc; int save_errno;
file_desc = open("/tmp/LCK.test", O_RDWR | O_CREAT | O_EXCL, 0444);
if (file_desc == -1) { save_errno = errno; printf("Open failed with error %d\n",save_errno); } else { printf("Open succeeded\n"); } exit(EXIT_SUCCESS);}
동작 방법
% lock1
Open Succeeded
% lock1
Open failed with error 17
- errno : /usr/include/errno.h참조
- 이 프로그램은 종료 된 뒤에도 lock file은 계속 존재
- 따라서 실행 중에만 lock file을 사용하는 critical section을 사용하기 위해서는 다른 방법 필요
Kongju national University
Linux System Programming
File locking: Critical section
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
const char *lock_file = "/tmp/LCK.test2";
main() {
int file_desc;
int tries = 10;
while (tries--) {
file_desc = open(lock_file, O_RDWR | O_CREAT | O_EXCL, 0444);
if (file_desc == -1) {
printf("%d - Lock already present\n", getpid());
sleep(3);
}
- 따라서 실행 중에만 lock file을 사용하는 critical section을 사용하기 위해서는 다른 방법 필요
- 프로그램 수행 중 독점적인 기능을 사용할 때는 lock file을 생성한 뒤 locking을 하고
- 해제 (release)를 할 시점에는 close() -> unlink() 함수 사용
Kongju national University
Linux System Programming
continue!
else { /* critical region */ printf("%d - I have exclusive access\n", getpid()); sleep(1); (void)close(file_desc); (void)unlink(lock_file); /* non-critical region */ sleep(2); } } /* while */ printf(“Done . . .\n”);}
실행 방법
% rm /tmp/LCK.test2
% lock2 & lock2
- 두 프로세스에서 동시에 locking을 시도하게 되고 먼저 시작된 프로세스에서 lock file을 생성하고 critical section에 들어 감
Kongju national University
Linux System Programming
fcntl() : 파일 구역 잠그기
#include <fcntl.h>
int fcntl(int fildes, int command,
struct flock *flock_struct);
command: 잠금 명령 (F_GETLK, F_SETLK, F_SETLKW)
struct flock :
short l_type = F_RDLCK( 공유잠금 ),F_UNLCK( 해제 ),F_WRLCK(배타적잠금 )
short l_whence = SEEK_SET, SEEK_CUR, SEEK_END (unistd.h 에 정의 )
off_t l_start = 파일내 영역중 잠금의 시작 (bytes)
off_t l_len = l_start 부터의 잠금영역의 크기 (bytes)
pid_t l_pid = 잠금 프로세스의 pid
Kongju national University
Linux System Programming
fcntl() continue !
command: 잠금 명령
F_GETLK : 잠금 정보 구하기 , 실제 lock 하지 않음 ,
다른 프로세스에 의한 locking 방지 , flock 구조체 전체 사용
* 이미 다른 프로세스에 의해 잠긴 경우 : flock 구조체에 정보 채워서 반환
* 잠겨 있지 않는 경우 : flock 구조체 변경 없이 반환
* file 의 locking 정보 구하기 실패하면 – 1 반환
F_SETLK : 실제 locking, l_type, l_pid 만 사용
F_SETLKW : F_GETLK 시행 후 다른 프로세스에 의해 잠긴 경우 waiting 명령
struct flock :
short l_type = F_RDLCK( 공유잠금 ),F_UNLCK( 해제 ),F_WRLCK( 배타적잠금 )
short l_whence = SEEK_SET, SEEK_CUR, SEEK_END (unistd.h 에 정의 )
off_t l_start = 파일내 영역중 잠금의 시작 (bytes)
off_t l_len = l_start 부터의 잠금영역의 크기 (bytes)
pid_t l_pid = 잠금 프로세스의 pidKongju national University
Linux System Programming
fcntl() : example code - p1
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
const char *test_file = "/tmp/test_lock";
main() {
int file_desc;
int byte_count;
char *byte_to_write = "A";
struct flock region_1;
struct flock region_2;
int res;
/* open a file descriptor */
file_desc = open(test_file, O_RDWR | O_CREAT, 0666);
if (!file_desc) {
fprintf(stderr, "Unable to open %s for read/write\n",test_file);
exit(EXIT_FAILURE);
}/* if */
- lock대상 파일은 100bytes 크기
- 위치는 /tmp/test.lock
- 두개의 영역에 걸쳐 locking
Kongju national University
Linux System Programming
fcntl() : example code – p2
/* put some data in the file */
for(byte_count = 0; byte_count < 100; byte_count++) {
(void)write(file_desc, byte_to_write, 1);
}/* for */
/* setup region 1, a shared lock, from bytes 10 -> 30 */
region_1.l_type = F_RDLCK;
region_1.l_whence = SEEK_SET;
region_1.l_start = 10;
region_1.l_len = 20;
/* setup region 2, an exclusive lock, from bytes 40 -> 50 */
region_2.l_type = F_WRLCK;
region_2.l_whence = SEEK_SET;
region_2.l_start = 40;
region_2.l_len = 10;
- /tmp/test.lock file에 먼저 100byte의 “A”로 채우기
- 첫번째 locking영역 10 – 30 byte 구역 을 구조체 flock에 입력 , 공유잠금
- 두번째 locking영역 40 – 50 bytes 구역을 구조체 flock에 입력 , 배타잠금
Kongju national University
Linux System Programming
fcntl() : example code – p3
/* now lock the file */
printf("Process %d locking file\n", getpid());
res = fcntl(file_desc, F_SETLK, ®ion_1);
if (res == -1) fprintf(stderr, "Failed to lock region 1\n");
res = fcntl(file_desc, F_SETLK, ®ion_2);
if (res == -1) fprintf(stderr, "Failed to lock region 2\n");
/* and wait for a while */
sleep(60);
printf("Process %d closing file\n", getpid());
close(file_desc);
printf(“\nDone. . .\n”);
}/* main */
Test 방법
예제 프로그램은 lock3.c
reference code로 lock4.c가 있음
두 파일을 compile !
% lock3 &
% lock4
두 프로세스가 경쟁적으로 lock file을 사용
Kongju national University