티스토리 뷰
목차
리눅스 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는 유저역역 프로세스에서 쓴 데이터를 커널 메모리 영역으로 복사하기 위해서 사용한다.
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 파일을 만들 수 있다.
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)만이 사용할 수 있다.
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