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><br />#include <linux/fs.h><br />#include <linux/init.h><br />#include <mach/regs-gpio.h><br />#include <mach/hardware.h></p><p>#define LED_MAJOR 234<br />#define DEVICE_NAME "led_driver"</p><p>static unsigned long led_table[]={<br />S3C2410_GPF3,<br />S3C2410_GPF4,<br />S3C2410_GPF5,<br />S3C2410_GPF6,<br />};</p><p>static unsigned long led_cfg_table[]={<br />S3C2410_GPF3_OUTP,<br />S3C2410_GPF4_OUTP,<br />S3C2410_GPF5_OUTP,<br />S3C2410_GPF6_OUTP,<br />};</p><p>int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd , unsigned long arg){<br />switch(cmd){<br />case 0:<br />s3c2410_gpio_setpin(led_table[0],0);<br />s3c2410_gpio_setpin(led_table[1],1);<br />s3c2410_gpio_setpin(led_table[2],1);<br />s3c2410_gpio_setpin(led_table[3],1);<br />break;<br />case 1:<br />s3c2410_gpio_setpin(led_table[0],1);<br />s3c2410_gpio_setpin(led_table[1],0);<br />s3c2410_gpio_setpin(led_table[2],1);<br />s3c2410_gpio_setpin(led_table[3],1);<br />break;<br />case 2:<br />s3c2410_gpio_setpin(led_table[0],1);<br />s3c2410_gpio_setpin(led_table[1],1);<br />s3c2410_gpio_setpin(led_table[2],0);<br />s3c2410_gpio_setpin(led_table[3],1);<br />break;<br />case 3:<br />s3c2410_gpio_setpin(led_table[0],1);<br />s3c2410_gpio_setpin(led_table[1],1);<br />s3c2410_gpio_setpin(led_table[2],1);<br />s3c2410_gpio_setpin(led_table[3],0);<br />break;<br />default:<br />return -EINVAL;<br />break;<br />}<br />return 0;<br />} </p><p>struct file_operations led_ops = {<br />.owner = THIS_MODULE,<br />.ioctl = led_ioctl,<br />};</p><p>static int __init init_led(void)<br />{<br />int i, ret;<br />ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&led_ops);<br />if(ret < 0){<br />printk(DEVICE_NAME, "can't register major number/n");<br />}<br />for(i = 0; i < 4; i++){<br />s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);<br />s3c2410_gpio_setpin(led_table[i],1);<br />}<br />printk(DEVICE_NAME "initialized/n");<br />return 0;<br />}</p><p>static void __exit exit_led(void)<br />{<br />unregister_chrdev(LED_MAJOR,DEVICE_NAME);<br />}</p><p>module_init(init_led);<br />module_exit(exit_led);<br />MODULE_LICENSE("GPL");<br />MODULE_AUTHOR("liwanpeng");
測試程式:
#include <stdio.h><br />#include <stdlib.h><br />#include <string.h><br />#include <fcntl.h><br />#include <unistd.h></p><p>int main(){<br />int fd, ret;<br />char *i;<br />fd = open("/dev/led_driver",0);<br />if(fd < 0){<br />printf("open device error");<br />}<br />else{<br />while(1){<br />ioctl(fd,0);<br />printf("led0 is on!/n");<br />sleep(1);<br />ioctl(fd,1);<br />printf("led1 is on!/n");<br />sleep(1);<br />ioctl(fd,2);<br />printf("led2 is on!/n");<br />sleep(1);<br />ioctl(fd,3);<br />printf("led3 is on!/n");<br />sleep(1);<br />}<br />close(fd);<br />}<br />return 0;<br />}
效果:此時LED燈也輪流閃爍。