panda.jpg 


안녕하세요 판다 이우영입니다.


이번주는 태풍이 한바탕 하고 지나갔는데요 다들 피해 없으셨으면 좋겠습니다.


그럼 먼저 복습!


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 파일을 만들고 삭제하는것은 별로 어려운 것은 없었습니다.

그럼 오늘도 여기까지!!

다음시간에 만나요~