使用Linux越来越多,千头万绪,冥冥之中走上这条路.........................
程序暂时是在ubuntu系统中测试的.
首先写驱动程序:
#include#include #include #include #include #include #define DEVICE_NAME "m_driver03"/*static struct file_operations dev_fops={.owner = THIS_MODULE};static struct miscdevice misc={.minor=MISC_DYNAMIC_MINOR,.name=DEVICE_NAME,.fops=&dev_fops};*/static unsigned char mem[10000];static int written_count=0;static char read_flag='y';/*static int m_driver03_init(void){ int ret; ret=misc_register(&misc); printk("m_driver03_init;\n"); return 0;}*/static ssize_t m_driver03_read(struct file *file,char __user *buf,size_t count,loff_t *ppos){ printk("read function entrance !\n"); unsigned char temp[4]; temp[0]=written_count>>24; temp[1]=written_count>>16; temp[2]=written_count>>8; temp[3]=written_count; if(read_flag=='n'){ copy_to_user(buf,(void*)temp,4); printk("read count : %d\t\n",(int)written_count); read_flag='y'; return count; }else{ return 0; }}static ssize_t m_driver03_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos){ copy_from_user(mem,buf,count); read_flag='n'; printk("write function entrance !\n"); written_count=count; printk("written count : %d\n",(int)count); return count;}static struct file_operations dev_fops={.owner=THIS_MODULE,.read=m_driver03_read,.write=m_driver03_write};static struct miscdevice misc={.minor=MISC_DYNAMIC_MINOR,.name=DEVICE_NAME,.fops=&dev_fops};static __init int m_driver03_init(void){ int ret; ret=misc_register(&misc); printk("m_driver03_init;\n"); return 0;}static __exit void m_driver03_exit(void){ misc_deregister(&misc); printk("m_driver03_exit;\n");}module_init(m_driver03_init);module_exit(m_driver03_exit);MODULE_AUTHOR("stephen");MODULE_DESCRIPTION("show how to develop linux module!");MODULE_ALIAS("using linux module!");MODULE_LICENSE("GPL");
下面肢解上面各个部分:
<1> : 初始化时和退出时必须要的单元:
static __init int m_driver03_init(void){ int ret; ret=misc_register(&misc); printk("m_driver03_init;\n"); return 0;}
这一段初始化代码,只要编译后,在终端输入insmod module_name装载模块就会进行初始,其中:
ret=misc_register(&misc);
是向系统注册一个设备,misc是一个结构体变量名.
static struct miscdevice misc={.minor=MISC_DYNAMIC_MINOR,.name=DEVICE_NAME,.fops=&dev_fops};
其中minor是动态分配一个次设备ID,
name是设备名,包括路径,格式="/dev/device_name"fops是指向操作入口.
static struct file_operations dev_fops={.owner=THIS_MODULE,.read=m_driver03_read,.write=m_driver03_write};
其中read指向m_driver03_read是读取时使用的函数;
write指向m_driver03_write是写入设备时使用的函数;下面是卸载设备操作时会调用的:
static __exit void m_driver03_exit(void){ misc_deregister(&misc); printk("m_driver03_exit;\n");}
反注册设备.
<2> : 具体读写操作如下:另外附加信息:
#include#include #include #include #include #include #define DEVICE_NAME "m_driver03"/*static struct file_operations dev_fops={.owner = THIS_MODULE};static struct miscdevice misc={.minor=MISC_DYNAMIC_MINOR,.name=DEVICE_NAME,.fops=&dev_fops};*/static unsigned char mem[10000];static int written_count=0;static char read_flag='y';
读设备:
static ssize_t m_driver03_read(struct file *file,char __user *buf,size_t count,loff_t *ppos){ printk("read function entrance !\n"); unsigned char temp[4]; temp[0]=written_count>>24; temp[1]=written_count>>16; temp[2]=written_count>>8; temp[3]=written_count; if(read_flag=='n'){ copy_to_user(buf,(void*)temp,4); printk("read count : %d\t\n",(int)written_count); read_flag='y'; return count; }else{ return 0; }}
上面对应读取操作,下面对应写入操作:
static ssize_t m_driver03_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos){ copy_from_user(mem,buf,count); read_flag='n'; printk("write function entrance !\n"); written_count=count; printk("written count : %d\n",(int)count); return count;}
<3> 装在卸载模块:
module_init(m_driver03_init);module_exit(m_driver03_exit);
<4> 模块信息:
MODULE_AUTHOR("stephen");MODULE_DESCRIPTION("show how to develop linux module!");MODULE_ALIAS("using linux module!");MODULE_LICENSE("GPL");
可以用下面命令行显示出来:上面模块名实际将会生成m_driver03.ko
$ sudo modinfo m_driver03.ko
<5> 为了编译上面的模块,我写了一个shell脚本:
#!/bin/bashmake -C /usr/src/linux-headers-3.8.0-29-generic M=/home/user/linux-driver/driver03sudo insmod m_driver03.ko#sudo lsmod | grep m_driver03sudo dmesg | grep m_driver03 | tail -n 2#sudo echo 'I love you' > /dev/m_driver03#sudo dmesg | grep driver03 | tail -n 2sudo rmmod m_driver03
修改属性:
sudo chmod u+x build.sh
另外我又写了一个启动和查看基本信息的shell脚本:
#!/bin/bashsudo insmod m_driver03.kosudo lsmod | grep m_driver03sudo dmesg | grep m_driver03 | tail -n 2ls -a /devls -l /dev#cat /proc/devicessudo modinfo m_driver03.ko
修改build_s.sh属性同上.
上面的已经测试过了,可以生成ko模块.
<6> : 测试上面的Linux驱动有两种方法,先第一种:
在测试之前,先修改一个驱动的属性:
sudo chmod 777 /dev/m_driver03
这里只是做测试用.
测试如下:echo 'I like' > /dev/m_driver03
dmesg
<7> 第二种就是写一个程序来操作:
#include#include #include #include #include int main(int argc,char *argv[]){ int testdev; unsigned char buf[4]; printf("driver test programm !\n"); testdev=open("/dev/m_driver03",O_RDWR); if(testdev==-1){ printf("can not open device! \n"); return 0; } if(argc>1){ write(testdev,argv[1],strlen(argv[1])); printf("string:%s\n",argv[1]); } read(testdev,buf,4); int n=0; n=((int)buf[0])<<24|((int)buf[1])<<16 | ((int)buf[2])<<8 | ((int)buf[3]); printf("word byte display:%d,%d,%d,%d\n",buf[0],buf[1],buf[2],buf[3]); printf("word count : %d\n",n); close(testdev); return 0; }
user@ubuntu:~/linux-driver/driver03$ ./driver_test "hello linux"driver test programm !string:hello linuxword byte display:0,0,0,11word count : 11
要看驱动那边的打印信息:
dmesg