第1个linux驱动___应用程序才是大Boss

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第1个linux驱动___应用程序才是大Boss相关的知识,希望对你有一定的参考价值。

我们的驱动模块已经可以被自动分配主设备号了,可以说到目前为止,一个驱动模块所具备的一些“基础设施”它都具备了,就像是养兵前日,用兵一时,已经可以让first_drv这个驱动模块出去打仗了。


那么说是出去打仗,总得有个发号施令的首长吧,在linux系统中,这位调兵遣将的首长就是应用程序,应用程序才是大Boss,我们“一直精雕细琢的驱动模块”说白了只是个跑腿的。


这就是为什么我们的专题是第1个linux驱动却要讲应用程序的原因,因为应用程序是让驱动程序能够被应用的,而驱动程序是让应用被驱动的,两者是一种主仆关系、合作关系,在linux系统中缺一不可。


其实说到应用程序,大家应该还会有一种亲和感,它也是C语言写的,不过在写应用程序之前,你最好对C语言的文件IO操作有所了解。


应用程序的名字就定为app.c吧,首先得有一个main函数:

   

int main(void)
{     
    return 0;
}


框架已经完成,那我们要在app.c里写什么才能实现对first_drv这个驱动的调用呢。

我们说过是通过register_chrdev这个函数向内核中注册驱动后,系统中就能够访问并使用这个驱动了,而向内核注册驱动指的是将驱动的信息存放在一个数组中,而存放在这个数组中的第几个元素是取决于驱动程序的主设备号的,比如主设备号是100,就那就是存放在数组的第100个格子中。


其实应用程序是通过设备文件来找到驱动的,那么最好的方法就是通过打开这个设备文件,得知驱动的主设备号是多少,再通过这个主设备号来找到驱动。


我们通过执行:"mknod /dev/test 主设备号 次设备号"这个命令来建立一个设备文件。


如执行:mknod /dev/test 100 0 就建立了一个主设备号为100、次设备号为0的设备文件,这个次设备号是什么我们暂时不去关心,我们只要知道主设备号100对应了唯一的一个驱动模块。


有了100这个主设备号,就能找到确定的驱动模块。


我们稍后再建立first_drv的设备文件/dev/test,先来在app.c中把打开设备文件/dev/test的代码写好:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
    int fd = -1;
    
     fd = open("/dev/test", O_RDWR);
     
     if(fd < 0)
     {
        printf("Open /dev/test failure!\n");
        return -1;
     }
     
     printf("Open /dev/test success...\n");
     
     close(fd);
          
     return 0;
}


open是linux内核为我们提供的访问系统的API接口,像这样的系统调用还有read、write、close等。


由于添加了app.c,在编译之前,我们得修改Makefile的all、cp和clean命令如下:


#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build
KERN_DIR = /work/kernel/linux-2.6.22.6

all:
        make -C $(KERN_DIR) M=`pwd` modules 
        arm-linux-gcc -o app app.c
        
cp:
        cp *.ko app /work/my_drivers/ko_file
        
clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        rm -rf Module.symvers app
        
obj-m   += zero_drv.o


修改好Makefile后,来执行make:


可以看到生成了app这个可执行文件,make cp将它和first_drv.ko拷贝到最小根文件系统的/mnt目录下。


在/mnt目录下执行:./app(执行前要确保已经安装驱动模块first_drv)


打印:Open /dev/test failure!


打开设备文件/dev/test失败,这是我们app.c中自己写的打开设备文件失败时的打印信息。


为什么打开失败,因为我们还没有创建这个设备文件,


我们先来cat /proc/devices查看一下当前first_drv驱动模块的主设备号是多少,我这里是252,你们去查看自己的主设备号是多少。次设备号暂定0好了。


我这边执行:mknod /dev/test c 252 0


没有异常,创建成功。


然后执行./app


显示:


It is in first_drv_open.

Open /dev/test success...It is in first_drv_release.

(此处是空行)

(光标在这行)


其中“It is in first_drv_open.”是我们驱动程序中first_drv_open函数的打印信息,而“Open /dev/test success...”是应用程序中的打印信息,我们看到紧接着没有回车,就打印了“It is in first_drv_release.”,这是我们驱动程序中first_drv_release函数的打印信息。


奇怪的是我们明明加了/n,为什么没有回车呢,这是因为驱动程序的优先级比应用程序要高,当应用程序正在打印信息时,如果驱动程序中也要执行打印信息,那么就会优先让驱动程序来打印信息,当驱动程序打印完成后,再让应用程序来打印信息,这就是为什么第3句话直接接在了第2句话的后面,而第3句话后又输出了第2句话最后的回车。


这一点不影响我们的功能测试,对于这个现象我们心知肚明就好。


总而言之,我们通过运行应用程序,让驱动得以工作了。


我们来对应用程序app.c进行一点小改进:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define FILE "/dev/test"

int main(void)
{
    int fd = -1;
    
    fd = open(FILE, O_RDWR);
     
     if(fd < 0)
     {
        printf("Open %s failure!\n", FILE);
        return -1;
     }
     
     printf("Open %s success...\n", FILE);
     
     close(fd);
     
     return 0;
}


无非就是添加了一个宏定义,这样便于修改设备文件名。


再测试一次,同样可以让驱动程序工作。


但我们目前的调用仅仅只是让驱动程序打印个信息,下一篇博文我们来继续完善驱动程序,让驱动程序在被应用程序调用的时候,能够做更多的事情。




本文出自 “12253782” 博客,请务必保留此出处http://12263782.blog.51cto.com/12253782/1874748

以上是关于第1个linux驱动___应用程序才是大Boss的主要内容,如果未能解决你的问题,请参考以下文章

第1个linux驱动___整个系统是怎样工作的

第1个linux驱动___打印"hello world"

第1个linux驱动___打印"hello world"

第1个linux驱动___打印"hello world"

第1个linux驱动___自动分配主设备号

第1个linux驱动___自动分配主设备号