Android 구조 분석의 Android 드라이버 개발
14565 단어 Android 구조 분석
블 로그:http://blog.csdn.net/liuhaoyutz
Android 버 전: 2.3.7r1
Linux 커 널 버 전: android - goldfish - 2.6.29
본 고 는 어떻게 안 드 로 이 드 드라이버 를 개발 하고 테스트 하 는 지 를 소개 한다.
1. Android 드라이버 개발
Android 는 Linux 기반 이기 때문에 Android 드라이버 개발 방법 은 Linux 드라이버 개발 방법 과 같 습 니 다.
다음은 하나의 예 프로그램 을 통 해 안 드 로 이 드 드라이버 의 개발 을 익 혀 보 겠 습 니 다. 여 기 는 간단 한 설명 일 뿐 입 니 다. 만약 에 리 눅 스 드라이버 개발 에 대해 서도 잘 모 르 면 리 눅 스 Device Driver 나 참고 한 제 블 로그 의 시리즈 문장 을 배 울 수 있 습 니 다.
우선 Android 커 널 소스 의 drivers 디 렉 터 리 에 새 디 렉 터 리 example 를 만 듭 니 다. 드라이버 소스 코드 는 이 디 렉 터 리 에 놓 여 있 습 니 다.
# mkdir drivers/example
# cd drivers/example
example. h 파일 을 만 듭 니 다. 그 내용 은 다음 과 같 습 니 다.
1#ifndef _EXAMPLE_H_
2#define _EXAMPLE_H_
3
4#include
5#include
6
7#define EXAMPLE_DEVICE_NODE_NAME "example"
8#define EXAMPLE_DEVICE_FILE_NAME "example"
9#define EXAMPLE_DEVICE_PROC_NAME "example"
10#define EXAMPLE_DEVICE_CLASS_NAME "example"
11#define EXAMPLE_MAJOR 0
12
13struct example_dev {
14 struct semaphore sem;
15 struct cdev cdev;
16 int val;
17};
18
19#endif
이 헤더 파일 은 드라이버 에 사용 할 매크로 를 정의 하고 장치 구조 체 example 을 정의 합 니 다.dev, 이 구조 체 의 구성원 sem 은 장치 에 대한 동기 화 접근 을 보장 하 는 데 사 용 됩 니 다. cdev 는 이 장 치 는 Linux 장치 구동 의 문자 장치 이 고, val 은 이 장치 의 레지스터 를 대표 합 니 다. 이 드라이버 의 역할 은 사용자 층 응용 프로그램 에 이 val 레지스터 를 읽 고 쓰 는 방법 을 제공 하 는 것 입 니 다.
example. c 파일 을 만 듭 니 다. 그 내용 은 다음 과 같 습 니 다.
1#include
2#include
3#include
4#include
5#include
6#include
7#include
8
9#include "example.h"
10
11static int example_major = EXAMPLE_MAJOR;
12static int example_minor = 0;
13
14static struct class* example_class = NULL;
15static struct example_dev* example_dev = NULL;
16
17module_param(example_major, int, S_IRUGO);
18module_param(example_minor, int, S_IRUGO);
19
20static int example_open(struct inode* inode, struct file* filp)
21{
22 struct example_dev* dev;
23
24 /*
25 * example_dev, filp , 。
26 */
27 dev = container_of(inode->i_cdev, struct example_dev, cdev);
28 filp->private_data = dev;
29
30 return 0;
31}
32
33static int example_release(struct inode* inode, struct file* filp)
34{
35 return 0;
36}
37
38static ssize_t example_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos)
39{
40 struct example_dev* dev = filp->private_data;
41 ssize_t retval = 0;
42
43 /*
44 *
45 */
46 if(down_interruptible(&(dev->sem)))
47 return -ERESTARTSYS;
48
49 if(count < sizeof(dev->val))
50 goto out;
51
52 /*
53 * 。
54 */
55 if(copy_to_user(buf, &(dev->val), sizeof(dev->val)))
56 {
57 retval = -EFAULT;
58 goto out;
59 }
60
61 retval = sizeof(dev->val);
62
63out:
64 /*
65 *
66 */
67 up(&(dev->sem));
68 return retval;
69}
70
71static ssize_t example_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos)
72{
73 struct example_dev* dev = filp->private_data;
74 ssize_t retval = 0;
75
76 /*
77 *
78 */
79 if(down_interruptible(&(dev->sem)))
80 return -ERESTARTSYS;
81
82 if(count != sizeof(dev->val))
83 goto out;
84
85 /*
86 * 。
87 */
88 if(copy_from_user(&(dev->val), buf, count))
89 {
90 retval = -EFAULT;
91 goto out;
92 }
93
94 retval = sizeof(dev->val);
95
96out:
97 /*
98 *
99 */
100 up(&(dev->sem));
101 return retval;
102}
103
104/*
105 *
106 */
107static struct file_operations example_fops =
108{
109 .owner = THIS_MODULE,
110 .open = example_open,
111 .release = example_release,
112 .read = example_read,
113 .write = example_write,
114};
115
116
117/*
118 * 。
119 */
120static ssize_t __example_get_val(struct example_dev* dev, char* buf)
121{
122 int val = 0;
123
124 if(down_interruptible(&(dev->sem)))
125 return -ERESTARTSYS;
126
127 val = dev->val;
128 up(&(dev->sem));
129
130 return snprintf(buf, 30, "%d
", val);
131}
132
133/*
134 * 。
135 */
136static ssize_t __example_set_val(struct example_dev* dev, const char* buf, size_t count)
137{
138 int val = 0;
139
140 val = (int)simple_strtol(buf, NULL, 10);
141
142 if(down_interruptible(&(dev->sem)))
143 return -ERESTARTSYS;
144
145 dev->val = val;
146 up(&(dev->sem));
147
148 return count;
149}
150
151/*
152 * 。
153 */
154static ssize_t example_val_show(struct device* dev, struct device_attribute* attr, char* buf)
155{
156 struct example_dev* hdev = (struct example_dev*)dev_get_drvdata(dev);
157
158 return __example_get_val(hdev, buf);
159}
160
161/*
162 * 。
163 */
164static ssize_t example_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
165{
166 struct example_dev* hdev = (struct example_dev*)dev_get_drvdata(dev);
167
168 return __example_set_val(hdev, buf, count);
169}
170
171/*
172 * DEVICE_ATTR dev_attr_val。
173 * "val“, example_val_show example_val_store。
174 */
175static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, example_val_show, example_val_store);
176
177/*
178 * /proc 。
179 */
180static ssize_t example_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data)
181{
182 if(off > 0)
183 {
184 *eof = 1;
185 return 0;
186 }
187
188 return __example_get_val(example_dev, page);
189}
190
191/*
192 * /proc 。
193 */
194static ssize_t example_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data)
195{
196 int err = 0;
197 char* page = NULL;
198
199 if(len > PAGE_SIZE)
200 {
201 printk(KERN_ALERT"The buff is too large: %lu.
", len);
202 return -EFAULT;
203 }
204
205 page = (char*)__get_free_page(GFP_KERNEL);
206 if(!page)
207 {
208 printk(KERN_ALERT"Failed to alloc page.
");
209 return -ENOMEM;
210 }
211
212 if(copy_from_user(page, buff, len))
213 {
214 printk(KERN_ALERT"Failed to copy buff from user.
");
215 err = -EFAULT;
216 goto out;
217 }
218
219 err = __example_set_val(example_dev, page, len);
220
221out:
222 free_page((unsigned long)page);
223 return err;
224}
225
226/*
227 * /proc
228 */
229static void example_create_proc(void)
230{
231 struct proc_dir_entry* entry;
232
233 entry = create_proc_entry(EXAMPLE_DEVICE_PROC_NAME, 0, NULL);
234 if(entry)
235 {
236 entry->owner = THIS_MODULE;
237 entry->read_proc = example_proc_read;
238 entry->write_proc = example_proc_write;
239 }
240}
241
242/*
243 * /proc
244 */
245static void example_remove_proc(void)
246{
247 remove_proc_entry(EXAMPLE_DEVICE_PROC_NAME, NULL);
248}
249
250/*
251 * example_dev。
252 */
253static int __example_setup_dev(struct example_dev* dev)
254{
255 int retval;
256
257 /*
258 *
259 */
260 dev_t devno = MKDEV(example_major, example_minor);
261
262 /*
263 * 0。
264 */
265 memset(dev, 0, sizeof(struct example_dev));
266
267 /*
268 * cdev , owner 。
269 */
270 cdev_init(&(dev->cdev), &example_fops);
271 dev->cdev.owner = THIS_MODULE;
272 dev->cdev.ops = &example_fops;
273
274 /*
275 * cdev_add, 。
276 */
277 retval = cdev_add(&(dev->cdev),devno, 1);
278 if(retval)
279 {
280 return retval;
281 }
282
283 /*
284 *
285 */
286 init_MUTEX(&(dev->sem));
287
288 /*
289 * val 0
290 */
291 dev->val = 0;
292
293 return 0;
294}
295
296/*
297 * 。
298 */
299static int __init example_init(void)
300{
301 int retval = -1;
302 dev_t dev = 0;
303 struct device* device = NULL;
304
305 printk(KERN_ALERT"Initializing example device.
");
306
307 /*
308 * , example_major 0,
309 * register_chrdev_region 。
310 * , example_major 0,
311 * alloc_chrdev_region 。
312 */
313 if (example_major) {
314 dev = MKDEV(example_major, example_minor);
315 retval = register_chrdev_region(dev, 1, EXAMPLE_DEVICE_NODE_NAME);
316 } else {
317 retval = alloc_chrdev_region(&dev, example_minor, 1, EXAMPLE_DEVICE_NODE_NAME);
318 }
319 if (retval < 0) {
320 printk(KERN_WARNING "can't get example_major %d
", example_major);
321 goto fail;
322 }
323
324 /*
325 *
326 */
327 example_major = MAJOR(dev);
328 example_minor = MINOR(dev);
329
330 /*
331 * example_dev 。
332 */
333 example_dev = kmalloc(sizeof(struct example_dev), GFP_KERNEL);
334 if(!example_dev)
335 {
336 retval = -ENOMEM;
337 printk(KERN_ALERT"Failed to alloc example_dev.
");
338 goto unregister;
339 }
340
341 /*
342 * __example_setup_dev example_dev 。
343 */
344 retval = __example_setup_dev(example_dev);
345 if(retval)
346 {
347 printk(KERN_ALERT"Failed to setup dev: %d.
", retval);
348 goto cleanup;
349 }
350
351 /*
352 * example,class_create , /sys/class
353 * example 。
354 */
355 example_class = class_create(THIS_MODULE, EXAMPLE_DEVICE_CLASS_NAME);
356 if(IS_ERR(example_class))
357 {
358 retval = PTR_ERR(example_class);
359 printk(KERN_ALERT"Failed to create example class.
");
360 goto destroy_cdev;
361 }
362
363 /*
364 * ,device_create , /dev/example
365 * /sys/class/example/example 。
366 * device struct device, 。
367 */
368 device = device_create(example_class, NULL, dev, "%s", EXAMPLE_DEVICE_FILE_NAME);
369 if(IS_ERR(device))
370 {
371 retval = PTR_ERR(device);
372 printk(KERN_ALERT"Failed to create example device.");
373 goto destroy_class;
374 }
375
376 /*
377 * , dev_attr_val 。
378 */
379 retval = device_create_file(device, &dev_attr_val);
380 if(retval < 0)
381 {
382 printk(KERN_ALERT"Failed to create attribute val.");
383 goto destroy_device;
384 }
385
386 /*
387 * example_dev 。
388 */
389 dev_set_drvdata(device, example_dev);
390
391 /*
392 * proc 。
393 */
394 example_create_proc();
395
396 printk(KERN_ALERT"Succedded to initialize example device.
");
397 return 0;
398
399destroy_device:
400 device_destroy(example_class, dev);
401
402destroy_class:
403 class_destroy(example_class);
404
405destroy_cdev:
406 cdev_del(&(example_dev->cdev));
407
408cleanup:
409 kfree(example_dev);
410
411unregister:
412 unregister_chrdev_region(MKDEV(example_major, example_minor), 1);
413
414fail:
415 return retval;
416}
417
418/*
419 * 。
420 */
421static void __exit example_exit(void)
422{
423 dev_t dev = MKDEV(example_major, example_minor);
424
425 printk(KERN_ALERT"Destroy example device.
");
426
427 example_remove_proc();
428
429 if(example_class)
430 {
431 device_destroy(example_class, MKDEV(example_major, example_minor));
432 class_destroy(example_class);
433 }
434
435 if(example_dev)
436 {
437 cdev_del(&(example_dev->cdev));
438 kfree(example_dev);
439 }
440
441 unregister_chrdev_region(dev, 1);
442}
443
444MODULE_LICENSE("GPL");
445
446module_init(example_init);
447module_exit(example_exit);
코드 에 있 는 주석 이 상세 합 니 다. 여기 서 간단하게 말씀 드 리 겠 습 니 다.
20 - 114 줄, example 정의open、example_release、example_read、example_write 이 4 개의 함수, 그리고 이 4 개의 함 수 를 file 에 할당 합 니 다.operations 구조 체 변수 examplefops, 응용 프로그램 이 / dev / example 장치 노드 를 통 해 장 치 를 방문 할 때 이 몇 가지 함수 로 호출 됩 니 다.
117 - 175 줄 은 / sys / class / example / example / val 을 통 해 장 치 를 방문 할 때 호출 되 는 함 수 를 정의 합 니 다.
177 - 248 줄 은 / proc / example 를 통 해 장 치 를 방문 할 때 호출 해 야 할 함 수 를 정의 합 니 다.
원본 코드 가 있 습 니 다. 이 원본 코드 를 컴 파일 하 는 Makefile 을 만들어 야 합 니 다.
Makefile 내용 은 다음 과 같 습 니 다.
obj-y += example.o
왜 Makefile 은 이 줄 만 있 을 수 있 습 니까? LDD 3 29 페이지 의 소 개 를 참고 하 실 수 있 습 니 다. 또한 제 블 로그 글 인 LDD 3 소스 코드 분석의 hello. c 와 Makefile 템 플 릿 도 참고 하 실 수 있 습 니 다.
커 널 을 컴 파일 할 때 example 를 컴 파일 할 수 있 도록 커 널 에 새로운 드라이버 example 를 추가 했다 는 것 을 알려 야 합 니 다.커 널 을 알 리 는 방법 은 커 널 drivers 디 렉 터 리 의 Makefile 을 수정 하 는 것 입 니 다. 이 파일 의 마지막 에 한 마디 를 추가 하 는 것 입 니 다.
obj-y += example/
왜 이 한 마디 를 늘 리 면 커 널 에 알 릴 수 있 습 니까?이것 은 Linux 커 널 컴 파일 체제 가 결정 한 것 입 니 다. 분석 을 전개 하면 많은 내용 을 포함 할 것 입 니 다. 여기 서 자세히 설명 하지 않 겠 습 니 다.다 들 알 고 이렇게 고치 면 돼.
이상 의 작업 이 끝 난 후에 우 리 는 리 눅 스 커 널 을 다시 컴 파일 할 수 있 습 니 다. 커 널 루트 디 렉 터 리 로 돌아 가 다음 과 같은 명령 을 수행 할 수 있 습 니 다.
make
컴 파일 에 성공 한 후 얻 은 커 널 미 러 에는 우리 가 가입 한 example 드라이브 가 포함 되 어 있 습 니 다.
새로 추 가 된 example 드라이버 가 정상적으로 작 동 하 는 지 테스트 해 보 겠 습 니 다.
먼저 새로 컴 파일 된 Linux 커 널 로 Android 시 뮬 레이 터 를 시작 합 니 다.
# source build/envsetup.sh
# lunch
# emulator -kernel kernel/goldfish/arch/arm/boot/zImage
# adb shell
시스템 에 들 어가 면 example 드라이버 가 만 든 장치 노드: / dev / example, / proc / example 및 / sys / devices / virtual / example / example 디 렉 터 리 를 볼 수 있 습 니 다.
다음 명령 을 실행 합 니 다:
# cat /proc/example
0
# echo 5 > /proc/example
# cat /proc/example
5
볼 수 있 습 니 다. 우 리 는 / proc / example 노드 를 통 해 장치 레지스터 에 접근 할 수 있 습 니 다.
# cat /sys/class/example/example/val
5
# echo 6 > /sys/class/example/example/val
# cat /sys/class/example/example/val
6
볼 수 있 습 니 다. / sys / class / example / example / val 노드 를 통 해 장치 레지스터 에 접근 할 수 있 습 니 다.
또한 / dev / example 노드 를 통 해 장치 레지스터 에 접근 할 수 있 습 니 다. 다음 블 로그 에 서 는 C 프로그램 이 / dev / example 노드 를 통 해 장치 레지스터 에 접근 하 는 동시에 안 드 로 이 드 시스템 에서 C 프로그램 을 개발 하 는 절 차 를 보 여 줍 니 다.