send me email if you have any questions.
what is procfs?
- porc file system으로 UNIX계열 OS에서 사용되며, OS의 각종 정보를 커널 모드가 아닌 유저 모드에서 쉽게 접근할 수 있도록 만들어 준다.
- ex) cpu사용율, 인터럽트, 네트워크 패킷 전송량, 적재된 모듈 등..
why use?
- 파일 시스템의 오버헤드를 줄일 수 있다.
- 일반적인 파일시스템은 inode와 superblocs같은 객체를 통해 관리.
- 물리적인 파일 시스템 장치가 필요하지 않다.
- proc는 커널 메모리에서 동작하는 가상 파일 시스템으로 커널에서 직접 관리.
how use?
- Makefile과 source code가 필요. -> make를 통해 모듈 생성
- 모듈을 적재하면 /proc디렉터리 아래에 procfile이 생성됨.
- echo “hello world!” » /proc/test 와 같은 터미널 명령이나 다른 프로세스에서 file io 를 이용해 write하여 proc file에 정보를 기록
- cat /proc/test 와 같은 터미널 명령이나 다른 프로세스에서 fs를 이용해 read하여 proc file을 읽을 수 있다.
example code
obj-m := procfs.o
obj := procfs
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all: default
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
rm -rf *.o *.mod* *dule*
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
Makefile
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define FILE_NAME "procfs"
#define FILE_SIZE 100
struct data_t
{
char value[FILE_SIZE + 1];
}netstat;
static struct proc_dir_entry *netstat_file;
/* proc file에 데이터를 쓰는 함수 */
static ssize_t write(struct file *file, const char *buf,
size_t count, loff_t *pos)
{
int len;
len = (count > FILE_SIZE) ? FILE_SIZE : count;
/* raw_copy_from_user? -> copy_from_user함수의 function chaining에 연결됨 */
if (raw_copy_from_user(netstat.value, buf, len)) //write 실패시 error return
return -EFAULT; // address error
netstat.value[len] = 0x00;
printk("%s count:%ld\n", netstat.value, count);
return len;
}
/* proc file을 읽을 경우 실행되는 함수 */
static int proc_show(struct seq_file *m, void *v)
{
// printk("%s\n", (char *)m->private);
seq_printf(m, "%s", netstat.value); // 출력 형식
return 0;
}
static int proc_open(struct inode *inode, struct file *file)
{
// return single_open(file, proc_show, "private_data");
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)
{
strcpy(netstat.value, ""); //proc file 초기값
// procfs 파일 생성
netstat_file = proc_create(FILE_NAME, 0646, NULL, &proc_fops);
//파일이름, 퍼미션, 디렉토리, file_operations 구조체
if(netstat_file == NULL){ //proc file 생성 실패경우
printk("netsat_file: error \n");
return -EEXIST;
}
// 시스템 로그에 mod_procfs_init 출력
printk("%s\n", __FUNCTION__);
return 0;
}
/* 모듈 제거 함수 */
static void mod_procfs_exit(void){
// 디렉토리, 파일 삭제
remove_proc_entry(FILE_NAME, NULL);
// 파일이 위치하고있는 디렉토리
remove_proc_entry(NULL, NULL);
// 시스템 로그에 mod_procfs_exit 출력
printk("%s\n", __FUNCTION__);
}
module_init(mod_procfs_init);
module_exit(mod_procfs_exit);
procfs.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
void main(void)
{
char buf[100];
int fd = open("/proc/wireless", O_RDWR);
read(fd, buf, 100);
printf("%s",buf);
}
read-proc.c
PREVIOUSC Thread example
NEXTC Shared memory