3.10 이후의 커널 버전에서의 struct proc_dir_entry 사용법에 대한 질문입니다.
현재 proc 파일 시스템 부분을 진행하고 있습니다만,
제가 참고하고있는 책(한빛미디어, IT EXPERT : 리눅스 커널 프로그래밍, 2006)에서 다루는 버전은 2.6버전이고 현재 kernel.org에서 구한 버전은 4.3.3이라서
차이가 큽니다. 때문에 어차피 배울 거 변경 사항이 있으면 그건 구글링으로 찾아본다는 방침으로 지금까지 해왔습니다만, 구글링으로도 제대로 된 답을 제 능력으로는 찾을 수 없었기에 질문드립니다.
3.10 버전 이후에서는 create_proc_entry 함수가 아예 삭제되고, proc_create로 대체되었으며, linux/proc_fs.h에서 정의되어있던 struct proc_dir_entry의 정의가 fs/proc/internal.h로 이동되었다는 사실까진 알아냈습니다.
// 선언
static struct proc_dir_entry *simple_proc = NULL;
static char* buf[100];
...
// file_operations
static struct file_operations simple_fops =
{
.owner = THIS_MODULE,
.read = my_read,
.write = my_write
};
// create
simple_proc = proc_create( "simple", 0, NULL, &simple_fops );
/* 구 버전에서의 지정
simple_proc->data = buf;
simple_proc->read_proc = my_read;
*/
...구 버전 방식으로 직접 지정하게 되면, dereferencing pointer to incomplete type 에러를 '지정' 섹션의 두 줄에서 출력하며 빌드되지 않습니다.
internal.h를 직접 include 하면 빌드가 가능하겠지만, 일부러 숨겨 놓은 것인데 그렇게 include하라고 만들어 놓았을 것 같지는 않으니 분명 다른 사용법이 있을 텐데, 그걸 찾지 못하고 있습니다.
proc_create 함수가 4번째 인수로 file_operations 구조체를 요구하는 점에서 착안하여 file_operations 구조체를 만들어 넣어줬습니다만, data는 여전히 지정할 방법을 모르겠습니다.
혹시 알고 계시는 분 계시면 친절하게 답변 부탁드립니다.
참고를 위하여 코드를 한 번 올려보겠습니다.
// 입력한 데이터를 그대로 반환하는 simple proc 파일
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/proc_fs.h> // procfs 관련 자료구조
#include <asm/uaccess.h>
static struct proc_dir_entry *simple_proc = NULL;
static char buf[100];
// /proc/simple을 읽을 때 호출되는 my_read
static int my_read( char* page, char **start, off_t off, int count, int *eof, void* data )
/*
* 매개변수 설명 *
page : 전달할 데이터를 저장할 공간
start : 스트림 데이터의 시작 위치, 대개는 다루지 않으므로 쓰지 않는다.
off : 현재 처리중인 파일의 현재 위치
count : 버퍼의 크기를 바이트 단위로 지정
eof : 파일의 끝을 설정
*/
{
int len;
len = sprintf( page, "[Msg] %s\n", (char *) data );
// page에, data의 내용을 출력한다. data는 앞에서 선언한 buf와 연결될 것.
// page는 각 proc 항목에 할당된 데이터 공간, page 단위(4096byte)로 할당.
// echo 효과이므로, 그대로 출력하는 것으로 충분.
*eof = 1; // 데이터 처리 완료로 설정
return len;
}
// my_write
static int my_write( struct file *file, const char *buffer, unsigned long count, void *data )
{
char *kernel_data;
kernel_data = (char*) data;
copy_from_user( kernel_data, buffer, count );
// NULL 문자 표시
kernel_data[count] = '\0';
if( kernel_data[ count - 1 ] == '\n' )
kernel_data[ count - 1 ] = '\0';
return count;
}
static struct file_operations simple_fops =
{
.owner = THIS_MODULE,
.read = my_read,
.write = my_write
};
int __init simple_init( void)
{
simple_proc = proc_create( "simple", 0, NULL, &simple_fops );
if( simple_proc == NULL )
return -ENOMEM; // error : NO MEMORY
return 0;
}
void __exit simple_exit(void)
{
remove_proc_entry( "simple", NULL );
// /proc/simple 삭제
}
module_init( simple_init );
module_exit( simple_exit );
MODULE_LICENSE( "GPL" );

조금 더 찾아보니, 간단한 코드 하나는 찾을 수 있었습니다.
#include <linux/module.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> static int hello_proc_show(struct seq_file *m, void *v) { seq_printf(m, "Hello proc!\n"); return 0; } static int hello_proc_open(struct inode *inode, struct file *file) { return single_open(file, hello_proc_show, NULL); } static const struct file_operations hello_proc_fops = { .owner = THIS_MODULE, .open = hello_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int __init hello_proc_init(void) { proc_create("hello_proc", 0, NULL, &hello_proc_fops); return 0; } static void __exit hello_proc_exit(void) { remove_proc_entry("hello_proc", NULL); } MODULE_LICENSE("GPL"); module_init(hello_proc_init); module_exit(hello_proc_exit);이러한 모듈 코드입니다. 이 모듈을 그대로 코딩하고 cat 명령을 해 보면, 정상적으로 hello proc!이 출력되는 것을 확인하였습니다.
seq_file이라는 생소한 헤더 파일이 쓰였는데, 이건 한 숨 자고 일어나서 살펴봐야겠군요. ㅜㅜ
댓글 달기