Linux_9th_第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;
}


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


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


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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值