티스토리 뷰

목차

    반응형

    리눅스 PROC 2. 프로그래밍 기초와 코딩 API


    proc 프로그래밍 기초


    1. 리눅스 proc 구조체 및 API


    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
    31
    struct proc_dir_entry {
        unsigned short low_ino;
        unsigned short namelen;
        const char *name;
     
        mode_t mode;
     
        nlink_t nlink;
     
        uid_t uid;
        gid_t gid;
     
        unsigned long size;
        struct inode_operations * proc_iops;
        struct file_operations * proc_fops;
     
        get_info_t *get_info;
     
        struct module *owner;
        struct proc_dir_entry *next, *parent, *subdir;
     
        void *data;
     
        read_proc_t *read_proc;
        write_proc_t *write_proc;
     
        atomic_t count; /* use count */
        int deleted; /* delete flag */
     
        kdev_t rdev;
    };
    cs


    프로그래밍 기초, proc_dir_entry 구조체


    const char *name

    - proc파일의 이름

    mode_t mode

    - proc파일의 권한으로 일반파일에 사용되는 권한과 동일하게 사용할 수 있다.


    struct proc_dir_entry *next, *parent, *subdir

    - 리눅스 proc파일이 위치하는 디렉토리로 일반 파일에서의 디렉토리 권한과 동일하게 사용되며, 링크드 리스트로 관리된다.


    void *data

    - data proc에서 읽은 데이터를 리턴하기 위해서 사용된다. 


    read_proc, write_proc 

    - 유저영역의 프로세스는 직접 커널 영역에 데이터를 읽거나 쓸 수 없다. 때문에 모듈 프로그램 등이 중간에서 커널과 유저영역 사이의 데이터전달을 해주어야 한다. 이러한 데이터 전달은 프로그래밍 과정에서 callback 함수를 통해서 이루어진다.


    read_proc는 커널로부터 읽은 데이터를 유저영역 프로세스로 되돌려주기 위해서 write_proc는 유저역역 프로세스에서 쓴 데이터를 커널 메모리 영역으로 복사하기 위해서 사용한다. 


    리눅스 PROC 2. 프로그래밍 기초와 코딩 API


    create_proc_entry


    1
    2
    3
    4
    5
    6
    struct proc_dir_entry *create_proc_entry
    (
        const char *name,
        mode_t mode,
        struct proc_dir_entry *parent);
    );
    cs


    첫 번째 인자인 name을 이름으로 하는 proc파일을 생성한다. mode는 생성될 때의 파일 모드로 open에 사용되는 것과 동일하게 사용된다.

    마지막 인자인 parent는 name로 만들어진 proc파일이 위치할 디렉토리다. 리눅스 proc 파일은 루트디렉토리가 "/"아닌 "/proc"에서부터 시작하게 된다. 만약 NULL이라면 /proc 디렉토리 밑에 위치하게 된다. 


    create_proc_read_entry 


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    static inline
    struct proc_dir_entry *create_proc_read_entry(
                            const char *name,mode_t mode,
                            struct proc_dir_entry *base,read_proc_t * read_proc,
                            void *data)
    {
        struct proc_dir_entry *res = create_proc_entry(name, mode, base);
     
        if (res)
        {
            res->read_proc = read_proc;
            res->data=data;
        }
     
        return res; 
    }
    cs


    create_proc_entry의 포장(wrapper) 함수

    쉽게 프로그래밍하여 읽기용 proc 파일을 만들 수 있다.


    linux proc 프로그래밍


    create_proc_info_entry


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ststic inline
    struct proc_dir_entry *create_proc_info_entry(
                        const char *name,
                        mode_t mode, struct proc_dir_entry *base,
                        get_info_t *get_info)
    {
        struct proc_dir_entry *res = create_proc_entry (name, mode, base);
     
        if (res) 
            res->get_info = get_info;
     
            return res;
    }
    cs


    create_proc_entry의 포장함수

    리눅스 proc 파일을 만들고 정보를 보여준다

    2. proc API


    proc_mkdir 


    1
    2
    3
    extern struct proc_dir_entry *proc_mkdir ( 
        const char *dir_name,
        struct proc_dir_entry *parent )
    cs


    proc파일 시스템에 디렉토리를 생성. 만들어지는 디렉토리는 proc파일 시스템의 최상위 디렉토리(/proc)를 기준으로 한다. 


    proc_symlink 


    1
    2
    3
    4
    extern struct proc_dir_entry *proc_symlink(
            const char *file_name,
            struct proc_dir_entry *parent,
            const char *symlink_name ); 
    cs


    심볼릭 링크를 프로그래밍(만들기) 위해서 사용. 실제 사용자(real user)만이 사용할 수 있다.


    리눅스 프로그래밍 proc


    remove_proc_entry 


    1
    2
    3
    extern void *remove_proc_entry(
            const char *name,
            struct proc_dir_entry parent ); 
    cs


    생성된 리눅스 proc 파일을 제거하는 함수. 프로그램 종료 시 이 함수를 호출하여 proc 파일을 지워 주는 것이 좋다


    3. 기타 포장 함수들


    proc_net_create

    create_proc_info_entry의 /proc/net 정보에 대한 포장함수. 네트워크 서브시스템에 대해서 쉽게 접근.


    1
    2
    3
    4
    5
    6
    7
    static inline
    struct proc_dir_entry *proc_net_create(
            const char *name,
            mode_t mode, get_info_t *get_info)
    {
        return create_proc_info_entry(name, mode, proc_net, get_info); 
    }
    cs

    proc_net_remove


    네트워크 서브 시스템에 대한 remove_proc_entry의 포장함수 


    1
    2
    3
    4
    static inline void proc_net_remove(const char *name)
    {
        remove_proc_entry(name, proc_net)
    }
    cs


    4-4. 일반 유저와의 데이터 교환 프로그래밍 기초

    - 일반 파일에서 유저와의 데이터 교환은 매우 단순.

    - 리눅스 proc파일 시스템은 커널 메모리에 저장되는데 커널 메모리는 유저레벨에서 직접 접근할 수 없다.

    - 커널과 일반유저 사이에 데이터를 서로에게 전달해 주는 어떤 함수가 필요하고 이 함수가 다룰 수 있는 표준적인 자료구조가 있어야 한다. 유저가 데이터를 읽고 쓰기 위해서는 읽기와 쓰기를 위한 callback 함수를 등록시켜서 사용해야 한다.

    - pric_dir_entry에 읽기/쓰기를 위한 콜백함수를 등록


    1
    2
    3
    4
    struct proc_dir_entry *entry;
     
    entry->read_proc = read_proc;
    entry->write_proc = write_proc;
    cs


    데이터 읽기

    유저영역 프로세스의 요청을 받으면 커널로부터 데이터를 읽어 들여서 알맞은 포맷으로 변경한 다음 유저영역 프로세스로 되돌려준다.


    읽기 함수는 읽어들 인 정보를 page에 쓰게 된다.


    1
    int read_func(char* page, char** start, off_t off, int count, int* eof, void* data);
    cs


    데이터 쓰기

    유저영역 프로세스로부터 데이터를 받은 다음 커널이 읽기 가능한 형식으로 변경 후 커널에 넘겨준다.


    쓰기함수는 buffer로부터 유저가 쓴 데이터를 읽어 들인다. buffer는 유저 데이터이므로 copy_from_user을 이용해서 커널 메모리 영역으로 데이터를 복사한다.


    1
    int write_func(struct file* file, const char *buffer, unsigned long count,void *data);
    cs



    리눅스 PROC 2. 프로그래밍 기초와 코딩 API

    반응형