該程式是一點點累加上來的,一開始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 ######################################