除了使用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