《嵌入式linux简单程序.docx》由会员分享,可在线阅读,更多相关《嵌入式linux简单程序.docx(10页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、1、demodemo.c#ifndef _KERNEL_#define _KERNEL_#endif#ifndef MODULE#define MODULE#endif#include #include /模块相关#include /内核相关#include /file_operations#include /ssize_t定义文件#include /_init和_exit相关#include #include #include /copy_to_user()和copy_from_user()在此定义#include /*相关宏定义*/#define DEVICE_NAMEdemo/设备名称#
2、define demo_MAJOR 88/主设备号#define demo_MINOR 0/次设备号#define ERROR -1static int MAX_BUF_LEN=1024;/数值的最大值static int WRI_LENGTH=0;/*结构体的定义*/static int demo_major=demo_MAJOR;struct demo_devstruct cdev cdev;char drv_buf1024;struct demo_dev * demo_devp;/*/*demo设备文件打开*/int demo_open(struct inode * inode,stru
3、ct file *filp)filp-private_data=demo_devp;sprintf(demo_devp-drv_buf,device open sucess!n);printk(device open sucess!n);return 0;/*/*demo设备文件关闭*/int demo_release(struct inode * inode,struct file *filp)return 0;/*/*逆序排列缓冲区数据*/static void do_write(char * drv_buf)int i;int len = WRI_LENGTH;char tmp;for(
4、i = 0; i private_data;if(count MAX_BUF_LEN)count = MAX_BUF_LEN;copy_from_user(dev-drv_buf, buffer, count);WRI_LENGTH = count;printk(user write data to drivern);do_write(dev-drv_buf);return count;/*/static ssize_t demo_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)struct demo_dev*
5、dev=filp-private_data;if(count MAX_BUF_LEN)count=MAX_BUF_LEN;copy_to_user(buffer, dev-drv_buf,count);printk(user read data from drivern);return count;/*/static int demo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)printk(ioctl runingn);switch(cmd)case 1:printk(ru
6、ning command 1 n);break;case 2:printk(runing command 2 n);break;default:printk(error cmd numbern);break;return 0;/*/*demo的模块加载函数*/static const struct file_operations demo_fops=.owner=THIS_MODULE,.read=demo_read,.write=demo_write,.ioctl=demo_ioctl,.open=demo_open,.release=demo_release,;/*/*demo的模块加载函
7、数*/int _init demo_init(void)int result;int err;dev_t devno=MKDEV(demo_MAJOR,demo_MINOR); if(demo_MAJOR) result=register_chrdev_region(devno,1,demo); else result=alloc_chrdev_region(&devno,0,1,demo); demo_major=MAJOR(devno); if(resultcdev,&demo_fops);demo_devp-cdev.owner=THIS_MODULE;err=cdev_add(&dem
8、o_devp-cdev,devno,1);if(err)printk(注册设备失败);unregister_chrdev_region(MKDEV(demo_MAJOR,demo_MINOR),1);return err;printk(demo init seccess !n);return 0;/*/*demo的模块卸载函数*/void _exit demo_exit(void)cdev_del(&demo_devp-cdev);kfree(demo_devp);unregister_chrdev_region(MKDEV(demo_MAJOR,demo_MINOR),1);MODULE_A
9、UTHOR(Liang Baoqiang);MODULE_LICENSE(Dual BSD/GPL);module_init(demo_init);module_exit(demo_exit);Makefileobj-m += demo.o#mod1-y := mod_a.oKVERSION = $(shell uname -r)all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modulesclean:make -C /lib/modules/$(KVERSION)/build M=$(PWD) cleanrm -f *.o *.ko
10、*.cmdtest_demo.c#include #include #include #include #include void showbuf(char *buf);int MAX_LEN=32;int main()int fd;int i;char buf255;for(i=0; iMAX_LEN; i+)bufi=i;fd=open(/dev/demo,O_RDWR);if(fd 0)printf(#DEMO device open fail#n);return (-1);printf(write %d bytes data to /dev/demo n,MAX_LEN);showbu
11、f(buf);write(fd,buf,MAX_LEN);printf(Read %d bytes data from /dev/demo n,MAX_LEN);read(fd,buf,MAX_LEN);showbuf(buf);ioctl(fd,1,NULL);ioctl(fd,4,NULL);close(fd);return 0;void showbuf(char *buf)int i,j=0;for(i=0;iMAX_LEN;i+)if(i%4 =0)printf(n%4d: ,j+);printf(%4d ,bufi);printf(n*n);2、hello.c #include#in
12、cludeMODULE_LICENSE(Dual BSD/GPL);static int hello_init(void) printk(KERN_ALERT Hello,init the module!); return 0;static void hello_exit(void) printk(KERN_ALERT Goodbye,exit the module!); module_init(hello_init);module_exit(hello_exit);LINUX驱动版本的hello world 终于下决心好好学习LINUX内核和驱动开发了,不怕千万人耻笑,勇敢将自己的学习过程写
13、出来:1、关于目录 /lib/modules/2.6.9-42.ELsmp/build/ 这个是内核源码所在的目录 一般使用这样的命令进入这个目录:cd /lib/modules/$(uname -r)/build/ 这个目录实际上指向了:/usr/src/kernels/2.6.9-42.EL-smp-i6862、编译驱动所使用的makefile 实际上编译驱动的时候是使用预先提供的一个makefile的,位置在:/lib/modules/$(uname -r)/build/Makefile 注意:M是大写的3、网上抄录的Linux驱动Hello world的源码:/ hello.c#inc
14、lude #include MODULE_LICENSE(Dual BSD/GPL);static int hello_init(void) printk(KERN_ALERT hello world!n); return 0;static void hello_exit(void) printk(KERN_ALERT goodbye!n); module_init(hello_init);module_exit(hello_exit);4、写个makefile来编译这个驱动:(版本一,最简单的)#下面这行是文件Makefile的内容,注意M是大写的obj-m := hello.o把hello
15、.c和Makefile保存在同一目录,然后执行:make -C /lib/modules/uname -r/build SUBDIRS=$PWD modules这样驱动就编译好了,成果是hello.ko文件。注意:makefile一定要写成Makefile,如果写成makefile就编译不过。(折腾啊,就这一步耗了N多时间)5、再写另一种Makefile:(版本二:最省事的)#以下是Makefile文件的内容obj-m := hello.oKERNEL_DIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)all: make
16、 -C $(KERNEL_DIR) SUBDIRS=$(PWD) modulesclean: rm *.o *.ko然后执行:make就编译成功了,命令行不再加参数,很省事。注意:all: 和clean:下面的行,前面是一个TAB键6、加载驱动:执行insmod ./hello.ko屏幕上没反应。(因为我是在WINDOWS上用远程终端连上去的嘛)OK,先让时光倒流,回到加载驱动以前,先另开一个窗口,执行:tail -f /var/log/message然后在原来的窗口里执行:insmod ./hello.ko哈哈,/var/log/message文件里面看见了盼望已久的hello world!
17、7、查看驱动:lsmod 看见 hello这个驱动在其中8、卸载驱动:rmmod hello 看见/var/log/message里显示了goodbye经过两周的摸索,终于对Linux设备驱动开发有了个初步的认识,下面对Linux设备驱动开发环境的搭建做个小结,以方便自己以后查询,同时也能给同道的初学者一点帮助。刚接触Linux设备驱动时,初学者往往连如何编译驱动程序都不懂,更别说编译进内核或加载测试了。一般都是在网上找个最简单的 helloworld驱动程序,然后严格按照网上所说的步骤编译,结果却得到一大堆见都没见过的错误,更不要说根据错误信息来解决问题了,很多人到这里就 不知道如何往下进行
18、了。十几天前我也卡在这里很长时间,现在知道所以然了就记下来,些许对一些同道者有帮助。一个基本的Linux设备驱动开发环境由宿主机和目标机组成,宿主机就是用来做驱动开发工作的主机,目标机就是用来运行和测试设备驱动的主机,在宿 主机上需要有开发工具(gcc,gdb,make等)和linux源码(版本要对应目标机上的linux内核),而目标机上只要运行linux即可。由于 步骤有所不同,下面分为普通Linux设备驱动开发和嵌入式Linux设别驱动开发两种情况来讲述环境的搭建和驱动程序的编译:(一)普通Linux设备驱动开发普通Linux主要是区分于嵌入式Linux(一般指uClinux),在这种开发
19、中宿主机和目标机可以是一台主机,即在本机上开发编译然后在本机 上加载运行(Linux设备驱动也可以直接编译进内核,但为了开发工作方便,一般采用动态加载的方式),当然也可以是两台主机,如果是两台主机的话,要保 证宿主机上的linux源码的版本号与目标机中的linux内核版本一致。普通Linux设备驱动开发的步骤如下:在宿主机上安装开发工具和下载linux源码(要求版本号和目标机上的linux内核版本一致)。开发工具主要有gcc、gdb、make等,这些工具在redhat或fc中默认就安装了,在debian或Ubuntu中可以通过下面这个命令安装:apt-get install build-ess
20、entiallinux源码可以通过以下几种途径获得:直接去www.kernel.org下载通过包管理工具下载源码,在debian和Ubuntu中可以通过下面这个命令下载,apt-get install linux-source-(版本号) ,下载后的文件在/usr/src目录中,解压到该目录即可将源码解压到/usr/src/目录后,进入linux-source-(版本号)目录中执行下面几个命令:make oldconfigmake preparemake scripts编写Linux驱动程序,以一个最简单的hello.c为例,hello.c的内容如下:#include linux/init.h
21、#include linux/module.hstatic int hello_init(void) printk(KERN_ALERT Hello World linux_driver_modulen); return 0;static void hello_exit(void) printk(KERN_ALERT Goodbey linux_driver_modulen);module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(lpj);写Makefile文件,一个示例如下,里面各项
22、参数根据实际情况更改:#sample driver moduleobj-m := hello.oKDIR = /usr/src/linux-source-2.6.24/all: $(MAKE) -C $(KDIR) M=$(PWD).PHONY:cleanclean: rm -f *.mod.c *.mod.o *.ko *.o *.tmp_versions编译,在hello.c和Makefile所在目录下执行 make 即可,编译后在当前目录生成hello.ko文件加载并测试:加载使用insmod或modprobe命令来实现,如在当前路径执行如下代码:insmod hello.ko 或 mo
23、dprobe hello注意,如果在虚拟终端加载内核的话,将看不到内核打印信息,因为内核打印信息不会输出到虚拟终端,而是输出到/proc/kmsg文件中,所以可以通过以下方式查看内核信息:cat /proc/kmsg 会一直打印,需要CtrlC手动终止dmesg 或 dmesg | tail -N ,N为一数字,表示显示最后N行卸载:使用rmmod命令卸载驱动模块,如 rmmod hello(二)嵌入式inux设备驱动开发这种开发中一般目标机为带有嵌入式处理器的开发板,而宿主机为PC,开发环境需要在宿主机上搭建,嵌入式Linux设备驱动开发的步骤如下:在宿主机上下载嵌入式Linux的源码,并安
24、装嵌入式Linux开发工具(针对于不同的嵌入式处理器,工具也有所不同,如对应于Arm的arm-gcc系列,针对nios2处理器的nios2-cc系列)编写Linux设备驱动驱动程序,还以上面给出的hello.c为例,将该文件复制到(linux 源码目录)/drivers/(目标文件夹)中在(目标文件夹)中创建Makefile和Kconfig(菜单配置文件),内容分别如下:#makefileobj-$(CONFIG_HELLODRV) += hello.o#Kconfigmenu USER_DEVICE_DRIVERSconfig HELLODRV tristate Hello -help- T
25、his is a sample driver programme.endmenu注意,如果Kconfig文件中的tristate写成bool,则该模块只能选为Y(编译进内核)或N(不选择),不能选为M(编译为模块,可动态加载)修改上层目录( linux内核源码目录/drivers/)中的Makefile和Kconfig文件,Makefile中加入如下语句:#makefileobj-y += (目标文件夹)(此处有多种写法,这只是其中一种)Kconfig中加入如下语句:#Kconfigsource drivers/(目标文件夹)/Kconfig编译内核:几个基本的命令及选择界面如下:make m
26、enuconfig 执行到这一步后,会看到下面这个界面:其中Vendor/Product.是选择处理器厂家和型号的,Kernel/Library.是配置应用程序的,按空格键或回车键可以进入选项进行配置,用上下键移动到Kernel/Library.菜单上,按空格或回车进入下面的内核配置界面:在该界面有两个Customize.选项,第一个是选择自定义配置内核,第二个是选择自定义配置应用程序,按空格键可以选择这些选项,选择后按 exit键退出,选择是否保存的时候选择“yes“,如果选择了第一个Customize.,则退出后会自动进入内核配置界面,如下图:该界面有很多选项,这里不细讲,我们要配置驱动模
27、块,就用上下键移动到Device Drivers上,然后按回车或空格键进入,设备驱动配置界面如下图:这里就是linux-2.X/drivers/Kconfig里的内容了,下面那个绿色的V(+)表示这一页没显示完,可以用下键继续往下浏览,找到我们自己的菜单名,然后按回车或空格进入,我的模块配置界面如下:用M键使选项前的尖括号里显示M表示该模块要动态加载,也可以按y键选择直接编辑进内核,选择完后exit退出,选择yes或no的对话框通一选yes。make romfs #第一次编译内核前一定要有该步骤make加载测试:将生成的zImage文件下载到开发板,开发板上的嵌入式Linux启动后可以用insmod或modprobe加载驱动模块,测试完毕后可以通过rmmod命令卸载驱动模块