본문 바로가기
C++ 200제/코딩 IT 정보

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

by vicddory 2017. 3. 19.

리눅스 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

댓글