[内核]Linux UserSpace和Kernel之间如何联系
转自:http://blog.csdn.net/dreaming_my_dreams/article/details/8272586
应用层和驱动的衔接,一直是一个老大难问题,若弄不清楚,总觉得驱动写起来似是而非的。下面就说说我对他们的理解,还有就是如何实现一个驱动支持多个上设备的问题。最主要涉及两个机制:inode和file
1. 在驱动中
- 我们先找到一个设备号devno,可以动态申请,也可以静态设定,假设静态设定为major,minor,通过宏MKDEV(major,minor)来生成devno
- 构建对设备的操作函数集file_opreation结构体,里面包含了的设备的操作:open、read、write、release、ioctl等
- 构建cdev结构体,里面填充两个主要成员dev(设备号)、file_operation(对设备的操作)
- 把cdev添加到cdev链表中:cdev_init、cdev_add
举个例子,tty驱动:
-->__init imx_serial_init //imx.c
-->uart_register_driver //serial_core.c
-->tty_regiser_driver //tty_io.c
-->MKDEV(driver->major, driver->minor_start) //tty_io.c
-->tty_cdev_add //tty_io.c
-->cdev_init(tty_fops) //tty_io.c, struct file_operations tty_fops={.open;.read;.write}
-->cdev_add //tty_io.c
就这样,一步步将file_operation的函数集加入到cdev->ops中,而User层则根据设备号找到cdev链表中对应的设备属性,从而找到函数集。
2. 应用程序中
fd=open("/dev/hello",O_RDWR)来打开设备文件,此设备对应有一个设备号,这是我们识别驱动和设备的桥梁。
设备号、设备文件、设备节点概念:设备号由主设备号和从设备号组成,设备号是16bit, 高8bit为主设备号,低8bit为从设备号。/dev下每个设备都有对应的设备文件,即设备节点。
打开 /dev/hello时,根据设备号,在cdev链表中找到cdev这个结构体,cdev里面包含了file_operation结构体,有设备的各种操作,打开时就调用里面的.open 函数。在这里要完成几件事:
- inode节点 每一个文件都对应有一个inode节点,inode结构体里.i_fop由cdev的file_operation填充,i_dev由cdev的设备号填充
- file结构体中的file_operation也同样由cdev中对应项填充,还有一项fd,对应于打开文件的文件描述符,fd和file一一对应,文件每打开一次,就有一个file结构。所以file里面的.private就很重要,下面会说到。
还有一个问题,那就是多个相同的设备,会公用同一个驱动(一个驱动文件1个主设备号如uart),所以要把每一个设备的私有数据封装起来,构成一个私有数据结构体。对设备的每一次读写,都通过操作设备的私有数据结构体中的资源来完成。也就是说,驱动在加载的时候,会申请多个设备私有资源结构体,每个结构体中包含了设备的所有私有资源,虽然公用一个驱动,可是通过设备号找到此设备号对应设备的私有资源,说的有点拗口。这可以通过file结构体的.private来指向。
例如封装私有数据的结构体为:
struct hello_device{
char buf[128]; //设备的私有资源,譬如buf
struct cdev cdev;//设备结构体,里面有devno和file_operation
……
};
前面应经提到inode中的i_cdev会指向cdev结构,所以可以由Container宏来得到hello_device的地址。
所以,在驱动的open函数中有两个参数,inode和file
int open(structc inode *inode,struct file *file){
struct hello_device *p =container(inode->i_cdev,hello_struct,cdev)
file->private=p;
}
这样file中就包含了设备的私有数据。
驱动read函数中:
ssize_t read(fd,char __user *buf,count)
fd和file一一对应,每打开一次设备,虽然有不同的fd,但他们的file.private是一样的。
每打开一个设备文件,把私有数据和file绑定,这样后面的read/write操作,由于fd和file一一对应,这样,read/write也就通过fd句柄就可以访问到file->private数据了。
前面主要说了一个驱动如何可以支持多个设备的问题,以及应用层和驱动之间的联系。还有一个问题就是,如何处理过多个进程访问同一个设备的问题。
-----------------------------------------------------------------------------------------------------------------------------------------------------------
转自:http://blog.chinaunix.net/uid-20543672-id-3203690.html
最近在看《深入Linux设备驱动程序机制》,这本书条理清晰,我从中获益良多。以前在学习内核驱动的时候就是知道怎么用,对于内部的原理了解的不是这么深入。且当时的能力有限,想了解深入也不容易。这次正好趁复习驱动原理的机会,把这本书认真学习以下。
1、字符设备号的管理原理

