1. 程式人生 > >Linux kernel 3.10 sg 驅動分析

Linux kernel 3.10 sg 驅動分析

原始碼地址

主裝置號

#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結構體的關聯找到)