Linux kernel 3.10 sg 驱动分析

源码地址

https://elixir.bootlin.com/linux/v3.10/source/drivers/scsi/sg.c

主设备号

https://elixir.bootlin.com/linux/v3.10/source/include/uapi/linux/major.h#L40

#define SCSI_GENERIC_MAJOR  21

file operations

此结构定义了sg的read write ioctl的具体实现

static const struct file_operations sg_fops = {
    .owner = THIS_MODULE,
    .read = sg_read,
    .write = sg_write,
    .poll = sg_poll,
    .unlocked_ioctl = sg_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl = sg_compat_ioctl,
#endif
    .open = sg_open,
    .mmap = sg_mmap,
    .release = sg_release,
    .fasync = sg_fasync,
    .llseek = no_llseek,
};

模块初始化 init_sg

将sg_fops和主设备号关联起来

static int __init
init_sg(void)
{
    int rc;

    if (scatter_elem_sz < PAGE_SIZE) {
        scatter_elem_sz = PAGE_SIZE;
        scatter_elem_sz_prev = scatter_elem_sz;
    }
    if (def_reserved_size >= 0)
        sg_big_buff = def_reserved_size;
    else
        def_reserved_size = sg_big_buff;
    /* 注册一个字符设备驱动 , 主设备号为21 */
    rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), 
                    SG_MAX_DEVS, "sg");
    if (rc)
        return rc;
        sg_sysfs_class = class_create(THIS_MODULE, "scsi_generic");
        if ( IS_ERR(sg_sysfs_class) ) {
        rc = PTR_ERR(sg_sysfs_class);
        goto err_out;
        }
    sg_sysfs_valid = 1;
    rc = scsi_register_interface(&sg_interface);
    if (0 == rc) {
#ifdef CONFIG_SCSI_PROC_FS
        sg_proc_init();
#endif              /* CONFIG_SCSI_PROC_FS */
        return 0;
    }
    class_destroy(sg_sysfs_class);
err_out:
    unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS);
    return rc;
}

sg为设备创建的文件/dev/sg0主设备号为21, 当使用open打开/dev/sg0时,我们调用ioctl(fd, SG_IO, &hdr)最终会调用到sg_ioctl(通过主设备号和fops结构体的关联找到)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值