除了使用mknod工具建立Symbloic Link之外,字元驅動程式也可以自行建立這個Symbolic Link
建立步驟:
1. alloc_chrdev_region() 2. __class_create() 3. device_create() 4. cdev_init() 5. cdev_add()
釋放步驟:
1. device_destroy() 2. cdev_del() 3. class_destroy() 4. unregister_chrdev_region()
ldd.S
.global init_module .global cleanup_module .section .modinfo, "ae" __UNIQUE_ID_0: .asciz "license=GPL" __UNIQUE_ID_1: .asciz "author=Steward Fu" __UNIQUE_ID_2: .asciz "description=Linux Driver" .equ cdev.kobj, 0 .equ cdev.owner, 36 .equ cdev.ops, 40 .equ cdev.list, 44 .equ cdev.dev, 52 .equ cdev.count, 56 .struct 0 cdev_s: c0: .struct . + 36 c1: .struct . + 4 c2: .struct . + 4 c3: .struct . + 8 c4: .struct . + 4 c5: .struct . + 4 cdev_e: cdev_l = cdev_e - cdev_s .equ file_operations.owner, 0 .equ file_operations.llseek, 4 .equ file_operations.read, 8 .equ file_operations.write, 12 .equ file_operations.read_iter, 16 .equ file_operations.write_iter, 20 .equ file_operations.iterate, 24 .equ file_operations.iterate_shared, 28 .equ file_operations.poll, 32 .equ file_operations.unlocked_ioctl, 36 .equ file_operations.compat_ioctl, 40 .equ file_operations.mmap, 44 .equ file_operations.open, 48 .equ file_operations.flush, 52 .equ file_operations.release, 56 .equ file_operations.fsync, 60 .equ file_operations.fasync, 64 .equ file_operations.lock, 68 .equ file_operations.sendpage, 72 .equ file_operations.get_unmapped_area, 76 .equ file_operations.check_flags, 80 .equ file_operations.setfl, 84 .equ file_operations.flock, 88 .equ file_operations.splice_write, 92 .equ file_operations.splice_read, 96 .equ file_operations.setlease, 100 .equ file_operations.fallocate, 104 .equ file_operations.show_fdinfo, 108 .equ file_operations.mmap_capabilities, 112 .equ file_operations.copy_file_range, 116 .equ file_operations.clone_file_range, 120 .equ file_operations.dedupe_file_range, 124 .struct 0 file_operations_s: i0: .struct . + 4 i1: .struct . + 4 i2: .struct . + 4 i3: .struct . + 4 i4: .struct . + 4 i5: .struct . + 4 i6: .struct . + 4 i7: .struct . + 4 i8: .struct . + 4 i9: .struct . + 4 i10: .struct . + 4 i11: .struct . + 4 i12: .struct . + 4 i13: .struct . + 4 i14: .struct . + 4 i15: .struct . + 4 i16: .struct . + 4 i17: .struct . + 4 i18: .struct . + 4 i19: .struct . + 4 i20: .struct . + 4 i21: .struct . + 4 i22: .struct . + 4 i23: .struct . + 4 i24: .struct . + 4 i25: .struct . + 4 i26: .struct . + 4 i27: .struct . + 4 i28: .struct . + 4 i29: .struct . + 4 i30: .struct . + 4 i31: .struct . + 4 file_operations_e: file_operations_l = file_operations_e - file_operations_s .section .data base: .dcb 4 mycdev: .space cdev_l myfops: .space file_operations_l chr_name: .asciz "myfile" open_msg: .asciz "myopen\n" close_msg: .asciz "myclose\n" myclass: .dcb 4 .align 2 .section .text myopen: push {lr} ldr r0, =open_msg bl printk mov r0, #0 pop {pc} myclose: push {lr} ldr r0, =close_msg bl printk mov r0, #0 pop {pc} init_module: push {r4, r5, lr} ldr r0, =myfops add r1, r0, #file_operations.open ldr r2, =myopen str r2, [r1] add r1, r0, #file_operations.release ldr r2, =myclose str r2, [r1] ldr r0, =base mov r1, #0 mov r2, #1 ldr r3, =chr_name bl alloc_chrdev_region ldr r4, =base mov r0, #0 ldr r1, =chr_name ldr r2, =myclass bl __class_create ldr r1, =myclass str r0, [r1] mov r1, #0 ldr r2, [r4] mov r3, #0 ldr r5, =chr_name push {r5} bl device_create pop {r5} ldr r0, =mycdev ldr r1, =myfops bl cdev_init ldr r0, =mycdev ldr r1, [r4] mov r2, #1 bl cdev_add mov r0, #0 pop {r4, r5, pc} cleanup_module: push {lr} ldr r0, =myclass ldr r0, [r0] ldr r1, =base ldr r1, [r1] bl device_destroy ldr r0, =mycdev bl cdev_del ldr r0, =myclass ldr r0, [r0] bl class_destroy ldr r0, =base ldr r0, [r0] mov r1, #1 bl unregister_chrdev_region pop {pc} .end
init_module: 建立字元驅動程式
myopen: 對應User Application的open()
myclose: 對應User Application的close()
cleanup_module: 刪除字元驅動程式
安裝驅動
# insmod /boot/main.ko
由於使用class device,因此,Symbolic已經建立完成,不再需要使用mknod建立
# ls -al /dev/myfile crw-r--r-- 1 root root 243, 0 Jan 1 00:00 /dev/myfile
開啟裝置
# echo "" > /dev/myfile myopen sh: write error: Invalid argument myclose