本篇文章给大家谈谈怎么做linux驱动,以及编译linux驱动对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、如何编写Linux操作系统的设备驱动程序
- 2、怎样编写Linux设备驱动程序?
- 3、如何搭建一个Linux驱动编写环境
- 4、如何编写Linux的驱动程序
- 5、linux如何安装驱动
1、如何编写Linux操作系统的设备驱动程序
Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和
思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的
区别.在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是
支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调
试也不方便.本人这几周来为实验室自行研制的一块多媒体卡编制了驱动程序,
获得了一些经验,愿与Linux fans共享,有不当之处,请予指正.
以下的一些文字主要来源于khg,johnsonm的Write linux device driver,
Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关
device driver的一些资料. 这些资料有的已经过时,有的还有一些错误,我依
据自己的试验结果进行了修正.
一. Linux device driver 的概念
系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统
内核和机器硬件之间的接口.设备驱动程序为应用程序屏蔽了硬件的细节,这样
在应用程序看来,硬件设备只是一个设备文件, 应用程序可以象操作普通文件
一样对硬件设备进行操作.设备驱动程序是内核的一部分,它完成以下的功能:
1.对设备初始化和释放.
2.把数据从内核传送到硬件和从硬件读取数据.
3.读取应用程序传送给设备文件的数据和回送应用程序请求的数据.
4.检测和处理设备出现的错误.
在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是
块设备.字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际
的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,
当用户进程对设备请求读/写时,它首先察看缓冲区的内容,如果缓冲区的数据
能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际
的I/O操作.块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间
来等待.
已经提到,用户进程是通过设备文件来与实际的硬件打交道.每个设备文件都
都有其文件属性(c/b),表示是字符设备还蔤强樯璞?另外每个文件都有两个设
备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个
设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分
他们.设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号
一致,否则用户进程将无法访问到驱动程序.
最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是
抢先式调度.也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他
的工作.如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就
2、怎样编写Linux设备驱动程序?
Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。本人这几周来为实验室自行研制的一块多媒体卡编制了驱动程序,获得了一些经验,愿与Linux fans共享
一、Linux device driver 的概念系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件, 应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:
1.对设备初始化和释放。
2.把数据从内核传送到硬件和从硬件读取数据。
3.读取应用程序传送给设备文件的数据和回送应用程序请求的数据。
4.检测和处理设备出现的错误。
二、实例剖析我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。
3、如何搭建一个Linux驱动编写环境
总结下之前尝试过的搭建的编写Linux驱动程序的环境。由于之前的环境是centos,其他平台的差异,就自己注意下吧。
步骤如下:
Step1:下载kernel源码包,解压到/usr/src目录下
命令如下:tar Jxvf /home/yourAccount/linux-2.6.32.67.tar.xz
Step2:为系统的include创建链接文件
命令如下:
cd /usr/include
rm -rf asm linux scsi
ln -s /usr/src/linux-2.6.32.22/include/asm-generic asm
ln -s /usr/src/linux-2.6.32.22/include/linux linux
ln -s /usr/src/linux-2.6.32.22/include/scsi scsi
Step3:下载安装内核开发包
命令如下: yum install kernel-devel-2.6.32-504.el6.x86_64.rpm
如果是其他linux系统,这个命令肯定不同!注意
Step4:建立构建的软连接
命令: ln -s ../../../usr/src/kernels/2.6.32-504.el6.x86_64/ build
在用make编译过程中之前出现过如下问题:
make:*** /lib/modules/.6.32-504.el6.x86_64/build/:No such file ore directory.Stop
出现这个问题的原因是系统没有安装内核开发包,可以查看/usr/src/kernals.
若该目录是空,则说明没安装。若非空,则可能链接有问题,安装上面Step4中到/lib/modules/2.6.32-504.el6.x86_64 去建立软链接
注:内核版本通过uname -r自行查看,查找匹配源码包和开发包
4、如何编写Linux的驱动程序
}; //IO功能选项,硬件上拉输出 static unsigned int gpio_cfg_table[] = { S3C2410_GPB5_OUTP, S3C2410_GPB6_OUTP, S3C2410_GPB7_OUTP, S3C2410_GPB8_OUTP, }; //编写一个ioctl函数,这个函数提供给用户端使用(也就是用户态使用) static int my_ioctl(struct inode *inode,struct file* file,unsigned int cmd, unsigned long arg) { if (arg 4) { return -EINVAL; } if (cmd == 1) //led ON { s3c2410_gpio_setpin(gpio_table[arg],0); return 0; } if (cmd == 0) //led OFF { s3c2410_gpio_setpin(gpio_table[arg],1); return 0; } else { return -EINVAL; } } //一个和文件设备相关的结构体。 static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = my_ioctl, //.read = my_read, //这个暂时屏蔽,一会我们再加入一个读操作的函数 }; //linux中设备的注册结构体 static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = dev_fops, }; //设备初始化(包括注册)函数 static int __init dev_init(void) { int ret; int i; for (i=0;i4;i++) { s3c2410_gpio_cfgpin(gpio_table[i],gpio_cfg_table[i]); s3c2410_gpio_setpin(gpio_table[i],0); mdelay(500); s3c2410_gpio_setpin(gpio_table[i],1); } ret = misc_register(misc); printk(DEVICE_NAME"MY_LED_DRIVER init ok\n"); return ret; } //设备注销函数 static void __exit dev_exit(void) { misc_deregister(misc); } //与模块相关的函数 module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("blog.ednchina.com/itspy");
MODULE_DESCRIPTION("MY LED DRIVER"); 到此,上面就完成了一个简单的驱动(别急,下面我们再会稍微增加点复杂的东西),以上代码的可以简单概括为:像自己写51单片机或者ARM的裸奔程序一样操作IO函数,然后再linux系统中进行相关必须的函数关联和注册。 为什么要关联呢,为什么注册呢? 因为这是必须的,从以下这些结构体就知道了。 stuct file_operations{ struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); … } file_operations 结构体中包括了很多与设备相关的函数指针,指向了驱动所提供的函数。 struct inode{ struct hlist_node i_hash; struct list_head i_list; struct list_head i_sb_list; struct list_head i_dentry; unsigned long i_ino; atomic_t i_count; unsigned int i_nlink; uid_t i_uid; gid_t i_gid; dev_t i_rdev; u64 i_version; loff_t i_size; … } inode 是 UNIX 操作系统中的一种数据结构,它包含了与文件系统中各个文件相关的一些重要信息。在 UNIX 中创建文件系统时,同时将会创建大量的 inode 。通常,文件系统磁盘空间中大约百分之一空间分配给了 inode 表。 大略了解以上信息之后,我们只需把我们所要实现的功能和结构体关联起来。上例中已经完成IO写操作的函数,现在我们再添加一个读的函数。基于这种原理,我们想实现各种功能的驱动也就很简单了。 //添加读函数示意, 用户层可以通过 read函数来操作。 static int my_read(struct file* fp, char __user *dat,size_t cnt) { size_t i; printk("now read the hardware...\n"); for(i=0;icnt;i++) dat[i] = 'A'; dat[i] = '\0'; return cnt; } 这样,完成驱动编写。编译之后,本驱动可以通过直接嵌入内核中,也可以以模块的嵌入的形式加载到linux内核中去。 完成了驱动,写个应用程序了验证一下吧: int main(int argc,char ** argv) {
int on; int led_no; int fd; char str[10]; int cnt =0; fd = open("/dev/MY_LED_DRIVER",0); if (fd 0) { printf("can't open dev\n"); exit(1); } printf("read process\n"); cnt = read(fd,str,10); printf("get data from driver:\n%s\ncount = %d\n",str,cnt); printf("read process end \n"); cnt = 0; printf("running...\n"); while(cnt++1000) { ioctl(fd,0,0); //led off ioctl(fd,0,1); ioctl(fd,0,2); ioctl(fd,0,3); sleep(1); //printf("sdfdsfdsfdsfds...\n"); ioctl(fd,1,0); //led on ioctl(fd,1,1); ioctl(fd,1,2); ioctl(fd,1,3); sleep(1); printf("%d\b",cnt); } close(fd); return 0; }
5、linux如何安装驱动
linux的驱动一般有两种格式,分别为:tar和rpm格式。
rpm安装步骤:
1.将驱动程序文件bcm5700-.src.rpm复制到一个临时目录中,并在此目录中运行以下命令:
rpm –ivh bcm5700-.src.rpm
2.运行以下命令切换到驱动目录中:
cd /usr/src/redhat/SPECS/
3.此目录中会生成一个名字为bcm5700.spec的文件,运行以下命令对驱动程序进行编译:
rpmbuild –bb bcm5700.spec (对4.x.x版本的RPM适用)或 rpm -bb bcm5700.spec
4.运行以下命令切换到RPM目录中:
cd /usr/src/redhat/RPMS/i386/
5.运行以下命令安装驱动程序:
rpm –ivh bcm5700-.i386.rpm (对于Red Hat 7.2, 7.3, 2.1AS和其他包含老版本驱动的系统需要使用--force的参数,强制用新的驱动替换系统自带的老版本驱动)
6.运行以下命令加载驱动模块:
insmod bcm5700
7.运行kudzu命令,系统会自动搜索到硬件,进行配置即可。
或者重新启动系统,启动过程中系统会自动找到硬件,进行相应配置即可。
tar格式安装步骤:
1. 将驱动程序压缩文件bcm5700-.tar.gz复制到一个临时目录中,并使用以下命令解压缩:
tar xvzf bcm5700-.tar.gz
2.构建驱动程序为运行内核可加载模块
cd bcm5700-/src
make
3.加载测试
insmod bcm5700
4.加载驱动程序
make install
5.重新启动系统,启动过程中找到硬件,进行相应配置。
或者直接运行kudzu命令,系统会自动搜索到硬件,进行配置即可。
怎么做linux驱动的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于编译linux驱动、怎么做linux驱动的信息别忘了在本站进行查找喔。