驱动原理(应用程序访问驱动程序)

以read为例:

  read是一个系统调用,系统调用之前在应用程序当中(或者叫用户空间当中),read的实现代码在内核中,read是如何找到内核的实现代码呢?

/*********************************************
*filename:read_mem.c
********************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int fd = 0;
    int dst = 0;

    fd = open("/dev/memdev0",O_RDWR);

    read(fd, &dst, sizeof(int));

    printf("dst is %d\n",dst);

    close(fd);

    return 0;
}

  这个应用程序就是打开字符设备文件,然后使用系统调用,去读取里头的数据,

  用 arm-linux-gcc static –g read_mem.c –o read_mem

  反汇编:arm-linux-objdump –D –S read_mem >dump

  找到主函数:vim dump -> /main

  

  找到libc_read函数

    

  关注两行代码:

  mov r7,#3

  svc 0x00000000

  read的系统调用在应用程序当中主要做了两项工作,3传给了r7,然后使用svc指令。

  svc系统调用指令,系统会从用户空间进入到内核空间,而且入口是固定的,3就是代表read要实现的代码,根据3查表,查出3代表的函数,然后调用这个函数。

  打开entry_common.S;找到其中的ENTRY(vector_swi)

    在这个函数中得到调用标号

    根据标号找到一个调用表

    然后找到进入表

    打开calls.S文件,会得到一张系统调用列表(部分图示)

  3代表的就是read;

  分析sys_read,原函数在read_write.c文件中(/linux/kernel code/linux-2.6.39/fs)

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
    struct file *file;
    ssize_t ret = -EBADF;
    int fput_needed;

    file = fget_light(fd, &fput_needed);
    if (file) {
        loff_t pos = file_pos_read(file);
        ret = vfs_read(file, buf, count, &pos);
        file_pos_write(file, pos);
        fput_light(file, fput_needed);
    }

    return ret;
}

  函数fd进去后,利用fd找到文件所对应的struct file,利用struct file调用vfs_read();

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
    ssize_t ret;

    if (!(file->f_mode & FMODE_READ))
        return -EBADF;
    if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
        return -EINVAL;
    if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
        return -EFAULT;

    ret = rw_verify_area(READ, file, pos, count);
    if (ret >= 0) {
        count = ret;
        if (file->f_op->read)
            ret = file->f_op->read(file, buf, count, pos);
        else
            ret = do_sync_read(file, buf, count, pos);
        if (ret > 0) {
            fsnotify_access(file);
            add_rchar(current, ret);
        }
        inc_syscr(current);
    }

    return ret;
}

原文地址:https://www.cnblogs.com/dongry/p/10656010.html

时间: 2024-11-10 13:09:40

驱动原理(应用程序访问驱动程序)的相关文章

STM32液晶显示HT1621驱动原理及程序代码

1.HT1621电路分析 HT1621为32×4即128点内存映像LCD驱动器,包含内嵌的32×4位显示RAM内存和时基发生器以及WDT看门狗定时器. HT1621驱动电路如下图所示: 图1 与单片机相连接控制的有9脚CS,3脚WR,12脚DATA,其功能描述如下表. 图2 2.字符显示原理 液晶管点亮和熄灭原理分别为在对应的RAM地址中写1和写0.首先需要清楚所驱动控制的液晶的COM-SEG对应关系,然后需要了解HT1621的32×4RAM地址映射. 例如要控制的液晶的装脚成品图部分如下: 图

android应用程序访问linux驱动第一步:实现并测试Linux驱动

一直都想亲自做一次使用android应用程序访问Linux内核驱动的尝试,但总是没能做到.最近抽出时间,下决心重新尝试一次.尝试的开始当然是先写一个Linux内核驱动了. 我希望写一个简单测驱动程序,实现写一个字符串进去,然后再把它读出来的功能.驱动中会创建dev/hello设备节点和/sys/class/hello/hello/val 设备节点,没有实现proc/下的对应的设备节点./sys/class/hello/hello/val 主要用于快速测试,而dev/hello则主要用于供上层应用

驱动开发之 用DeviceIoControl实现应用程序与驱动程序通信

Ring3测试程序:http://blog.csdn.net/zj510/article/details/8216321 1.readfile和writefile可以实现应用程序与驱动程序通信,另外一个Win32 API 是DeviceIoControl. 应用程序自定义一中IO控制码,然后调用DeviceIoControl函数,IO管理器会产生一个MajorFunction 为IRP_MJ_DEVICE_CONTROL,MinorFunction 为自己定义的控制码的IRP,系统就调用相应的处

Docker五种存储驱动原理及应用场景和性能测试对比

Docker最开始采用AUFS作为文件系统,也得益于AUFS分层的概念,实现了多个Container可以共享同一个image.但由于AUFS未并入Linux内核,且只支持Ubuntu,考虑到兼容性问题,在Docker 0.7版本中引入了存储驱动, 目前,Docker支持AUFS.Btrfs.Device mapper.OverlayFS.ZFS五种存储驱动.就如Docker官网上说的,没有单一的驱动适合所有的应用场景,要根据不同的场景选择合适的存储驱动,才能有效的提高Docker的性能.如何选择

Android应用程序、应用程序访问硬件的流程

对于分层的系统,刚开始认识时,从宏观的框架层面了解应用的构建过程,有助于形成自己对新系统的清晰概念. 1.Android应用程序构建框架: 这里就涉及活动.布局.注册之间的关系.搞清了这三者,会对真个应用的实现流程了然于心. 2.应用程序访问底层硬件的程序构成: 这里就涉及应用.Android Frameworks.JNI.硬件抽象层HAL.驱动.硬件(OS)之间的关系,了解它们间的关系,对于整个安卓系统就有了整体的清晰认识. 版权声明:本文为博主原创文章,未经博主允许不得转载.

Android中Input型输入设备驱动原理分析(一)

转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反正这个是没变的,在android的底层开发中对于Linux的基本驱动程序设计还是没变的,当然Android底层机制也增加几个属于android自己的机制.典型的IPC Android中的input设备驱动主要包括:游戏杆(joystick).鼠标(mouse)和事件设备(Event). 1.Inpu

[OpenNebula]中间件访问驱动程序

/* -------------------------------------------------------------------------- */ /* Copyright 2002-2014, OpenNebula Project (OpenNebula.org), C12G Labs */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); you may */ /* not

二级域名原理以及程序代码

二级域名原理以及程序代码 TYPE:经典代码片段 TIME:2002-7-30 AUTHOR:扬子 URL:N/A HIT:51  DAYHIT:1  WEEKHIT:1 要达到二级名的效果,必须一下条件以及流程: 1.必须有一个顶级域名,而且此域名必须做好泛解析并做好指向. 2.必须有一台独立的服务器.泛解析的域名指向该服务器. 3.在服务器上的IIS建一个空的主机头名的web站点. 4.将默认的页面设置为你的二机解析程序(比如:freedns.asp) 5.二级域名系列程序(包括申请页:sh

ADO.NET程序访问数据的组件

组成--数据集(内存中的数据库) --DataSet数据集 --DataTable数据表 --DataColumn数据列 --DataRow数据行 --DataView数据视图--NET数据提供程序 --Connection连接(程序和数据库之间的桥梁) --Open/Close --ConnectionString:连接字符串(目标数据库的信息) --服务器:server / data source --用户名:uid / user id --密码:pwd / password --数据库:d