I have a problem that confused me for a week. I want someone to help me. I wrote a simple char device module, insmod
it into the kernel and mknod
a char file under /dev
. I see it after I insmod
it on cat /proc/devices
. But there is an error when I open this char device file.
My char device code:
#include <linux/module.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/cdev.h> #include <asm/io.h> #include <asm/system.h> #include <asm/uaccess.h> #define CALL_DEV_NAME "mn2" #define CALL_DEV_MAJOR 230 struct cdev cdev; MODULE_LICENSE("GPL"); int call_open(struct inode *inode,struct file *filp){ int num=MINOR(inode->i_rdev); printk("call open minor is:%d \n",num); return 0; } static struct file_operations call_fops={ .owner=THIS_MODULE, .open=call_open, }; int call_init(void){ int result; printk("call call_init \n"); result=register_chrdev_region(MKDEV(CALL_DEV_MAJOR,0), 1,CALL_DEV_NAME); if(result<0){ printk("registerfail \n"); return result; } cdev_init(&cdev,&call_fops); cdev.ops=&call_fops; cdev.owner=THIS_MODULE; cdev_add(&cdev,MKDEV(CALL_DEV_MAJOR,0),1); return 0; } void call_exit(void){ printk("call call_exit \n"); unregister_chrdev(CALL_DEV_MAJOR,CALL_DEV_NAME); } module_init(call_init); module_exit(call_exit);
test code:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <fcntl.h> int main(){ FILE *fd; fd=fopen("/dev/mn2","r+"); if(fd==NULL) printf("fail\n"); }
My Makefile:
ifneq ($(KERNELRELEASE),) obj-m := mn2.o else KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order endif
The command I use is:
make insmod mn2.ko
then I see mn2
in /proc/devices
mknod mn2 c 230 0
as well as the mn2
file under /dev
But after I compiled test.c with gcc test.c -o test
and run the test, I always get the fail
world.
Can you help me identify my mistake?
source share