강좌 & 팁
안녕하세요 판다 이우영입니다.
이번주는 태풍이 한바탕 하고 지나갔는데요 다들 피해 없으셨으면 좋겠습니다.
그럼 먼저 복습!
1. 복습!!
저번 시간에는 struct proc_dir_entry 에 등록하는 read, write 함수에 대해서 알아보았습니다.
그럼 간단하게 함수를 만드는 방법을 볼까요?
int read_proc_func(char *page, char **start, off_t off, int count, int *eof, void *data_unused) { 읽을 data를 page에 써 넣는다. *eof = 1; return 써 넣은 data의 수 } int write_proc_func(struct file *file, const char *buffer, unsigned long count, void *data) { buffer를 통해 넘어온 data를 커널영역에 저장한다 return 처리한 data의 수 } |
함수의 원형은 include/linux/proc_fs.h 를 참조 하시면 되겠습니다.
인자들중 마지막 인자인 void * 타입은 proc_dir_entry에 등록한 data 가 날라옵니다.
위에 나와 있는데로 하시면 문제는 없을꺼 같습니다.
다만 주의할 점이 하나 있었죠?
data를 저장할때 PAGE_SIZE - 80 크기만큼만 사용가능하다는거~ 잊지마세요!
그럼 다음으로!!
2. proc 파일 생성과 삭제
오늘은 proc 파일을 생성하고 삭제하는 함수에 대해서 알아 보겠습니다.
소스는 kernel 3.5.3 버전에서 fs/proc/generic.c에 있습니다.
먼저 폴더를 생성하는 proc_mkdir 입니다.
695struct proc_dir_entry *proc_mkdir(const char *name, 696 struct proc_dir_entry *parent) 697{ 698 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent); 699} 700EXPORT_SYMBOL(proc_mkdir);
인자는 2개 들어갑니다. 먼저 폴더의 이름 그리고 상위 폴더의 proc_dir_entry 가 들어 갑니다.
예로 /proc 밑에 폴더를 생성 할때에는 2번째 인자에 0을 주어 생성합니다.
struct proc_dir_entry *proc_dir = NULL;
proc_dir = proc_dir_mkdir("topdir", 0);
이렇게 선언 하시면 /proc 에 topdir이 생성됩니다.
그럼 topdir 아래에 생성하기 위해서는 다음과 같이 생성하면
struct proc_dir_entry * bottom_proc_dir = NULL;
bottom_proc_dir = proc_dir_mkdir("bottomdir", proc_dir );
/proc/topdir/bottomdir 폴더가 생성 됩니다.
자 그럼 proc 파일을 생성하겠습니다.
proc 파일은 create_proc_entry 함수를 이용해서 만듭니다.
702struct proc_dir_entry *create_proc_entry(const char *name, umode_t mode, 703 struct proc_dir_entry *parent) 704{ 705 struct proc_dir_entry *ent; 706 nlink_t nlink; 707 708 if (S_ISDIR(mode)) { 709 if ((mode & S_IALLUGO) == 0) 710 mode |= S_IRUGO | S_IXUGO; 711 nlink = 2; 712 } else { 713 if ((mode & S_IFMT) == 0) 714 mode |= S_IFREG; 715 if ((mode & S_IALLUGO) == 0) 716 mode |= S_IRUGO; 717 nlink = 1; 718 } 719 720 ent = __proc_create(&parent, name, mode, nlink); 721 if (ent) { 722 if (proc_register(parent, ent) < 0) { 723 kfree(ent); 724 ent = NULL; 725 } 726 } 727 return ent; 728} 729EXPORT_SYMBOL(create_proc_entry);
여기는 인자가 3개 들어갑니다 아까와 같이 이름, 상위 폴더의 proc_dir_entry 이 들어가고
둘 사이에 file의 속성을 정하는 mode가 들어 갑니다.
사용 방법은 폴더 만들 때와 별로 달라 진것은 없습니다.
struct proc_dir_entry * proc_file = NULL;
proc_file = create_proc_entry("testfile", S_IFREG | S_IRWXU, 0);
위와 같이 만들면 /proc 밑에 testfile 이 생성 됩니다.
위에 준 옵션은 S_IFREG 는 일반 파일 속성으로 파일을 생성하고,
S_IRWXU 는 소유가의 읽고 쓰기 접근이 가능하도록 한것입니다.
폴더 아래에 만들 경우에는
struct proc_dir_entry * proc_file2 = NULL;
proc_file2 = create_proc_entry("testfile", S_IFREG | S_IRWXU, proc_dir);
/proc/topdir/testfile 이 생성됩니다.
자 그럼 마지막으로 proc 파일을 삭제하는 함수를 알아 보겠습니다.
784void remove_proc_entry(const char *name, struct proc_dir_entry *parent) 785{ 786 struct proc_dir_entry **p; 787 struct proc_dir_entry *de = NULL; 788 const char *fn = name; 789 unsigned int len; 790 791 spin_lock(&proc_subdir_lock); 792 if (__xlate_proc_name(name, &parent, &fn) != 0) { 793 spin_unlock(&proc_subdir_lock); 794 return; 795 } 796 len = strlen(fn); 797 798 for (p = &parent->subdir; *p; p=&(*p)->next ) { 799 if (proc_match(len, fn, *p)) { 800 de = *p; 801 *p = de->next; 802 de->next = NULL; 803 break; 804 } 805 } 806 spin_unlock(&proc_subdir_lock); 807 if (!de) { 808 WARN(1, "name '%s'\n", name); 809 return; 810 } 811 812 spin_lock(&de->pde_unload_lock); 813 /* 814 * Stop accepting new callers into module. If you're 815 * dynamically allocating ->proc_fops, save a pointer somewhere. 816 */ 817 de->proc_fops = NULL; 818 /* Wait until all existing callers into module are done. */ 819 if (de->pde_users > 0) { 820 DECLARE_COMPLETION_ONSTACK(c); 821 822 if (!de->pde_unload_completion) 823 de->pde_unload_completion = &c; 824 825 spin_unlock(&de->pde_unload_lock); 826 827 wait_for_completion(de->pde_unload_completion); 828 829 spin_lock(&de->pde_unload_lock); 830 } 831 832 while (!list_empty(&de->pde_openers)) { 833 struct pde_opener *pdeo; 834 835 pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh); 836 list_del(&pdeo->lh); 837 spin_unlock(&de->pde_unload_lock); 838 pdeo->release(pdeo->inode, pdeo->file); 839 kfree(pdeo); 840 spin_lock(&de->pde_unload_lock); 841 } 842 spin_unlock(&de->pde_unload_lock); 843 844 if (S_ISDIR(de->mode)) 845 parent->nlink--; 846 de->nlink = 0; 847 WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory " 848 "'%s/%s', leaking at least '%s'\n", __func__, 849 de->parent->name, de->name, de->subdir->name); 850 pde_put(de); 851} 852EXPORT_SYMBOL(remove_proc_entry);
여기도 2개의 인자가 들어 갑니다.
먼저 파일의 이름과 어떤 위치에 있는 파일인지 알기위한 상위 proc_dir_entry입니다.
(폴더 만들때 넣었던 인자와 같습니다 ㅎㅎ)
remove_proc_entry("testfile", 0);
remove_proc_entry("testfile", proc_dir);
remove_proc_entry("bottomdir", proc_dir);
remove_proc_entry("topdir", 0);
(폴더 만들때 넣었던 인자와 같습니다 ㅎㅎ)
순서대로 먼저 /proc/testfile 을 삭제하였고
/proc/topdir/testfile 을 삭제, /proc/topdir/bottomdir 을 삭제, 마지막으로 /proc/topdir 을 삭제하였습니다.
proc 파일을 만들고 삭제하는것은 별로 어려운 것은 없었습니다.
그럼 오늘도 여기까지!!
다음시간에 만나요~