AndroidM 内核空间到用户空间接口类型

Android系统中, 驱动程序因商业需求分为运行在用户空间的hardware层以及运行在内核空间的驱动程序, 大多情况下内核驱动都需要提供用户空间访问的接口。

Linux内核空间到用户空间的接口有主要有以下几种类型
1.系统调用
   系统调用是指系统实现的所有系统调用所构成的集合,即程序接口。
   linux系统调用分为:进程控制,文件系统控制,系统控制,内存管理,网络管理,用户管理,进程管理等类型
   linux操作系统中,系统调用的ID通常在arch/{体系结构}/include/asm/目录的unistd.h文件中.
   可增加系统调用为用户空间提供访问接口,用于系统调用是UNIX标准的内容,所以一般情况下不这样做。

2.字符设备节点
   字符设备进行I/O操作不经过操作系统的缓冲区,每次操作只传输一个字符,可以通过字符设备文件来访问
   文件操作file_operations表示对一个文件的操作,其定义在/kernel/include/linux/fs.h
   ........
   struct file_operations {
      struct module *owner;
      loff_t (*llseek) (struct file *, loff_t, int);
      ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
      ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
      ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
      ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
      ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
      ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
      int (*iterate) (struct file *, struct dir_context *);
      unsigned int (*poll) (struct file *, struct poll_table_struct *);
      long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
      long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
      int (*mmap) (struct file *, struct vm_area_struct *);
      int (*open) (struct inode *, struct file *);
      int (*flush) (struct file *, fl_owner_t id);
      int (*release) (struct inode *, struct file *);
      ........
      int (*flock) (struct file *, int, struct file_lock *);
      ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
      ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
      int (*setlease)(struct file *, long, struct file_lock **, void **);
      long (*fallocate)(struct file *file, int mode, loff_t offset,
      loff_t len);
      int (*show_fdinfo)(struct seq_file *m, struct file *f);
   };
   ........
   // 字符设备的注册函数

static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops) 
   {
      return __register_chrdev(major, 0, 256, name, fops);
   }
   // 字符设备的销毁函数
   static inline void unregister_chrdev(unsigned int major, const char *name)
   {
      __unregister_chrdev(major, 0, 256, name);
   }
   ........
   对于一般的文件,可以通过通用的文件操作,如open,read,write,ioctl,mmap,release等,
   对于简单的字符设备,也是驱动的设备节点,它的文件操作与一般的文件不一样,需要单独实现。
   字符设备的驱动程序,可以基于字符设备的驱动程序框架来构建,也可基于特定的字符设备架构来构建.
   基于字符设备的驱动程序架构来建设:
   直接实现对字符设备的注册函数进行注册,此时定义的字符设备一般具有一个唯一的主设备号.
   在注册具体的字符设备时,构建file_operations中的各个成员函数指针
   基于特定的字符设备驱动程序架构来构建:(Misc驱动程序,帧缓存驱动程序,TTY驱动程序等)
   这些驱动程序的架构通常对字符设备驱动架构进行封装,实现自己的架构,并且具有了自己的注册机制。
   在具体的驱动程序的实现中,通过这种驱动程序架构的注册函数进行注册,实现相关的函数。
   此时,驱动程序的架构一般已经实现了主设备号,具体的驱动程序实现的是次设备号。
   在用户空间通过/dev/中设备节点调用驱动程序顺序:用户空间-->字符设备驱动程序的架构-->该类驱动程序的框架-->具体驱动程序的实现。

3.块设备节点(光盘,硬盘,软盘)
   块设备采用随机访问的方式传输数据,并且数据总是具有固定大小的快,为了提高数据传输效率,块设备驱动程序内部采用块缓冲技术.
   块设备的操作在/kernel/include/linux/blkdev.h中定义
   struct block_device_operations {
      int (*open) (struct block_device *, fmode_t);
      void (*release) (struct gendisk *, fmode_t);
      int (*rw_page)(struct block_device *, sector_t, struct page *, int rw);
      int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
      int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
      int (*direct_access) (struct block_device *, sector_t,
      void **, unsigned long *);
      unsigned int (*check_events) (struct gendisk *disk,
      unsigned int clearing);
      /* ->media_changed() is DEPRECATED, use ->check_events() instead */
      int (*media_changed) (struct gendisk *);
      void (*unlock_native_capacity) (struct gendisk *);
      int (*revalidate_disk) (struct gendisk *);
      int (*getgeo)(struct block_device *, struct hd_geometry *);
      /* this callback is with swap_lock and sometimes page table lock held */
      void (*swap_slot_free_notify) (struct block_device *, unsigned long);
      struct module *owner;
   };

