Linux驱动修炼之道
module.h包含可装载模块需要的大量符号和函数定义,包含init.h的目的是指定初始化和清除代码,struct file是在<linux/fs.h>中定义的。
注册字符设备使用
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
移除字符设备使用
int unregister_chrdev(unsigned int major, const char *name);
init函数是在insmod时被调用的,exit函数是在rmmod时被调用的。
使用命令 cat /proc/devices 可以查看设备的主设备号。
如果内核没有为我们生成设备文件,我们需要手动生成:
mknod /dev/led_driver c 234 0
__init标记表示该函数只在初始化期间使用,在模块被装载后,模块装载器就会将初始化函数扔掉,这样可将函数占用的内存释放出来。
__exit修饰的函数只在模块卸载或系统关闭时被调用,如果模块被直接内嵌到内核中,或者内核的配置不允许卸载模块,则被标记为__exit的模块将被简单丢弃。
驱动程序:
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #define LED_MAJOR 234
- #define DEVICE_NAME "led_driver"
- static unsigned long led_table[]={
- S3C2410_GPF3,
- S3C2410_GPF4,
- S3C2410_GPF5,
- S3C2410_GPF6,
- };
- static unsigned long led_cfg_table[]={
- S3C2410_GPF3_OUTP,
- S3C2410_GPF4_OUTP,
- S3C2410_GPF5_OUTP,
- S3C2410_GPF6_OUTP,
- };
- int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg){
- switch(cmd){
- case 0:
- s3c2410_gpio_setpin(led_table[0],0);
- s3c2410_gpio_setpin(led_table[1],1);
- s3c2410_gpio_setpin(led_table[2],1);
- s3c2410_gpio_setpin(led_table[3],1);
- break;
- case 1:
- s3c2410_gpio_setpin(led_table[0],1);
- s3c2410_gpio_setpin(led_table[1],0);
- s3c2410_gpio_setpin(led_table[2],1);
- s3c2410_gpio_setpin(led_table[3],1);
- break;
- case 2:
- s3c2410_gpio_setpin(led_table[0],1);
- s3c2410_gpio_setpin(led_table[1],1);
- s3c2410_gpio_setpin(led_table[2],0);
- s3c2410_gpio_setpin(led_table[3],1);
- break;
- case 3:
- s3c2410_gpio_setpin(led_table[0],1);
- s3c2410_gpio_setpin(led_table[1],1);
- s3c2410_gpio_setpin(led_table[2],1);
- s3c2410_gpio_setpin(led_table[3],0);
- break;
- default:
- return -EINVAL;
- break;
- }
- return 0;
- }
- struct file_operations led_ops = {
- .owner = THIS_MODULE,
- .ioctl = led_ioctl,
- };
- static int __init init_led(void)
- {
- int i, ret;
- ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&led_ops);
- if(ret < 0){
- printk(DEVICE_NAME, "can't register major number\n");
- }
- for(i = 0; i < 4; i++){
- s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);
- s3c2410_gpio_setpin(led_table[i],1);
- }
- printk(DEVICE_NAME "initialized\n");
- return 0;
- }
- static void __exit exit_led(void)
- {
- unregister_chrdev(LED_MAJOR,DEVICE_NAME);
- }
- module_init(init_led);
- module_exit(exit_led);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("liwanpeng");
测试程序:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <unistd.h>
- int main(){
- int fd, ret;
- char *i;
- fd = open("/dev/led_driver",0);
- if(fd < 0){
- printf("open device error");
- }
- else{
- while(1){
- ioctl(fd,0);
- printf("led0 is on!\n");
- sleep(1);
- ioctl(fd,1);
- printf("led1 is on!\n");
- sleep(1);
- ioctl(fd,2);
- printf("led2 is on!\n");
- sleep(1);
- ioctl(fd,3);
- printf("led3 is on!\n");
- sleep(1);
- }
- close(fd);
- }
- return 0;
- }
效果:此时LED灯也轮流闪烁。
相关推荐
IT之家 2020-03-11
graseed 2020-10-28
zbkyumlei 2020-10-12
SXIAOYI 2020-09-16
jinhao 2020-09-07
impress 2020-08-26
liuqipao 2020-07-07
淡风wisdon大大 2020-06-06
yoohsummer 2020-06-01
chenjia00 2020-05-29
baike 2020-05-19
扭来不叫牛奶 2020-05-08
hxmilyy 2020-05-11
黎豆子 2020-05-07
xiongweiwei00 2020-04-29
Cypress 2020-04-25
冰蝶 2020-04-20