[제7장] 데이터 관리

정보 | 2007/06/25 19:03

=================================================================
  * 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, &region_1);
    if (res == -1) fprintf(stderr, "Failed to lock region 1\n");
    res = fcntl(file_desc, F_SETLK, &region_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, &region_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(&region_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, &region_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(&region_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_

Trackback Address :: http://badnom.com/trackback/289 관련글 쓰기
Name
Password
Homepage
Secret
< PREV |  1  |  ...  830  |  831  |  832  |  833  |  834  |  835  |  836  |  837  |  838  |  ...  1058  |  NEXT >