注册与注销/kernel/include/linux/fs.h
   extern int register_blkdev(unsigned int, const char *);
   extern void unregister_blkdev(unsigned int, const char *);

对于块设备,由于也是设备节点,也可以使用文件接口来访问,一般不直接访问块设备节点,而是使用文件系统来访问。可用df或mount来查看挂载情况
   Android块设备在/dev/block/目录中

4.网络设备
   网络设备没有文件系统的节点,使用socket机制,通过专有的数据结构进行访问,系统内部支持数据的收发。
   网络设备与字符设备和块设备最大的区别在于网络设备没有文件系统的节点。
   一般网络驱动程序不会由应用程序调用,而是由linux内核的网络模块调用,用户空间程序通过socket等通用网络接口,间接调用网络驱动程序。
   访问网络设备时,需要用到socket相关的几个函数:socket(),bind(),listen(),accept(),connect()等
   socket()和open一样,返回类型也是一个文件描述符,表示一个在进程中打开的文件。可以用通常的文件操作来对这个文件描述符进行操作。
   网络设备的核心定义在/kernel/include/linux/netdevice.h
   ........
   struct net_device {
      char name[IFNAMSIZ];
      struct hlist_node name_hlist;
      char *ifalias;
      ........
   };
   ........
   int register_netdev(struct net_device *dev); // 注册函数
   void unregister_netdev(struct net_device *dev);// 撤销函数
   ........

5.proc文件系统(ramconsole驱动)
   proc文件在/proc目录中,用于查看有关硬件,进程的状态,也可以通过操作proc文件系统进行控制工作
   proc文件系统的创建函数定义在/kernel/include/linux/proc_fs.h
   struct proc_dir_entry { // 表示一个目录项的入口
      unsigned int low_ino;
      umode_t mode;
      nlink_t nlink;
      kuid_t uid;
      kgid_t gid;
      loff_t size;
      const struct inode_operations *proc_iops; // 文件系统操作
      const struct file_operations *proc_fops; // 文件系统节点操作
      ........
   };

6.sys文件系统
    sys文件系统与proc有些类似,除了查看和设定内核参数功能之外,还有位linux统一设备模型作为管理之用
    sys文件系统只有读和写两个接口,不支持参数传递,大规模数据块操作等复杂的操作
    sys文件系统在linux文件系统的/sys/目录中,如/sys/bus/为总线目录结构,/sys/class为按功能分类设备模型
    通过cat与echo重定向来查看与设置/sys目录

7.无用户空间接口

时间: 2024-12-19 16:53:04

AndroidM 内核空间到用户空间接口类型的相关文章

内核空间与用户空间的通信方式

内核空间与用户空间的通信方式 下面总结了7种方式,主要对以前不是很熟悉的方式做了编程实现,以便加深印象. 1.使用API:这是最常使用的一种方式了 A.get_user(x,ptr):在内核中被调用,获取用户空间指定地址的数值并保存到内核变量x中. B.put_user(x,ptr):在内核中被调用,将内核空间的变量x的数值保存到到用户空间指定地址处. C.Copy_from_user()/copy_to_user():主要应用于设备驱动读写函数中,通过系统调用触发. 2.使用proc文件系统:

Linux内核工程导论——用户空间设备管理

用户空间设备管理 用户空间所能见到的所有设备都放在/dev目录下(当然,只是一个目录,是可以变化的),文件系统所在的分区被当成一个单独的设备也放在该目录下.以前的2.4版本的曾经出现过devfs,这个思路非常好,在内核态实现对磁盘设备的动态管理.可以做到当用户访问一个设备的设备的时候,devfs驱动才会去加载该设备的驱动.甚至每个节点的设备号都是动态获得的.但是该机制的作者不再维护他的代码,linux成员经过讨论,使用用户态的udev代替内核态的devfs,所以现在的devfs已经废弃了.用户态

