Linux Kernel 4.x의 proc 파일 시스템 예제 코드
/**
* file : proc.c
* brief : procfs of kernel version 4.x
* author : Jihoon Park (INSLAB)
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#define DIRECTORY "ai_result"
#define FILE_PREDICT0 "prediction0"
#define FILE_PREDICT1 "prediction1"
#define FILE_NETSTAT0 "netstat0"
#define FILE_NETSTAT1 "netstat1"
#define FILE_MAX_SIZE 100
static struct proc_dir_entry *predict0_file, *predict1_file, *netstat0_file, *netstat1_file, *netstat_dir;
char file_value[4][FILE_MAX_SIZE];
/* proc file에 데이터를 쓰는 함수 */
static ssize_t write(struct file *file, const char *buf, size_t count, loff_t *pos)
{
int len;
int target_idx;
char *file_name = file->f_path.dentry->d_iname;
len = (count > FILE_MAX_SIZE) ? FILE_MAX_SIZE : count;
if(!strcmp(file_name, "prediction0")) target_idx = 0;
else if(!strcmp(file_name, "prediction1")) target_idx = 1;
else if(!strcmp(file_name, "netstat0")) target_idx = 2;
else if(!strcmp(file_name, "netstat1")) target_idx = 3;
if (raw_copy_from_user(file_value[target_idx], buf, len)) //write 실패시 error return
return -EFAULT; // address error
file_value[target_idx][len] = 0x00;
return len;
}
/* proc file을 읽을 경우 실행되는 함수 */
static int proc_show(struct seq_file *m, void *v)
{
char *file_name = m->file->f_path.dentry->d_iname;
int target_idx;
if(!strcmp(file_name, "prediction0")) target_idx = 0;
else if(!strcmp(file_name, "prediction1")) target_idx = 1;
else if(!strcmp(file_name, "netstat0")) target_idx = 2;
else if(!strcmp(file_name, "netstat1")) target_idx = 3;
seq_printf(m, "%s", file_value[target_idx]); // 출력 형식
return 0;
}
static int proc_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_show, NULL);
}
// file_operations 구조체 초기화
// c99 버전부터 아래와 같은 방식으로 초기화 가능
static const struct file_operations proc_fops = {
.owner = THIS_MODULE,
//파일을 열때 불려지는 함수
.open = proc_open,
// 파일을 읽을때 불려지는 함수
.read = seq_read,
// 파일을 쓸때 불려지는 함수
.write = write,
.llseek = seq_lseek,
.release = single_release,
};
/* module 적재 함수 */
static int mod_procfs_init(void)
{
int i;
for(i=0; i<3; i++)
strcpy(file_value[i], "0");
netstat_dir = proc_mkdir(DIRECTORY, NULL);
// procfs 파일 생성
// 파일이름, 퍼미션, 디렉토리, file_operations 구조체
predict0_file = proc_create(FILE_PREDICT0, 0646, netstat_dir, &proc_fops);
predict1_file = proc_create(FILE_PREDICT1, 0646, netstat_dir, &proc_fops);
netstat0_file = proc_create(FILE_NETSTAT0, 0646, netstat_dir, &proc_fops);
netstat1_file = proc_create(FILE_NETSTAT1, 0646, netstat_dir, &proc_fops);
if(predict0_file == NULL || predict1_file == NULL || netstat0_file == NULL || netstat1_file == NULL )
{
printk("netsat_file: error \n");
return -EEXIST;
}
printk("%s\n", __FUNCTION__);
return 0;
}
/* 모듈 제거 함수 */
static void mod_procfs_exit(void){
remove_proc_entry(FILE_PREDICT0, netstat_dir);
remove_proc_entry(FILE_PREDICT1, netstat_dir);
remove_proc_entry(FILE_NETSTAT0, netstat_dir);
remove_proc_entry(FILE_NETSTAT1, netstat_dir);
remove_proc_entry(DIRECTORY, NULL);
printk("%s\n", __FUNCTION__);
}
module_init(mod_procfs_init);
module_exit(mod_procfs_exit);
MODULE_LICENSE("INSLAB");
Linux Kernel 5.x의 proc 파일 시스템 예제 코드
/**
* file : proc.c
* brief : procfs of kernel version 5.x
* author : Jihoon Park (INSLAB)
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#define DIRECTORY "inslab"
#define FILE_RESULT0 "result0"
#define FILE_RESULT1 "result1"
#define FILE_NETSTAT0 "netstat0"
#define FILE_NETSTAT1 "netstat1"
#define FILE_MAX_SIZE 100
static struct proc_dir_entry *result0_file, *result1_file, *netstat0_file, *netstat1_file, *netstat_dir;
char file_value[4][FILE_MAX_SIZE];
/* proc file에 데이터를 쓰는 함수 */
static ssize_t write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
int len;
int target_idx;
char *file_name = file->f_path.dentry->d_iname;
len = (count > FILE_MAX_SIZE) ? FILE_MAX_SIZE : count;
if(!strcmp(file_name, "result0")) target_idx = 0;
else if(!strcmp(file_name, "result1")) target_idx = 1;
else if(!strcmp(file_name, "netstat0")) target_idx = 2;
else if(!strcmp(file_name, "netstat1")) target_idx = 3;
if (raw_copy_from_user(file_value[target_idx], buf, len)) //write 실패시 error return
return -EFAULT; // address error
file_value[target_idx][len] = 0x00;
return len;
}
/* proc file로부터 데이터를 읽는 함수 */
static ssize_t read(struct file *file, char __user *buff, size_t count, loff_t *pos)
{
int len = 0;
int target_idx = 0;
char *file_name = file->f_path.dentry->d_iname;
/* proc을 read하면 반복적으로 읽히는 현상이 발생한다.
* 커널 버그인지는 잘 모르겠지만 반복 읽힘 문제를 해결하기
* 위해 completed 변수로 반복을 제어하는 코드를 추가하였다.
*
* ref : https://github.com/ray326/hw1
**/
static int completed = 0;
if (completed) {
completed = 0;
return 0;
}
completed = 1;
if(!strcmp(file_name, "result0")) target_idx = 0;
else if(!strcmp(file_name, "result1")) target_idx = 1;
else if(!strcmp(file_name, "netstat0")) target_idx = 2;
else if(!strcmp(file_name, "netstat1")) target_idx = 3;
len = strlen(file_value[target_idx]);
if (raw_copy_to_user(buff, file_value[target_idx], len))
return -EFAULT;
return len;
}
// proc_ops 구조체 초기화
static const struct proc_ops proc_fops = {
// 파일을 읽을때 불려지는 함수
.proc_read = read,
// 파일을 쓸때 불려지는 함수
.proc_write = write
};
/* module 적재 함수 */
static int mod_procfs_init(void)
{
int i;
for(i=0; i<4; i++)
strcpy(file_value[i], "0\0");
netstat_dir = proc_mkdir(DIRECTORY, NULL);
// procfs 파일 생성
// 파일이름, 퍼미션, 디렉토리, file_operations 구조체
result0_file = proc_create(FILE_RESULT0, 0646, netstat_dir, &proc_fops);
result1_file = proc_create(FILE_RESULT1, 0646, netstat_dir, &proc_fops);
netstat0_file = proc_create(FILE_NETSTAT0, 0646, netstat_dir, &proc_fops);
netstat1_file = proc_create(FILE_NETSTAT1, 0646, netstat_dir, &proc_fops);
if(result0_file == NULL || result1_file == NULL || netstat0_file == NULL || netstat1_file == NULL )
{
printk("netsat_file: error \n");
return -EEXIST;
}
printk("inslab_proc : %s\n", __FUNCTION__);
return 0;
}
/* 모듈 제거 함수 */
static void mod_procfs_exit(void){
remove_proc_entry(FILE_RESULT0, netstat_dir);
remove_proc_entry(FILE_RESULT1, netstat_dir);
remove_proc_entry(FILE_NETSTAT0, netstat_dir);
remove_proc_entry(FILE_NETSTAT1, netstat_dir);
remove_proc_entry(DIRECTORY, NULL);
printk("inslab_proc : %s\n", __FUNCTION__);
}
module_init(mod_procfs_init);
module_exit(mod_procfs_exit);
MODULE_LICENSE("INSLAB");
약간의 설명
리눅스 4점대 커널 버전에서는 proc operation을 file_operations 구조체로 관리하였다.
하지만 5점대 커널 버전에서는 proc operation을 따로 proc_ops 구조체로 관리하고 있다.
따라서, 4점대에서 사용하던 proc 파일시스템 코드를 사용하지 못해 5점대에서는 위와 같이 업데이트 해주어야 한다.
Ref..
'Linux' 카테고리의 다른 글
Python에서 C함수 사용해서 리턴값 받기 in Linux (2) | 2022.09.02 |
---|---|
Linux 커널에서 Built-in 모듈간의 IPC 방법 (+TCP Cwnd 제어) (0) | 2022.08.30 |
Linux 커널의 TC(Traffic Control) 구조 (0) | 2022.07.15 |
새로운 소켓 옵션 생성 방법 (in Linux Kernel) (0) | 2022.04.11 |
여러 네트워크 인터페이스(NIC) 중 특정 인터페이스를 통한 통신 방법 (in Linux) (0) | 2022.01.12 |