[内核]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 ...
随机推荐
- RS报表自动适应屏幕分辨率大小
问题:同一个报表,由于用户电脑显示器大小,分辨率大小不同显示的不一样,看起来不完整或者很不协调 原因:设计报表大小属性的时候使用了固定值属性,比如限制为宽:1200px 那么在电脑屏幕小分辨率很小的情 ...
- 我们为什么在移动端项目中选择jQuery而不是Zepto
1.文件大小比较 首先从cnd上(http://www.bootcdn.cn/)下载jquery和zepto. jquery下载的是2.2.4版本压缩: zepto下载的是是1.20压缩版本: 二个文 ...
- 怎样线程安全地遍历List:Vector、CopyOnWriteArrayList
遍历List的多种方式 在讲怎样线程安全地遍历List之前,先看看通常我们遍历一个List会採用哪些方式. 方式一: for(int i = 0; i < list.size(); i++) { ...
- Unicode 与UTF-8 关系
作者:邱昊宇链接:https://www.zhihu.com/question/23374078/answer/24385963来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- java反射--动态加载
Class.forName("类的全称") 1)不仅表示类的类类型,还表示了动态加载类 2)请区分编译,运行 3)编译时刻加载类是静态加载类,运行时刻加载类是动态加载类 比如下面: ...
- Appium完整安装教程
Appium安装教程 发布时间: 2014-12-11 10:34 作者: 柒月 来源: 51Testing软件测试网采编 字体: 小 中 大 | 上一篇 下一篇 | 打印 | ...
- DP SRM 661 Div2 Hard: ColorfulLineGraphsDiv2
Problem Statement Bob is going to create a graph with N nodes. The graph will be constructed in two ...
- Linux下挂载硬盘分区的几种方法
1.使用Autofs自动挂载分区 2.修改/etc/fstab 3.编写shell脚本,开机自动运行mount命令 方法一.使用Autofs 1.Autofs的特点:Autofs与Mount/Um ...
- mysql允许远程连接
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123' WITH GRANT OPTION;
- C# 编写Windows服务在VS中调试的步骤
1.以管理员身份运行cmd 2.安装windows服务 cd C:\Windows\Microsoft.NET\Framework\v4.0.30319(InstallUtil.exe的路径,注意In ...