2、字符设备驱动的file_operation中的函数如何与file结构体中的相应结构对应上,并被应用程序调用

[内核]Linux UserSpace和Kernel之间如何联系的更多相关文章
- shell、bash、terminal和kernel之间的关系
shell.bash.terminal和kernel之间的关系 本文是<鸟哥的Linux私房菜>的学习笔记 什么是kernel kernel的中文是"操作系统核心",主 ...
- ZMQ 在linux进程 和分布式之间的通信
ZMQ 在linux进程 和分布式之间的通信 待补全
- Linux/Unix shell sql 之间传递变量
灵活结合Linux/Unix Shell 与SQL 之间的变量传输,极大程度的提高了DBA的工作效率,本文针对Linux/Unix shell sql 之间传递变量给出几个简单的示例以供参考. Lin ...
- 远程调用内核接口(remote call kernel)
-------------------------------------------------------------------------------- 标题: 远程调用内核接口(remote ...
- Level-IP(Linux userspace TCP/IP stack)
转自:github.com/saminiir/level-ip Level-IP is a Linux userspace TCP/IP stack, implemented with TUN/TAP ...
- lower_case_table_names和数据库在Linux和windows平台之间的相互迁移问题
MySQL关于 lower_case_table_names 的文档 https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivi ...
- Memory Allocation API In Linux Kernel && Linux Userspace、kmalloc vmalloc Difference、Kernel Large Section Memory Allocation
目录 . 内核态(ring0)内存申请和用户态(ring3)内存申请 . 内核态(ring0)内存申请:kmalloc/kfree.vmalloc/vfree . 用户态(ring3)内存申请:mal ...
- archlinux 传统方法编译内核linux kernel 3.3.7
From: http://hi.baidu.com/flashgive/item/eaef6326b5eb73d3a417b662 archlinux中传统方法编译内核 1)下载内核以及补丁并解压: ...
- Linux 内核源码(kernel source)
查看内核的发行版:uname -r(--kernel-release) $ uname -r 4.4.0-78-generic 内核源码所在的位置:/usr/src $ cd /usr/src $ l ...
随机推荐
- 小课堂week19 编程范式巡礼最终季 超级范式
编程范式巡礼(最终季)--超级范式 本周是编程范式系列的最后一次分享,让我们拉长视角,看向远方,进入"元编程"的领域,在<冒号课堂>中起了个很酷的名字:"超级 ...
- Asp 将MSXML2.serverXMLHTTP返回的responseBody 内容转换成支持中文编码
参考:ASP四个小技巧,抓取网页:GetBody,字节转字符BytesToBstr,正则表达式测试方法,生成静态页 Function GetBody(weburl) '创建对象 Dim ObjXMLH ...
- 转:Tortoise SVN 版本控制常用操作知识
转自:http://www.cnblogs.com/csharp4/archive/2010/11/26/1889317.html 今天老大跑过来问我如何把SVN服务器上的当前版本回退到某一个版本上去 ...
- Hibernate_8_Person和IdCard实例_一对一关系:基于外键
1)建立Person类: public class Person { private Integer id; private String name; private IdCard IdCard; p ...
- C++标准库简介
C++标准库的所有头文件都没有扩展名.C++标准库的内容总共在50个标准头文件中定义,其中18个提供了C库的功能. <cname>形式的标准头文件[ <complex>例外]其 ...
- Ubuntu 下建立WiFi热点的方法
使用ap-hotspot来创建WIFI热点.终端里输入: $ sudo add-apt-repository ppa:nilarimogard/webupd8 $ sudo apt-get updat ...
- java通过反射调用不同参数的方法
import java.lang.reflect.Method; public class testReflect { /** * @param args */ public static void ...
- activiti自己定义流程之Spring整合activiti-modeler实例(七):任务列表展示
1.通过上一节的操作,能够知道流程启动以后会同一时候生成一个流程实例和用户任务.这个用户任务保存在act_ru_task和act_hi_task表中,从表明能够看出ru是runtime,hi是hist ...
- Mysql字符串中有数字的排序问题
此方法是我见过最聪明的写法,不过不知道有没有隐含的bug: 参考地址 select id, col from tableName order by length(col) asc, col asc这种 ...
- iOS-开发者相关的几种证书(转)
分享一篇关于苹果开发者证书非常详细的解释. 哈哈,我太懒了,直接转发链接. iOS-开发者相关的几种证书