在linux应用层写driver驱动程序介绍

来源:互联网 发布:淘宝货款什么时候到账 编辑:程序博客网 时间:2024/06/03 13:31

刚从vxworks或其他rtos转到linux的朋友一定对linux下涉及到硬件的操作很不适应,因为在linux的体系结构中不允许应用层直接对物理地址进行访问,应用看到的都是进程内经过映射的虚拟地址。所以一般的做法是只要涉及到硬件的操作都是设计一个相应的driver,随后应用程序通过driver提供的文件操作接口去读写寄存器或者物理内存。在这里介绍一种比较折中的方法,即通过特殊的设计使得应用程序可以直接访问物理地址,这样就可以省掉编写驱动程序的工作。

这个方法的核心就是使用mmap函数,mmap是干什么的呢?它主要实现将绝对的物理地址映射到调用该函数的应用程序进程空间,建立了相关页表,这样应用程序就可以通过访问mmap返回的虚拟地址指针去访问物理绝对地址了。 下面给出一个代码实例实现对物理绝对地址的直接读写。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
  
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]/n", /
  __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char **argv) {
    int fd;
    void *map_base, *virt_addr;
    unsigned long read_result, writeval;
    off_t target;
    int access_type = 'w';
    
    if(argc < 2) {
        fprintf(stderr, "/nUsage:/t%s { address } [ type [ data ] ]/n"
            "/taddress : memory address to act upon/n"
            "/ttype    : access operation type : yte, [h]alfword, [w]ord/n"
            "/tdata    : data to be written/n/n",
            argv[0]);
        exit(1);
    }
    target = strtoul(argv[1], 0, 0);

    if(argc > 2)
        access_type = tolower(argv[2][0]);


    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
    printf("/dev/mem opened./n");
    fflush(stdout);
    
    /* Map one page */
    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
    if(map_base == (void *) -1) FATAL;
    printf("Memory mapped at address %p./n", map_base);
    fflush(stdout);
    
    virt_addr = map_base + (target & MAP_MASK);
    switch(access_type) {
        case 'b':
            read_result = *((unsigned char *) virt_addr);
            break;
        case 'h':
            read_result = *((unsigned short *) virt_addr);
            break;
        case 'w':
            read_result = *((unsigned long *) virt_addr);
            break;
        default:
            fprintf(stderr, "Illegal data type '%c'./n", access_type);
            exit(2);
    }
    printf("Value at address 0x%X (%p): 0x%X/n", target, virt_addr, read_result);
    fflush(stdout);

    if(argc > 3) {
        writeval = strtoul(argv[3], 0, 0);
        switch(access_type) {
            case 'b':
                *((unsigned char *) virt_addr) = writeval;
                read_result = *((unsigned char *) virt_addr);
                break;
            case 'h':
                *((unsigned short *) virt_addr) = writeval;
                read_result = *((unsigned short *) virt_addr);
                break;
            case 'w':
                *((unsigned long *) virt_addr) = writeval;
                read_result = *((unsigned long *) virt_addr);
                break;
        }
        printf("Written 0x%X; readback 0x%X/n", writeval, read_result);
        fflush(stdout);
    }
    
    if(munmap(map_base, MAP_SIZE) == -1) FATAL;
    close(fd);
    return 0;
}
http://www.boxueshe.org/simple/?t71.html

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 开通米粉卡店铺预留电话号码怎么办 办信用卡没有单位电话怎么办 qq账号永久封停怎么办 qq号给冻结了怎么办 微信被官方封2天怎么办 天虹的卡丢了怎么办 顺丰快递到不了的地区怎么办 信用卡兑换东西超过积分怎么办 新买的冰箱坏了怎么办 买新洗衣机出现克坏怎么办 京东当日达没到达怎么办 兴隆卡不能用了怎么办 龙津时代烂尾了怎么办 三星s8电耗尽无法开机怎么办 杜鹃买回来蔫了怎么办 电视柜比背景墙小了怎么办 美图m8手机发热怎么办 美图t8手机很卡怎么办 美图m6手机发热怎么办 金立m6打电话声音小怎么办 美图m6突然黑屏怎么办 美图t8s死机了怎么办 美图手机音量小怎么办 美图手机突然音量小怎么办 苹果六手机反应慢怎么办 美图t8开机慢怎么办 美图m6s拍照模糊怎么办 8848m4密码忘了怎么办 美图手机m4自拍黑屏怎么办 美图m4相机黑屏怎么办 美图m4手机拍照黑屏怎么办 美图m4拍照黑屏怎么办 美图m4很卡怎么办 美图m8工厂模式怎么办 美图m6开不了机怎么办 美图m8开不开机怎么办 美图摄像头坏了怎么办 美图t8相机模糊怎么办 美图m4卡槽坏了怎么办 美图t8手机好卡怎么办 美图手机m6卡怎么办