linux 将外设抽象为 /dev 下的文件,通过统一的文件读写接口访问外设

linux与外设通信:

  • I/O 端口:通过 I/O 读写访问设备
  • I/O 内存映射:对 I/O 端口进行内存映射,将外设地址映射到内存地址,PCI 总线寻址通过内存映射完成
  • 中断

设备访问:
分为块设备/字符型设备
ls -alh /dev
2022-09-22T07:19:59.png

块设备权限首位为 b
字符设备权限首位 c
目录首位 d
链接首位 l

用户,组 后面两个数字为 主设备号,从设备号
主设备对应一个驱动程序,其下若干从设备由该驱动程序管理
查找驱动根据设备类型(块设备/字符设备)+设备主编号定位驱动
主从设备号 唯一对应一个设备

关于 linux 中 /dev/null:

/* drivers/char/mem.c */
static const struct file_operations null_fops = {
    .llseek        = null_lseek,
    .read        = read_null,
    .write        = write_null,
    .read_iter    = read_iter_null,
    .write_iter    = write_iter_null,
    .splice_write    = splice_write_null,
};
static ssize_t read_null(struct file *file, char __user *buf,
             size_t count, loff_t *ppos)
{
    return 0;
}

static ssize_t write_null(struct file *file, const char __user *buf,
              size_t count, loff_t *ppos)
{
    return count;
}

static ssize_t read_iter_null(struct kiocb *iocb, struct iov_iter *to)
{
    return 0;
}

ioctl

用户通过 ioctl 向 driver 发送设备操作

static long my_ioctl (struct file *file, unsigned int cmd, unsigned long arg);

arg 请求参数
cmd 32位 记录请求:

  • bit31-30 dir : 区别读写请求,_IOC_NONE无数据传输,_IOC_READ读, _IOC_WRITE写,_IOC_READ | _IOC_WRITE 双向
  • bit29-16 size : arg 部分大小
  • bit15-8 type : magic number,定义于 Documentation/ioctl/ioctl-number.txt
  • bit7-0 nr : 命令序号

linux kernel 定义了宏 _IOC(dir, type, nr, size) 用于转换 cmd

其他辅助宏:
_IO(type, nr) : _IOC(_IOC_NONE,(type),(nr),0) 无数据传输情况
_IOR(type, nr, type_of_data), _IOW(type, nr, type_of_data), _IOWR(type, nr, type_of_data) ,注意第三个参数为 arg 变量类型而非 size

标签: none

添加新评论