Linux 内核空间与用户空间

本文以 32 位系统为例介绍内核空间(kernel space)和用户空间(user space). 内核空间和用户空间 对 32 位操作系统而言,它的寻址空间(虚拟地址空间,或叫线性地址空间)为 4G(2的32次方).也就是说一个进程的最大地址空间为 4G.操作系统的核心是内核(kernel),它独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限.为了保证内核的安全,现在的操作系统一般都强制用户进程不能直接操作内核.具体的实现方式基本都是由操作系统将虚拟地址空间划分

内核空间和用户空间的分界 PAGE_OFFSET

PAGE_OFFSET 首先看看PAGE_OFFSET的功能 内存映射 |            用户空间                  |   内核空间   | |——————+——————+——————+———————| 物理 A:0        1G                         B:3G          C:4G B: 定义为    PAGE_OFFSET 0-1G: 和内核空间又有丰富的内容,我还没有整理,以后再说. ---------------------

内核空间、用户空间和虚拟地址(转)

原文:http://www.cnblogs.com/yanhaidong/archive/2011/02/11/2339050.html IO是基于缓存区来做的,所谓的输入和输出就是从缓存区中移入和移出数据.以IO输入为例,首先是用户空间进程向内核请求某个磁盘空间数据,然后内核将磁盘数据读取到内核 空间的buffer中,然后用户空间的进程再将内核空间buffer中的数据读取到自身的buffer中,然后进程就可以访问使用这些数据. 内核空间是指操作系统内核运行的空间,是为了保证操作系统内核的能够安

内核空间与用户空间

首先,这个概念的由来,我认为跟CPU的发展有很大关系,在目前CPU的保护模式下,系统需要对其赖以运行的资料进行保护,为了保证操作系统内核资料,我们把内存空间进行划分,一部分为操作系统内核运行的空间,另一部分是应用程序运行的空间,所谓空间就是内存的地址.因此内核空间和用户空间的概念就出现了.在386以前的CPU实模式下,操作系统内核与用户程序的内存空间是不做区分的,也就不存在内核空间和用户空间的说法了.其次,CPU的保护模式的一个重大特点,也就是硬件直接支持的内存访问模式,虚拟地址空间到物理地址空

Linux内核工程导论——用户空间进程使用内核资源

本文大部分转载和组装,只是觉得这些知识应该放到一起比较好. 进程系统资源的使用原理 大部分进程通过glibc申请使用内存,但是glibc也是一个应用程序库,它最终也是要调用操作系统的内存管理接口来使用内存.大部分情况下,glibc对用户和操作系统是透明的,所以直接观察操作系统记录的进程对内存的使用情况有很大的帮助.但是glibc自己的实现也是有问题的,所以太特殊情况下追究进程的内存使用也要考虑glibc的因素.其他操作系统资源使用情况则可以直接通过proc文件系统查看. 进程所需要的系统资源种类

内核态和用户态,内核空间和用户空间

内核态与用户态是操作系统的两种运行级别,intel cpu提供Ring0-Ring3三种级别的运行模式.Ring0级别最高,Ring3最低 内核态可以拥有比用户态更大的权限 处于内核态的进程,可以访问用户进程空间(是虚拟地址空间),就是通过进程的页表(进程本身就是一个4G虚拟地址空间.其中用户空间的3G是独立的,内核空间是共享的)来访问用户地址空间对应的物理地址,从而访问用户空间 相反用户态的进程,只能访问用户地址空间(虚拟地址空间) 在内核态下,利用内核地址空间中的高端内存地址空间,来映射高端

虚拟内存_内核空间_用户空间

转自:http://blog.sina.com.cn/s/blog_65373f1401019f49.html 转载自解惑-Linux内核空间 Linux虚拟内存的大小为2^32(在32位的x86机器上),内核将这4G字节的空间分为两部分.最高的1G字节(从虚地址0xC0000000到0xFFFFFFFF)供内核使用,称为“内核空间”.而较低的3G字节(从虚地址0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间”.因为每个进程可以通过系统调用进入内核,因此,Linux内