该程序是一点点累加上来的,一开始file_operations 中只实现了read()及open()函数进行测试只要这一步测试通过了后面的添砖加瓦就相对容易了很多,后来成功后添加write(),ioctl()函数;
该驱动模块相对简单,不过我也是花了好几个小时才算调试成功。该模块可以编译后直接插入当前正在跑的Ubuntu中测试运行不过
驱动模块中的printk()信息不会在终端上显示,它是输入到了/var/lo/messages文件中。可以使用
tail -f /var/log/messages 来进行实时查看驱动通过printk()函数打印的信息。
依次贴出了helloworld.c(driver), Makefile, app_helloworld.c(app)
直接make, 即可生成可插入当前计算机的模块
然后insmod (信息可在/var/log/messages查询)装入模块
在mknod 创建设备节点,这样就可以在app中使用open()打开进行测试了。
在驱动的编写中主要是编译模块时有问题,可能是所利用的内核配置有问题,也可能是自己的驱动有问题,如使用了野指针造成段错误等。
程序功能的话就是驱动给用户每次一个字符【a-z】【A-Z】或【0-9】通过ioctl实现的什么时候送什么字符。然后用户空间将该值加一后在传到内核空间,并打印。
######helloworld.c 驱动程序 #######################################
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/module.h>
4 #include <linux/fs.h>
5 #include <linux/cdev.h>
6 #include <asm/uaccess.h>
7 #include <linux/mm.h>
8 #include <asm/io.h>
9 #include <asm/system.h>
10
11 MODULE_LICENSE("Dual BSD/GPL");
12 #define hello_major 234
13 #define hello_minor 0
14 #define number_of_device 1
15
16 #define LetterU 1
17 #define LetterD 2
18 #define Dig 3
19 static char toUser = 'a';
20
21 static hello_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long a rg)
22 {
23 switch (cmd)
24 {
25 case LetterU:
26 toUser = 'A';
27 printk("get ioctl from user to use 'A'/n");
28 break;
29
30 case LetterD:
31 toUser = 'a';
32 printk("get ioctl from user to use 'a'/n");
33 break;
34
35 case Dig:
36 toUser ='1';
37 printk("get ioctl from user to use dig'1'/n");
38 break;
39
40 default:
41 printk("get invalid ioctl from user/n");
42 }
43 return 0;
44 }
45 int hello_open(struct inode *pi, struct file *pf)
46 {
47 printk("system call open success firstdriver/n");
48 return 0;
49 }
50 ssize_t hello_read(struct file *filp, char __user *buf, ssize_t count, loff_t *f_pos )
51 { printk("in system call read firstdriver/n");
52 copy_to_user(buf, &toUser, 1);
53
54 toUser++;
55 return 1;
56 }
57
58 ssize_t hello_write(struct file *filp, char __user *buf, ssize_t count, loff_t *f_pos)
59 {
60 char frUser;
61 copy_from_user(&frUser, buf, count);
62 printk("value from user space is %c/n", frUser);
63 return count;
64 }
65
66 struct file_operations hello_ops=
67 {
68 .owner = THIS_MODULE,
69 .open = hello_open,
70 .read = hello_read,
71 .write = hello_write,
72 .ioctl = hello_ioctl,
73
74 };
75
76 static int __init hello_init(void)
77 {
78 int result;
79 result = register_chrdev(hello_major, "hello", &hello_ops);
80 if (result <0)
81 {
82 printk(KERN_WARNING "can'r register the character device/n");
83 return result;
84 }
85
86
87 printk( KERN_INFO "register character done!/n");
88 return 0;
89 }
90
91 static void __exit hello_exit(void)
92 {
93 unregister_chrdev(hello_major, "hello");
94 printk( "good bye from first driver/n");
95 }
96 module_init(hello_init);
97 module_exit(hello_exit);
########################end driver############################################
###############################Makefile##############################
KER_DIR := /usr/src/linux-headers-`uname -r`/
MOD_DIR := `pwd`
obj := helloworld.o
modules:
$(MAKE) -C ${KER_DIR} M=${MOD_DIR} modules
######################################end Makefile #####################
###########测试应用程序app_helloworld.c###################################
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <sys/stat.h>
6 #include <sys/ioctl.h>
7
8 #define LetterU 1
9 #define LetterD 2
10 #define Dig 3
11
12 int main(void)
13 {
14 int fd;
15 fd = open("/dev/hello", O_RDWR);
16 if (fd < 0)
17 {
18 printf("can't open file/n");
19 return -1;
20 }
21
22 printf("the data from kernel will be held evenif app exit so reset the kernel data/n" );
23 ioctl(fd, LetterD, NULL);
24
25 char buf = '0';
26
27 int rb;
28 static int count = 0;
29
30 while (1)
31 {
32 rb = read(fd, &buf, 1);
33 count++;
34
35 if (count > 10)
36 {
37 static turn = 0;
38 turn ++;
39 count = 0;
40 switch (turn %= 3)
41 {
42 printf("the turn3 =%d /n", turn);
43 case LetterU:
44 ioctl(fd, LetterU, NULL);
45 break;
46
47 case LetterD:
48 ioctl(fd, LetterD, NULL);
49 break;
50
51 case Dig:
52 ioctl(fd, Dig, NULL);
53 }
54 }
55
56 printf("the value return from kernel is %c /n", buf);
57 sleep(2);
58 buf++;
59 printf("write to kernel is %c/n", buf);
60 rb = write(fd, &buf, 1);
61 sleep(1);
62 }
63
64 return 0;
65 }
#######################end of app ######################################