[제7장] 데이터 관리
=================================================================
* Subject : [제7장] 데이터 관리
* Writer: w0rm9 (research.hackerschool.org)
* Date: 2004/02/03
=================================================================
/* 스터디 참여 못해서 로그를 바탕으로 정리했습니다.
* dbm 부분은 스터디 하지 않아서 뺐고, 쉬운 부분은 테스트 하지 않았습니다.
*/
0x01. 메모리 관리하기
■ 간단한 메모리 할당
사용법)
#include <stdlib.h>
void *malloc(size_t size);
=> size만큰의 메모리를 할당
■ 메모리 해제하기
사용법)
#include <stdlib.h>
void free(void *ptr_to memory);
=> 메모리 해제
■ 그 밖의 메모리 할당 함수
사용법)
#include <stdlib.h>
void *calloc(size_t number_of_elements, size_t element_size);
void *realloc(void *existing_memory, size_t new_size);
=> calloc함수는 요소의 수와 각 요소의 크기를 파라미터로 받아들여 배열 행태로 메모리에 할당. 할당된 메모리는 0으로 채워짐
realloc함수는 이전에 할당된 메모리 블록의 크기를 변경한다.
0x02. 파일 잠금
■ 잠금 파일 생성하기
테스트)
[w0rm9@work DATA]$ cat lock1.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
int 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);
}
[w0rm9@work DATA]$ gcc -o lock1 lock1.c
[w0rm9@work DATA]$ ./lock1
Open succeeded //처음엔 성공했지만,
[w0rm9@work DATA]$ ./lock1
Open failed with error 17 //두번째는 실패. O_CREAT와 O_EXCL 플래그를 사용하였기 때문에
[w0rm9@work DATA]$
0x03. 구역 잠그기
■ fcntl
사용법)
#include <fcntl.h>
int fcntl(int fildes, int command, struct flock *flock_structure);
□ 파일 잠금에서 필요한 세가지 command 값
F_GETLK fildes가 열었던 파일에 대한 잠금 정보를 구한다. 파일을 잠그지 않는다.
◆ flock 구조체에서 사용되는 값
l_type 공유나 읽기 전용 잠금을 가리키는 F_RDLCK나 배타나 쓰기 잠금을 가리키는 F_WRLCK
l_whence SEEK SET, SEEK CUR, SEEK END의 하나
l_start 원하는 파일 구역의 시작 바이트
l_len 원하는 파일 구역의 바이트 수
l_pid 잠금을 가지는 프로세스의 식별자
F_SETLK fildes가 참조하는 파일의 일부분을 자금거나 해제한다. 잠금에 실패하면 -1을 반환.
◆ flock 구조체에서 사용되는값
l_type 읽기 전용이나 공유 잠금을 가리키는 F_RDLCK나 배타적이거나 쓰기 잠금을 가리키는 F_WRLCK 구역을 해제하기 위한 F_UNLCK
l_pid 사용되지 않음
F_SETLKW 잠금을 구할 수 없으면 가능할 때까지 대기한다는 사실을 제외하고는 앞의 F_SETLK 명령과 같다.
테스트)
[w0rm9@work DATA]$ cat lock3.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
const char *test_file = "/tmp/lock.tmp";
int main() {
int file_desc;
int byte_count;
char *byte_to_write = "A";
struct flock region_1;
struct flock region_2;
int res;
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);
}
for(byte_count = 0; byte_count < 100; byte_count++) {
(void)write(file_desc, byte_to_write, 1);
}
/* 10~20까지 공유 잠금 설정 */
region_1.l_type = F_RDLCK;
region_1.l_whence = SEEK_SET;
region_1.l_start = 10;
region_1.l_len = 20;
/* 40~50까지 배타 잠금 설정 */
region_2.l_type = F_WRLCK;
region_2.l_whence = SEEK_SET;
region_2.l_start = 40;
region_2.l_len = 10;
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");
sleep(60);
printf("Process %d closing file\n", getpid());
close(file_desc);
exit(EXIT_SUCCESS);
}
[w0rm9@work DATA]$ gcc -o lock3 lock3.c
[w0rm9@work DATA]$ cat lock4.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
const char *test_file = "/tmp/lock.tmp";
#define SIZE_TO_TRY 5
void show_lock_info(struct flock *to_show);
int main() {
int file_desc;
int res;
struct flock region_to_test;
int start_byte;
file_desc = open(test_file, O_RDWR | O_CREAT, 0666);
if (!file_desc) {
fprintf(stderr, "Unable to open %s for read/write", test_file);
exit(EXIT_FAILURE);
}
/* for()를 통해 파일의 잠금 여부를 구역별로 테스트한다. */
for (start_byte = 0; start_byte < 99; start_byte += SIZE_TO_TRY) {
region_to_test.l_type = F_WRLCK;
region_to_test.l_whence = SEEK_SET;
region_to_test.l_start = start_byte;
region_to_test.l_len = SIZE_TO_TRY;
region_to_test.l_pid = -1;
printf("Testing F_WRLCK on region from %d to %d\n",
start_byte, start_byte + SIZE_TO_TRY);
res = fcntl(file_desc, F_GETLK, ®ion_to_test);
if (res == -1) {
fprintf(stderr, "F_GETLK failed\n");
exit(EXIT_FAILURE);
}
if (region_to_test.l_pid != -1) {
printf("Lock would fail. F_GETLK returned:\n");
show_lock_info(®ion_to_test);
}
else {
printf("F_WRLCK - Lock would succeed\n");
}
region_to_test.l_type = F_RDLCK;
region_to_test.l_whence = SEEK_SET;
region_to_test.l_start = start_byte;
region_to_test.l_len = SIZE_TO_TRY;
region_to_test.l_pid = -1;
printf("Testing F_RDLCK on region from %d to %d\n",
start_byte, start_byte + SIZE_TO_TRY);
res = fcntl(file_desc, F_GETLK, ®ion_to_test);
if (res == -1) {
fprintf(stderr, "F_GETLK failed\n");
exit(EXIT_FAILURE);
}
if (region_to_test.l_pid != -1) {
printf("Lock would fail. F_GETLK returned:\n");
show_lock_info(®ion_to_test);
}
else {
printf("F_RDLCK - Lock would succeed\n");
}
} /* for */
close(file_desc);
exit(EXIT_SUCCESS);
}
void show_lock_info(struct flock *to_show) {
printf("\tl_type %d, ", to_show->l_type);
printf("l_whence %d, ", to_show->l_whence);
printf("l_start %d, ", (int)to_show->l_start);
printf("l_len %d, ", (int)to_show->l_len);
printf("l_pid %d\n", to_show->l_pid);
}
[w0rm9@work DATA]$ gcc -o lock4 lock4.c
[w0rm9@work DATA]$ ./lock3 &
[1] 21404
[w0rm9@work DATA]$ Process 21404 locking file
[w0rm9@work DATA]$ ./lock4
Testing F_WRLCK on region from 0 to 5
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 0 to 5
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 5 to 10
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 5 to 10
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 10 to 15 // 10 ~ 30까지 공유 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 21404
Testing F_RDLCK on region from 10 to 15
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 15 to 20 // 10 ~ 30까지 공유 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 21404
Testing F_RDLCK on region from 15 to 20
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 20 to 25 // 10 ~ 30까지 공유 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 21404
Testing F_RDLCK on region from 20 to 25
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 25 to 30 // 10 ~ 30까지 공유 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 21404
Testing F_RDLCK on region from 25 to 30
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 30 to 35
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 30 to 35
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 35 to 40
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 35 to 40
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 40 to 45 // 40 ~ 50까지 배타 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 21404
Testing F_RDLCK on region from 40 to 45 // 40 ~ 50까지 배타 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 21404
Testing F_WRLCK on region from 45 to 50 // 40 ~ 50까지 배타 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 21404
Testing F_RDLCK on region from 45 to 50 // 40 ~ 50까지 배타 잠금으로 인해 실패
Lock would fail. F_GETLK returned:
l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 21404
Testing F_WRLCK on region from 50 to 55
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 50 to 55
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 55 to 60
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 55 to 60
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 60 to 65
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 60 to 65
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 65 to 70
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 65 to 70
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 70 to 75
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 70 to 75
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 75 to 80
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 75 to 80
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 80 to 85
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 80 to 85
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 85 to 90
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 85 to 90
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 90 to 95
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 90 to 95
F_RDLCK - Lock would succeed
Testing F_WRLCK on region from 95 to 100
F_WRLCK - Lock would succeed
Testing F_RDLCK on region from 95 to 100
F_RDLCK - Lock would succeed
[w0rm9@work DATA]$ Process 21404 closing file
■ 그 밖의 잠금 명령
사용법)
#include <unistd.h>
int lockf(int fildes, int function, off_t size_to_lock);
=> function에 따라 파일을 현재 오프셋에서 부터 바이트 수 만큼 잠근다.
□ function 값
F_ULOCK 잠금 해제
F_LOCK 배타적인 잠금
F_TLOCK 테스트와 배타적인 잠금
F_TEST 다른 프로세스에 의한 잠금 테스트
테스트)
알아서하기요- _-//
_eof_
