file_operations 구조체에 관하여...

cjy1126의 이미지

리눅스 커널 프로그래밍 책에나온 디바이스 드라이버 모듈 프로그래밍을 하는데, 의문점이 있어서 질문올립니다.

책에 나온 mydrv.c 파일입니다.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
                                                                                
#define DEVICE_NAME "mydrv"
#define MYDRV_MAJOR 250
                                                                                
static int mydrv_open(struct inode *inode, struct file *file)
{
        if(MAJOR(inode->i_rdev) != MYDRV_MAJOR)
                return -1;
        MOD_INC_USE_COUNT;
        return 0;
}
                                                                                
static int mydrv_release(struct inode *inode, struct file *file)
{
        if(MAJOR(inode->i_rdev) != MYDRV_MAJOR)
                return -1;
        MOD_DEC_USE_COUNT;
        return 0;
}

static ssize_t mydrv_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
        printk("mydrv_read is invoked\n");
        return(0);
}
                                                                                
static ssize_t mydrv_write(struct file *file, char *buf, size_t count, loff_t *ppos)
{
        printk("mydrv_write is invoked\n");
        return(0);
}
                                                                                
struct file_operations mydrv_fops = {
        NULL, mydrv_read, mydrv_write, NULL, NULL, NULL, NULL,
        mydrv_open, NULL, mydrv_release, NULL, NULL, NULL, NULL
};

int init_module(void)
{
        int result;
        result = register_chrdev(MYDRV_MAJOR, "mydrv", &mydrv_fops);
        if(result<0)
        {
                printk("mydrv: %d character device driver can't be registered\n", MYDRV_MAJOR);
                return result;
        }
        return(0);
}
                                                                                
void cleanup_module(void)
{
        unregister_chrdev(MYDRV_MAJOR, "mydrv");
}

이 파일을 컴파일하면 계속 아래와같은 경고가 나옵니다.

gcc -D__KERNEL__ -D_LINUX -DMODULE -c mydrv.c
mydrv.c:38: warning: initialization from incompatible pointer type

경고가 나오는 부분입니다.

struct file_operations mydrv_fops = {
        NULL, mydrv_read, mydrv_write, NULL, NULL, NULL, NULL,
        mydrv_open, NULL, mydrv_release, NULL, NULL, NULL, NULL
};

인터넷과 다른 책을 찾아서 제 linux/fs.h에 있는 file_operations의 인자값과 맞춰서 아래와 같이 고쳤는데도 계속 같은 경고가 나옵니다.

struct file_operations mydrv_fops = {
        NULL, NULL, mydrv_read, mydrv_write, NULL, NULL, NULL, NULL,
        mydrv_open, NULL, mydrv_release, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};

제 linux/fs.h입니다.

struct file_operations {
        struct module *owner;
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char *, size_t, loff_t *);
        ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
        int (*fsync) (struct file *, struct dentry *, int datasync);
        int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
        ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
        ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
        ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
};

제 linux/fs.h구조체대로 숫자를 맞춰줘야 하지않나요?

어떻게해줘야 경고를 잡을 수 있는지 모르겠습니다.

제대로 실행은되는데, 경고가 눈에 거슬리네요.

또 한번은 계속 수정하다가 module테스트 프로그램을 돌리면 모듈의 use by가 -1씩 증가되어 rmmod를하면 module이 busy해서 종료할 수가 없습니다.

결국 리붓으로 해결했지만... 이럴때 강제로 모듈을 죽이는 방법이 없는지 알고싶습니다.

연말 잘보내시고, 새해에는 좋은 일들만 가득하시길...

ch3cooh의 이미지

리눅스 커널 프로그래밍 책들이 Kernel 2.2대를 기준으로 프로그램이 되어 있어 현재 많이 사용하고 있는 Kernel2.4에서는 Kernel Programming 사용형식이 조금 다른것으로 알고 있습니다.

그 대표적인 것이 int init_module(void)와 void cleanup_module(void)이 module_init(module_begin); module_exit(module_end);으로 매크로화 시킨 것으로 압니다. 2.4의 사용법을 익히신 후에 프로그램을 조금만 수정하면.. 정상적으로 동작 할것 같네요! ^^

은영신랑의 이미지

struct file_operations mydrv_fops = { 
        NULL, mydrv_read, mydrv_write, NULL, NULL, NULL, NULL, 
        mydrv_open, NULL, mydrv_release, NULL, NULL, NULL, NULL 
}; 

을 이렇게 한번 고쳐보세요.

 struct file_operations mydrv_fops = {
                  read:  mydrv_read,
                  write: mydrv_write,
                  open: mydrv_open,
                  release: mydrv_release
  };